diff -ur v9/Makefile v10/Makefile --- v9/Makefile 2018-09-06 02:13:01.000000000 +0900 +++ v10/Makefile 2018-09-07 23:03:17.000000000 +0900 @@ -3,8 +3,9 @@ CFLAGS += -g OBJS = ezyaml.o objs.o +TARG = ezyaml -all: ezyaml +all: $(TARG) ezyaml: $(OBJS) gcc $(CFLAGS) -o $@ $(OBJS) @@ -12,5 +13,6 @@ clean: rm -f *.o *~ *.pyc rm -rf __pycache__ + rm -f $(TARG) # EOF diff -ur v9/ezyaml.c v10/ezyaml.c --- v9/ezyaml.c 2018-09-06 02:13:01.000000000 +0900 +++ v10/ezyaml.c 2018-09-07 23:45:13.000000000 +0900 @@ -1,5 +1,48 @@ #include "objs.h" +#define DBG_(...) fprintf(stderr, __VA_ARGS__) +#define DBG(...) do{ DBG_(__VA_ARGS__); DBG_("\n"); }while(0) + +char * +cp_add(char *a, char *b) +{ + char *r = malloc( strlen(a) + strlen(b) + 1 ); + + strcpy(r, a); + free(a); /* ! */ + + strcat(r, b); + free(b); /* ! */ + + return r; +} + +char * +cp_replace(char *s, char *from, char *to) +{ + char *bak = s, *t, *r = strdup(""); + + while( ( t = strstr(s, from) ) != NULL ){ + if(t > s){ + r = cp_add( r, strndup(s, t-s) ); + } + r = cp_add( r, strdup(to) ); + s = t + strlen(from); + } + r = cp_add(r, s); + free(bak); /* ! */ + return r; +} + +/**/ + +void +err(char *t, char *s) +{ + fprintf(stderr, "err %s \"%s\"\n", t, s); + exit(1); +} + static struct obj * lines_dump_sub(struct obj *str) { @@ -29,6 +72,21 @@ return c == '"' || c == '\''; } +char *kwd_true[] = { "True", "true", "TRUE", "ON", "On", "On", NULL }; +char *kwd_false[] = { "False", "false", "FALSE", "OFF", "Off", "off", NULL }; + +int +is_any_str(char *s, char **ss) +{ + while(*ss){ + if( strcmp(s, *ss) == 0 ){ + return 1; + } + ss++; + } + return 0; +} + struct obj * parse_append(struct obj *buf, int c) { @@ -126,15 +184,7 @@ struct obj * cut_tail_spc(struct obj *str) { - char *s = obj_buf(str); - while(1){ - char *t = s + strlen(s) - 1; - if(*t != ' ' && *t != '\t'){ - str->buf_n = strlen(s) + 1; - break; - } - *t = '\0'; - } + str_trunc(str); return NULL; } @@ -151,18 +201,95 @@ *kind = get_kind( slice_tail(s, *idt) ); } +struct obj *get_dict(int idt, struct obj *lines); +struct obj *get_list(int idt, struct obj *lines); +struct obj *get_other(int idt, struct obj *lines); +struct obj *get_value(char *s); +struct obj *get(int idt, int kind, struct obj *lines); +struct obj *get_cont_str(int idt, struct obj *lines); + +struct obj * +get_dict_v(int idt, struct obj *lines) +{ + char *s = lines_top_str(lines); + int idt_, kind_; + void *vp; + + get_idt_kind(s, &idt_, &kind_); + + if(kind_ == OBJ_TYP_DICT){ + if(idt_ == idt+2){ + return get_dict(idt_, lines); + }else if(idt_ > idt){ + err("indent dict", s); + } + }else if(kind_ == OBJ_TYP_LIST){ + if(idt_ == idt+2 || idt_ == idt){ + return get_list(idt_, lines); + }else if(idt_ > idt){ + err("indent list", s); + } + }else{ + if(idt_ == idt+2){ + return get_other(idt_, lines); + }else if(idt_ >= idt){ + err("indent other", s); + } + } + vp = NULL; + return obj_new(OBJ_TYP_PTR, &vp, 0); +} + struct obj * get_dict(int idt, struct obj *lines) { - // ... - return NULL; + struct obj *str = list_pop_top(lines); + char *s = obj_buf(str); + int idx = find_colon_idx(s); + + struct obj *sk = str_new_n(s, idx); + struct obj *sv = str_new( slice_tail(s, idx+1) ); + struct obj *k, *v; + struct obj *dic = dict_new(); + + obj_del(str); + + sk = str_strip(sk); + k = get_value( obj_buf(sk) ); + obj_del(sk); + + sv = str_strip(sv); + v = get_value( obj_buf(sv) ); + obj_del(sv); + + if(v->typ == OBJ_TYP_PTR && v->any.p == NULL){ + if( list_len(lines) ){ + v = get_dict_v(idt, lines); + } + }else if(v->typ == OBJ_TYP_STR){ + struct obj *add = get_cont_str(idt, lines); + v = str_append( v, obj_buf(add) ); + obj_del(add); + } + + dict_add(dic, k, v); + if( list_len(lines) ){ + char *s = lines_top_str(lines); + int idt_, kind_; + get_idt_kind(s, &idt_, &kind_); + if(kind_ == OBJ_TYP_DICT && idt_ == idt){ + struct obj *add = get_dict(idt, lines); + while( dict_len(add) ){ + dict_add_lst_kv( dic, dict_pop_top(add) ); + } + } + } + return dic; } struct obj * get_list(int idt, struct obj *lines) { - struct obj *get(int idt, int kind, struct obj *lines); - int idt_ = idt + 2; char *s = lines_top_str(lines); int kind_ = get_kind( slice_tail(s, idt_) ); @@ -189,8 +316,56 @@ struct obj * get_value(char *s) { - // ... - return NULL; + int i; + double d; + char *e; + struct obj *obj, *lst, *str; + + if(*s == '\0'){ + void *vp = NULL; + return obj_new(OBJ_TYP_PTR, &vp, 0); + } + + i = (int) strtol(s, &e, 10); + if(*e == '\0'){ + return obj_new(OBJ_TYP_INT, &i, 0); + } + d = strtod(s, &e); + if(*e == '\0'){ + return obj_new(OBJ_TYP_DOUBLE, &d, 0); + } + + if( is_any_str(s, kwd_true) ){ + i = 1; + return obj_new(OBJ_TYP_BOOL, &i, 0); + } + if( is_any_str(s, kwd_false) ){ + i = 0; + return obj_new(OBJ_TYP_BOOL, &i, 0); + } + if( strcmp(s, "null") == 0 ){ + void *vp = NULL; + return obj_new(OBJ_TYP_PTR, &vp, 0); + } + if( strcmp(s, "[]") == 0 ){ + return list_new(); + } + if( strcmp(s, "{}") == 0 ){ + obj = list_new(); + obj->typ = OBJ_TYP_DICT; /* ! */ + return obj; + } + + lst = parse(s); + if( list_len(lst) == 1 && is_qts(*s) ){ + str = str_new(s+1); + s = obj_buf(str); + s[ strlen(s) - 1 ] = '\0'; + str->buf_n = strlen(s) + 1; + return str; + } + + return str_new(s); } struct obj * @@ -205,19 +380,17 @@ int typ = v->typ; if( ( typ == OBJ_TYP_STR && strlen( obj_buf(v) ) ) || ( typ == OBJ_TYP_INT || typ == OBJ_TYP_DOUBLE ) ){ - ; struct obj *str = list_pop_top(lines); char *s = slice_tail( obj_buf(str), idt ); struct obj *add = get_cont_str(idt, lines); struct obj *ret = str_new(" "); - str_append(ret, s); - str_append( ret, obj_buf(add) ); + ret = str_append(ret, s); + ret = str_append( ret, obj_buf(add) ); obj_del(str); obj_del(add); return ret; } - } } return str_new(""); @@ -226,7 +399,8 @@ struct obj * get_other(int idt, struct obj *lines) { - char *s = lines_top_str(lines); + struct obj *str = list_pop_top(lines); + char *s = obj_buf(str); struct obj *v = get_value( slice_tail(s, idt) ); if(v->typ == OBJ_TYP_STR){ struct obj *add = get_cont_str(idt+2, lines); @@ -279,17 +453,14 @@ list_filter(lines, is_not_empty, lst_trash); list_del(lst_trash); - lines_dump(lines); - objs = list_new(); -#if 0 + while( list_len(lines) ){ int idt, kind; get_idt_kind( obj_buf( list_top(lines) ), &idt, &kind ); obj = get(idt, kind, lines); list_append(objs, obj); } -#endif obj_del(lines); @@ -301,10 +472,181 @@ return obj; } +/**/ + +struct obj *dump_list(struct obj *lst, int idt); +struct obj *dump_value(struct obj *obj); +struct obj *dump_other(struct obj *obj, int idt); +struct obj *dump_obj(struct obj *obj, int idt); + +struct obj * +dump_dict(struct obj *dic, int idt) +{ + struct obj *lines = list_new(); + struct obj *str, *tmp; + struct obj *lst_kv = dict_top_lst_kv(dic); + int n = dict_len(dic), i; + + for(i=0; inext; + + str = str_append( dump_other(k, idt), ":" ); + + if( v->typ == OBJ_TYP_LIST && list_len(v) ){ + list_append(lines, str); + str = dump_list(v, idt); + }else if( v->typ == OBJ_TYP_DICT && dict_len(v) ){ + list_append(lines, str); + str = dump_dict(v, idt+2); + }else{ + str = str_append(str, " "); + tmp = dump_value(v); + str = str_append( str, obj_buf(tmp) ); + obj_del(tmp); + } + list_append(lines, str); + + lst_kv = lst_kv->next; + } + + str = lines_join(lines, "\n"); + obj_del(lines); + return str; +} + +struct obj * +dump_list(struct obj *lst, int idt) +{ + struct obj *lines = list_new(); + struct obj *str; + struct obj *e = list_top(lst); + int n = list_len(lst), i; + + for(i=0; inext; + } + + str = lines_join(lines, "\n"); + obj_del(lines); + return str; +} + +int +need_quote(char *s) +{ + char h, t; + + if( *s == '\0' || is_any_str(s, kwd_true) || is_any_str(s, kwd_false) ){ + return 1; + } + + h = *s; + t = s[ strlen(s)-1 ]; + if( (h == '[' && t == ']') || (h == '{' && t == '}') ){ + return 1; + } + return 0; +} + +int +is_not_same_str(char *s, struct obj *obj) +{ + struct obj *v = get_value(s); + int r = !obj_eq(v, obj); + obj_del(v); + return r; +} + +struct obj * +dump_value(struct obj *obj) +{ + if(obj->typ == OBJ_TYP_STR){ + struct obj *str; + char *s = strdup( obj_buf(obj) ); + int q2 = strchr(s, '"') != NULL; + int q1 = strchr(s, '\'') != NULL; + int cl = strchr(s, ':') != NULL; + + if(q2 && q1){ + s = cp_replace(s, "'", "\\'"); + q1 = 0; + } + if(q2 || q1 || cl || is_not_same_str(s, obj) || need_quote(s) ){ + char *qt = q1 ? "\"" : "'"; + s = cp_add( strdup(qt), s ); + s = cp_add( s, strdup(qt) ); + } + str = str_new(s); + free(s); + return str; + } + if(obj->typ == OBJ_TYP_LIST){ + return str_new("[]"); + } + if(obj->typ == OBJ_TYP_DICT){ + return str_new("{}"); + } + if(obj->typ == OBJ_TYP_PTR && obj->any.p == NULL){ + return str_new("null"); + } + + if(obj->typ == OBJ_TYP_BOOL){ + return str_new(obj->any.i ? "True" : "False"); + } + if(obj->typ == OBJ_TYP_INT){ + char buf[1024]; + sprintf(buf, "%d", obj->any.i); + return str_new(buf); + } + if(obj->typ == OBJ_TYP_DOUBLE){ + char buf[1024]; + sprintf(buf, "%g", obj->any.d); + return str_new(buf); + } + return str_new(""); /* ! */ +} + +struct obj * +dump_other(struct obj *obj, int idt) +{ + struct obj *str = dump_value(obj); + char *s = malloc(idt+1); + memset(s, ' ', idt); + s[idt] = '\0'; + + s = cp_add( s, strdup( obj_buf(str) ) ); + obj_del(str); + return str_new(s); +} + +struct obj * +dump_obj(struct obj *obj, int idt) +{ + int t = obj->typ; + if( t == OBJ_TYP_DICT && dict_len(obj) ){ + return dump_dict(obj, idt); + } + if( t == OBJ_TYP_LIST && list_len(obj) ){ + return dump_list(obj, idt); + } + return dump_other(obj, idt); +} + struct obj * dump(struct obj *obj) { - return str_new("foo: bar\n"); /* ... */ + return str_append( dump_obj(obj, 0), "\n" ); } int diff -ur v9/objs.c v10/objs.c --- v9/objs.c 2018-09-06 02:13:01.000000000 +0900 +++ v10/objs.c 2018-09-07 23:07:30.000000000 +0900 @@ -176,8 +176,12 @@ obj->buf_sz = OBJ_TYP_BASE(typ) == OBJ_TYP_BUF ? req_sz : 0; obj->buf_n = 0; if(vp && req_sz > 0){ - memcpy(&obj->any, vp, req_sz); - obj->buf_n = req_sz; + int n = req_sz; + if(typ == OBJ_TYP_STR && strlen(vp) + 1 < n){ + n = strlen(vp) + 1; + } + memcpy(&obj->any, vp, n); + obj->buf_n = n; } } @@ -220,6 +224,55 @@ return obj->any.buf; } +int +obj_eq(struct obj *a, struct obj *b) +{ + int bs_typ; + + if(a->typ != b->typ){ + return 0; + } + + bs_typ = OBJ_TYP_BASE(a->typ); + + if(bs_typ == OBJ_TYP_INT){ + return a->any.i == b->any.i; + } + if(bs_typ == OBJ_TYP_DOUBLE){ + return a->any.d == b->any.d; + } + if(bs_typ == OBJ_TYP_PTR){ + return a->any.p == b->any.p; + } + if(a->typ == OBJ_TYP_STR){ + return strcmp( obj_buf(a), obj_buf(b) ) == 0; + } + if(bs_typ == OBJ_TYP_BUF){ + if(a->buf_n != b->buf_n){ + return 0; + } + return memcmp( obj_buf(a), obj_buf(b), a->buf_n ) == 0; + } + if(bs_typ == OBJ_TYP_OBJS){ + /* same order ! */ + int i, n; + if(a->any.objs.n != b->any.objs.n){ + return 0; + } + n = a->any.objs.n; + a = a->any.objs.top; + b = b->any.objs.top; + for(i=0; i 0){ + bufs_append(&bufs, buf, n); + } + if(add_sz > 0){ + bufs_append(&bufs, NULL, add_sz); + } + obj = bufs_join(&bufs); + obj->buf_n -= add_sz; + bufs_fini(&bufs); + return obj; +} + +struct obj * buf_append(struct obj *buf, void *vp, int sz) { char *dst; @@ -259,50 +332,77 @@ return buf_append( buf, s, strlen(s)+1 ); } +/**/ + struct obj * -buf_read(FILE *fp, int add_sz) +str_new(char *s) { - char buf[4096]; - struct obj bufs, *obj; - int n; + return obj_new(OBJ_TYP_STR, s, 0); +} - bufs_init(&bufs); - while((n = fread(buf, 1, sizeof(buf), fp)) > 0){ - bufs_append(&bufs, buf, n); - } - if(add_sz > 0){ - bufs_append(&bufs, NULL, add_sz); - } - obj = bufs_join(&bufs); - obj->buf_n -= add_sz; - bufs_fini(&bufs); - return obj; +struct obj * +str_new_n(char *s, int n) +{ + struct obj *str = obj_new(OBJ_TYP_STR, NULL, n+1); + char *d = obj_buf(str); + memcpy(d, s, n); + d[n] = '\0'; + return str; } -/**/ +struct obj * +str_new_sz(int sz) +{ + return obj_new(OBJ_TYP_STR, NULL, sz); +} struct obj * -str_new(char *s) +str_read(FILE *fp) { - return obj_new(OBJ_TYP_STR, s, 0); + struct obj *str = buf_read(fp, 1); + char c = '\0'; + buf_append(str, &c, 1); + str->typ = OBJ_TYP_STR; /* ! */ + return str; } struct obj * str_append(struct obj *str, char *s) { str->typ = OBJ_TYP_BUF; /* ! */ + str->buf_n = strlen( obj_buf(str) ); str = buf_append_str(str, s); str->typ = OBJ_TYP_STR; /* ! */ return str; } +void +str_trunc(struct obj *str) +{ + char *s = obj_buf(str); + char *t = &s[ strlen(s)-1 ]; + + while(*t == ' ' || *t == '\t'){ + *t-- = '\0'; + str->buf_n--; + } +} + struct obj * -str_read(FILE *fp) +str_strip(struct obj *str) { - struct obj *str = buf_read(fp, 1); - char c = '\0'; - buf_append(str, &c, 1); - str->typ = OBJ_TYP_STR; /* ! */ + char *s = obj_buf(str), *t = s; + + str_trunc(str); + + while(*t == ' ' || *t == '\t'){ + t++; + } + if(s < t){ + struct obj *bak = str; + str = str_new(t); + obj_del(bak); + } return str; } @@ -431,6 +531,78 @@ /**/ +struct obj * +dict_new(void) +{ + struct obj *obj = list_new(); + obj->typ = OBJ_TYP_DICT; /* ! */ + return obj; +} + +void +dict_del(struct obj *dic) +{ + dic->typ = OBJ_TYP_LIST; /* ! */ + list_del(dic); +} + +void +dict_add(struct obj *dic, struct obj *k, struct obj *v) +{ + struct obj *lst_kv = list_new(); + + list_append(lst_kv, k); + list_append(lst_kv, v); + + dict_add_lst_kv(dic, lst_kv); +} + +void +dict_add_lst_kv(struct obj *dic, struct obj *lst_kv) +{ + dic->typ = OBJ_TYP_LIST; /* ! */ + list_append(dic, lst_kv); + dic->typ = OBJ_TYP_DICT; /* ! */ +} + +struct obj * +dict_top_lst_kv(struct obj *dic) +{ + struct obj *lst_kv; + + dic->typ = OBJ_TYP_LIST; /* ! */ + lst_kv = list_top(dic); + dic->typ = OBJ_TYP_DICT; /* ! */ + + return lst_kv; +} + +struct obj * +dict_pop_top(struct obj *dic) +{ + struct obj *lst_kv; + + dic->typ = OBJ_TYP_LIST; /* ! */ + lst_kv = list_pop_top(dic); + dic->typ = OBJ_TYP_DICT; /* ! */ + + return lst_kv; +} + +int +dict_len(struct obj *dic) +{ + int n; + + dic->typ = OBJ_TYP_LIST; /* ! */ + n = list_len(dic); + dic->typ = OBJ_TYP_DICT; /* ! */ + + return n; +} + +/**/ + void bufs_init(struct obj *bufs) { @@ -491,11 +663,15 @@ struct obj *lines = list_new(); while(s && *s){ + struct obj *str; char *t = strchr(s, '\n'); if(t){ - *t++ = '\0'; + str = str_new_n(s, (t-s)); + t++; + }else{ + str = str_new(s); } - list_append( lines, str_new(s) ); + list_append(lines, str); s = t; } return lines; @@ -507,4 +683,21 @@ return list_len(lines) ? obj_buf( list_top(lines) ) : NULL; } +struct obj * +lines_join(struct obj *lines, char *delim) +{ + struct obj *r = str_new(""); + struct obj *str = list_top(lines); + int n = list_len(lines), i; + + for(i=0; inext; + } + return r; +} + /* EOF */ diff -ur v9/objs.h v10/objs.h --- v9/objs.h 2018-09-06 02:13:01.000000000 +0900 +++ v10/objs.h 2018-09-07 23:03:17.000000000 +0900 @@ -71,6 +71,7 @@ void *obj_buf(struct obj *obj); +int obj_eq(struct obj *a, struct obj *b); /* for stack */ @@ -113,13 +114,17 @@ */ struct obj *buf_new(int buf_sz); +struct obj *buf_read(FILE *fp, int add_sz); struct obj *buf_append(struct obj *buf, void *vp, int sz); struct obj *buf_append_str(struct obj *buf, char *s); -struct obj *buf_read(FILE *fp, int add_sz); struct obj *str_new(char *s); -struct obj *str_append(struct obj *str, char *s); +struct obj *str_new_n(char *s, int n); +struct obj *str_new_sz(int sz); struct obj *str_read(FILE *fp); +struct obj *str_append(struct obj *str, char *s); +void str_trunc(struct obj *str); +struct obj *str_strip(struct obj *str); void list_init(struct obj *obj); void list_fini(struct obj *lst); @@ -141,6 +146,14 @@ struct obj *list_map(struct obj *lst, struct obj *(*fp)(struct obj *e)); void list_filter(struct obj *lst, int (*fp)(struct obj *e), struct obj *lst_false); +struct obj *dict_new(void); +void dict_del(struct obj *dic); +void dict_add(struct obj *dic, struct obj *k, struct obj *v); +void dict_add_lst_kv(struct obj *dic, struct obj *lst_kv); +struct obj *dict_top_lst_kv(struct obj *dic); +struct obj *dict_pop_top(struct obj *dic); +int dict_len(struct obj *dic); + void bufs_init(struct obj *bufs); void bufs_append(struct obj *bufs, void *buf, int buf_sz); int bufs_sum_sz(struct obj *bufs); @@ -149,5 +162,6 @@ struct obj *lines_new(char *s); char *lines_top_str(struct obj *lines); +struct obj *lines_join(struct obj *lines, char *delim); #endif