Initial commit
This commit is contained in:
141
src/dstr.c
Normal file
141
src/dstr.c
Normal file
@@ -0,0 +1,141 @@
|
||||
#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));
|
||||
}
|
||||
Reference in New Issue
Block a user