Initial commit

master
Avril 5 years ago
commit 52f831c3b9

@ -0,0 +1,23 @@
SOURCE:= src/*.c
TEST_SOURCE:= src/test/*.c
INCLUDE:= include/
CFLAGS:= -Wall --std=gnu99
OBJ:= obj
BUILD:= build
LFLAGS:= -L./$(BUILD) -lse
all: clean libse test
clean:
rm -f $(BUILD)/*
rm -f $(OBJ)/*
libse:
gcc -c $(SOURCE) -I$(INCLUDE) $(CFLAGS)
mv *.o $(OBJ)/
ar rcs $(BUILD)/$@.a $(OBJ)/*.o
ranlib $(BUILD)/$@.a
test:
gcc $(TEST_SOURCE) -I$(INCLUDE) $(CFLAGS) -o $(BUILD)/$@ $(LFLAGS)
$(BUILD)/$@

@ -0,0 +1,30 @@
/* Simple extendable string.
* I think this doesn't leak?
*/
#ifndef _EXSTRING_H
#define _EXSTRING_H
#include <stddef.h>
typedef struct {
size_t currentSize;
char cstr[];
} exStringOpt;
typedef char* exString;
#define EXS(s) (* (char**)(s))
exString* exs_new(const char* from);
exString* exs_clone(exString* from);
void exs_free(exString* str);
void exs_nappend(exString* str, const char* from, size_t length);
void exs_append(exString* str, const char* from);
void exs_appendf(exString* str, const char* fmt, ...);
size_t exs_realsize(exString* str);
void exs_reduce(exString* str, size_t by);
void exs_appendtimes(exString* str, char c, int times);
void exs_recalc(exString* str);
void exs_reset(exString * str);
#endif /* _EXSTRING_H */

@ -0,0 +1,27 @@
#ifndef _LIBSE_H
#define _LIBSE_H
#include <stdio.h>
typedef struct {
void* ptr;
int size;
int alloced;
int sexpr;
} car_t;
typedef struct cons {
union {
void* ptr;
car_t car;
};
struct cons* cdr;
} list_t;
//TODO: String quoting & escaping.
list_t* se_parse(const char* sexpr); //Parse string into list.
void se_free(list_t* list); //Free whole list.
void se_print(FILE* fp, const list_t* list); //Print list to fp, if fp is NULL, print to stdout.
#endif /* _LIBSE_H */

@ -0,0 +1,150 @@
#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);
}

@ -0,0 +1,123 @@
#include <stdlib.h>
#include <string.h>
#include <libse.h>
#include <internal/exstring.h>
static void _addcar(list_t* out, exString* token)
{
#ifdef SE_PARSE_NIL
if(strcmp(EXS(token), "nil")==0)
out->ptr = NULL;
else {
#endif
out->ptr = strdup(EXS(token));
out->car.size = strlen(out->ptr);
out->car.alloced = 1;
exs_reset(token);
#ifdef SE_PARSE_NIL
}
#endif
}
static list_t* _parse_list(const char* sexpr, int* lp)
{
list_t* out = malloc(sizeof(list_t));
memset(out,0,sizeof(list_t));
exString *token = exs_new(NULL);
while(*sexpr) {
if(*sexpr==' ') {
if(strlen(EXS(token))>0) {
_addcar(out, token);
if(*(sexpr+1))
out->cdr = _parse_list(sexpr, lp);
else out->cdr =NULL;
break;
}
}
else if(*sexpr == ')')
{
_addcar(out, token);
out->cdr=NULL;
(*lp)+=1;
break;
}
else if(*sexpr == '(')
{
int hp =0;
list_t* nc = _parse_list(sexpr+1, &hp);
out->ptr = nc;
out->car.alloced=1;
out->car.sexpr=1;
out->car.size = sizeof(list_t);
sexpr+= hp+1;
(*lp) += hp+1;
if(*(sexpr))
out->cdr = _parse_list(sexpr, lp);
else out->cdr =NULL;
break;
}
else
exs_nappend(token, sexpr, 1);
sexpr+=1;
(*lp)+=1;
}
if(strlen(EXS(token))>0)
_addcar(out, token);
else if(!out->ptr && !out->cdr) {
free(out);
out=NULL;
}
exs_free(token);
return out;
}
list_t* se_parse(const char* str)
{
int lp=0;
return _parse_list(str,&lp);
}
void _list_tostring(exString *out, const list_t* list)
{
if(!list->ptr)
exs_append(out, "nil");
else if(list->car.sexpr) {
exs_append(out, "(");
_list_tostring(out, (list_t*)list->ptr);
}
else exs_append(out,(char*)list->ptr);
if(list->cdr)
{
exString *wtf = exs_new(NULL);
_list_tostring(wtf, list->cdr);
if(EXS(wtf)[0]!=')')
exs_append(out, " ");
exs_append(out, EXS(wtf));
exs_free(wtf);
}
else exs_append(out, ")");
}
void se_print(FILE* fp, const list_t* list)
{
if(fp == NULL) fp = stdout;
exString* str = exs_new("(");
_list_tostring(str, list);
fprintf(fp, "%s", EXS(str));
exs_free(str);
}
void se_free(list_t* list)
{
if(list->cdr) se_free(list->cdr);
if(list->ptr && list->car.alloced)
free(list->ptr);
free(list);
}

@ -0,0 +1,58 @@
#include <libse.h>
#include <stdio.h>
#include <string.h>
#include <internal/exstring.h>
void test_exs()
{
exString *test= exs_new(NULL);
printf("New success\n");
exs_append(test, "Hello");
exs_append(test, " world.");
exs_append(test, " Test, ");
exs_append(test, "two, three. FOUR FIVE.");
exs_reduce(test, 5);
EXS(test)[strlen(EXS(test))-5] = 0;
exs_recalc(test);
exs_append(test, " Scream: ");
exs_appendtimes(test, 'A', 6);
exs_appendf(test, "\nCurrent size: %d -> %d", strlen(EXS(test)), exs_realsize(test));
exs_appendf(test, "AOISDJOAIJS%s", "sokdok");
printf("%s\n", EXS(test));
printf("strlen() %d, ->currentSize %d\n", strlen(EXS(test)), exs_realsize(test));
exs_free(test);
}
void test_parse()
{
const char* parse = "hello (there (firend) (i) (love (you a lot))) how are (you (doing today?))";
list_t* list = se_parse(parse);
printf("Parse okay\n");
se_print(NULL, list);
printf("\n");
// printf("(car list) -> %s\n", (char*)list->ptr);
// printf("(cadr list) -> %s\n", (list->cdr?(char*)list->cdr->ptr:"nil"));
se_free(list);
}
int main()
{
// test_exs();
test_parse();
return 0;
}
Loading…
Cancel
Save