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
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);
|
|
}
|