You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
2.9 KiB

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <internal/exstring.h>
#define min(x,y) ((x)<(y)?(x):(y))
#define ceil(x, to) \
((((x) + (to) - 1) / (to)) * (to))
#define GETOPT(str) ((exStringOpt*) (((byte*)*(str))-sizeof(exStringOpt)))
typedef unsigned char byte;
exString* exs_new(const char* from)
{
if(from&&!from[0]) return exs_new(NULL);
size_t deflen = (!from?0:strlen(from))+1;
exStringOpt *tr = malloc(sizeof(exStringOpt) + deflen);
memset(tr,0,sizeof(exStringOpt) +deflen);
tr->currentSize = deflen;
if(from) strncpy(tr->cstr, from, deflen-1);
else tr->cstr[0] = 0;
exString *ret = malloc(sizeof(exString));
*ret = (exString)tr->cstr;
return ret;
}
void exs_free(exString* str)
{
exStringOpt *opt = GETOPT(str);
free(opt);
free(str);
}
static char* _exs_extend(exString* str, size_t to)
{
exStringOpt *opt = GETOPT(str);
assert(to>opt->currentSize);
opt = realloc(opt, sizeof(exStringOpt)+to);
memset(opt->cstr+opt->currentSize, 0, to-opt->currentSize);
size_t oldSize = opt->currentSize;
opt->currentSize= to;
*str = opt->cstr;
return opt->cstr+oldSize;
}
void exs_nappend(exString* str, const char* from, size_t length)
{
size_t beflen = GETOPT(str)->currentSize-1;
size_t addlen = length;
if(addlen<1) return;
char *cpit = _exs_extend(str, beflen+addlen+1);
strncpy(cpit-1, from, addlen);
}
size_t exs_realsize(exString* str)
{
return GETOPT(str)->currentSize;
}
void exs_append(exString* str, const char* from)
{
return exs_nappend(str, from, strlen(from));
}
exString* exs_clone(exString* str)
{
return exs_new(*str);
}
void exs_appendf(exString* str, const char* fmt, ...)
{
va_list va;
va_start(va, fmt);
size_t sz = vsnprintf(NULL, 0, fmt, va);
char buf[sz+2];
buf[sz+1]=0;
vsnprintf(buf, sz+1, fmt, va);
va_end(va);
exs_nappend(str, buf, sz);
}
void exs_reduce(exString *str, size_t sz)
{
exStringOpt *opt = GETOPT(str);
if(opt->currentSize-sz<0) exs_reduce(str, opt->currentSize);
else if(opt->currentSize-sz==0) {
opt = realloc(opt, sizeof(exStringOpt)+1);
opt->cstr[0] = 0;
opt->currentSize = 1;
*str = opt->cstr;
}
else {
size_t ns = opt->currentSize-sz;
opt = realloc(opt, sizeof(exStringOpt)+ns);//+1 is already in currentSize;
opt->cstr[ns-1] = 0;
opt->currentSize = ns;
*str = opt->cstr;
}
}
void exs_appendtimes(exString *str, char c, int times)
{
if(!times) return;
else if(times==1) exs_nappend(str, &c, 1);
else {
char* buf = _exs_extend(str, GETOPT(str)->currentSize+times);
memset(buf-1, (byte)c, times);
}
}
void exs_recalc(exString* str)
{
register int i=0;
int pos =-1;
for(;i<GETOPT(str)->currentSize;i++)
if(!EXS(str)[i]) { pos = i; break; }
if(pos<0 || pos == GETOPT(str)->currentSize-1) return;
else
exs_reduce(str, GETOPT(str)->currentSize-pos);
}
void exs_reset(exString *str)
{
exs_reduce(str, GETOPT(str)->currentSize);
}