nctref/src/dstr.c
2023-08-27 19:48:06 +03:00

142 lines
2.6 KiB
C

#include"dstr.h"
#include<stdarg.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
static int ilen(int i) {
if(i == 0) return 1;
int ret = 0;
if(i < 0) {
ret = 1;
i = -i;
}
while(i > 0) {
ret++;
i = i / 10;
}
return ret;
}
static char *myitoa(int src) {
static char ret[12];
snprintf(ret, 12, "%i", src);
return ret;
}
typedef struct {
size_t length;
char data[];
} dstrInternal;
dstr dstrempty() {
dstrInternal *i = malloc(sizeof(dstrInternal) + 1);
i->length = 0;
i->data[0] = '\0';
return (dstr) i + sizeof(dstrInternal);
}
dstr dstrz(const char *src) {
size_t len = strlen(src);
dstrInternal *i = malloc(sizeof(dstrInternal) + len + 1);
i->length = len;
memcpy(i->data, src, len + 1);
return (dstr) i + sizeof(dstrInternal);
}
dstr dstrfmt(dstr original, const char *fmt, ...) {
dstrInternal *originalInternal = (dstrInternal*) (original - sizeof(dstrInternal));
const char *start = fmt;
va_list list;
va_start(list, fmt);
size_t totalLength = 0;
while(*fmt) {
if(*fmt == '%') {
switch(*++fmt) {
case 's':
totalLength += strlen(va_arg(list, char*));
break;
case 'c':
if(va_arg(list, int)) totalLength++;
break;
case 'S': {
dstrInternal *i = (dstrInternal*) (va_arg(list, dstr) - sizeof(dstrInternal));
totalLength += i->length;
break;
}
case 'i':
totalLength += ilen(va_arg(list, int));
break;
default: {
totalLength++;
}
}
} else totalLength++;
fmt++;
}
va_end(list);
fmt = start;
originalInternal = realloc(originalInternal, sizeof(dstrInternal) + originalInternal->length + totalLength + 1);
va_start(list, fmt);
char *dst = originalInternal->data + originalInternal->length;
originalInternal->length += totalLength;
originalInternal->data[originalInternal->length] = 0;
while(*fmt) {
if(*fmt == '%') {
switch(*++fmt) {
case 's': {
char *asdfasdf = va_arg(list, char*);
strcpy(dst, asdfasdf);
dst += strlen(asdfasdf);
break;
}
case 'c': {
int c = va_arg(list, int);
if(c) {
*(dst++) = c;
}
break;
}
case 'S': {
dstrInternal *i = (dstrInternal*) (va_arg(list, dstr) - sizeof(dstrInternal));
memcpy(dst, i->data, i->length);
dst += i->length;
break;
}
case 'i': {
const char *asdf = myitoa(va_arg(list, int));
strcpy(dst, asdf);
dst += strlen(asdf);
break;
}
default: {
*(dst++) = *fmt;
}
}
} else {
*(dst++) = *fmt;
}
fmt++;
}
va_end(list);
return (dstr) originalInternal + sizeof(dstrInternal);
}
void dstrfree(dstr s) {
free(s - sizeof(dstrInternal));
}