From dbe6e0a45392c7464386122b15954991410cd8c5 Mon Sep 17 00:00:00 2001 From: Gabor Adam Toth Date: Fri, 13 May 2011 23:17:10 +0200 Subject: [PATCH] pkg-psyc: list parsing & rendering --- src/pkg-psyc.c | 113 ++++++++++++++++++++++++++++++++++--------------- src/pkg-psyc.h | 2 + src/version.sh | 2 +- 3 files changed, 82 insertions(+), 35 deletions(-) diff --git a/src/pkg-psyc.c b/src/pkg-psyc.c index c17cf1d..d73bad1 100644 --- a/src/pkg-psyc.c +++ b/src/pkg-psyc.c @@ -22,6 +22,19 @@ mixed pr = psyc_render(p); debug_message(sprintf("libpsyc returned %O (%s)\n", p, pr == s ? "SUCCESS": "FAIL!")); + + string ls = ":_context\ttest\n\n:_list_foo\t|foo|bar|baz\n:_list_bar\t\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"; + string ls2 = ":_context\ttest\n\n:_list_bar\t\n:_list_foo\t|foo|bar|baz\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"; + mixed *lf = psyc_parse(ls); + mixed *lfr = psyc_render(lf); + mixed lr = ({ ([ "_context": "test" ]), + ([ "_list_foo": ({ "foo", "bar", "baz" }), "_list_bar": ({}) ]), + "_notice_test_libpsyc", + "Just [_topic] libpsyc." }); + mixed lrr = psyc_render(lr); + + debug_message(sprintf("libpsyc returned %O,\n%O\nand\n%O\n(%s)\n", lf, lfr, lrr, + (lfr == ls || lfr == ls2) && (lrr == ls || lrr == ls2) ? "SUCCESS": "FAIL!")); */ #include "array.h" @@ -49,16 +62,41 @@ void fill_header_from_mapping (svalue_t *key, svalue_t *val, void *extra) { psyc_modifier_t *m = extra; char *name, *value; - size_t namelen, valuelen; + size_t namelen, valuelen, i; - if (key->type != T_STRING || val->type != T_STRING) - errorf("fill_header_from_mapping: only strings are supported for routing & entity header names & values\n"); + if (key->type != T_STRING) + errorf("fill_header_from_mapping: key type %d not supported\n", key->type); name = get_txt(key->u.str); namelen = mstrsize(key->u.str); - value = get_txt(val->u.str); - valuelen = mstrsize(val->u.str); + if (val->type == T_STRING) { + value = get_txt(val->u.str); + valuelen = mstrsize(val->u.str); + } else if (val->type == T_POINTER) { + psycList list; + psycString *elems = NULL; + + if (VEC_SIZE(val->u.vec)) { + elems = pxalloc(sizeof(psycString) * VEC_SIZE(val->u.vec)); + if (!elems) errorf("Out of memory in fill_header_from_mapping for elems"); + + for (i = 0; i < VEC_SIZE(val->u.vec); i++) { + if (val->u.vec->item[i].type == T_STRING) + elems[i] = (psycString){mstrsize(val->u.vec->item[i].u.str), get_txt(val->u.vec->item[i].u.str)}; + else + errorf("fill_header_from_mapping: list value type %d not supported\n", key->type); + } + } + + list = psyc_newList(elems, VEC_SIZE(val->u.vec), PSYC_LIST_CHECK_LENGTH); + valuelen = list.length; + value = pxalloc(valuelen); + if (!value) errorf("Out of memory in fill_header_from_mapping for list value"); + + psyc_renderList(&list, value, valuelen); + } else + errorf("fill_header_from_mapping: value type %d not supported\n", key->type); m->header->modifiers[m->header->lines++] = psyc_newModifier2(m->oper, name, namelen, value, valuelen, m->flag); @@ -155,15 +193,15 @@ f_psyc_render(svalue_t *sp) { svalue_t * f_psyc_parse (svalue_t *sp) { - string_t *str = NULL; char *buffer = NULL; - vector_t *v; + svalue_t *sv; + vector_t *v, *list; mapping_t *map; - mp_int i; char oper = 0; - psycString name = {0,0}, value = {0,0}, elem; + psycString name = {0,0}, value = {0,0}, elems[MAX_LIST_SIZE], elem; psycParseListState listState; - int ret; + int ret, retl; + size_t size, i; assert_shadow_sent(current_object); psyc_state_t *state = O_GET_PSYC_STATE(current_object); @@ -178,9 +216,8 @@ f_psyc_parse (svalue_t *sp) { psyc_initParseState(state->parser); } - i = 0; if (sp->type == T_POINTER) { - errorf("\npsyc_parse got %ld int* bytes... not supported yet\n", i); + errorf("\npsyc_parse got %ld int* bytes... not supported yet\n", VEC_SIZE(sp->u.vec)); } else if (sp->type == T_STRING) { printf("\npsyc_parse got a %ld bytes long string...\n", mstrsize(sp->u.str)); @@ -216,7 +253,6 @@ f_psyc_parse (svalue_t *sp) { put_mapping(&v->item[PACKET_ENTITY], map); do { - svalue_t *sv; ret = psyc_parse(state->parser, &oper, &name, &value); printf("#%2d %c%.*s = %.*s\n", ret, oper ? oper : ' ', (int)name.length, name.ptr, (int)value.length, value.ptr); @@ -312,7 +348,6 @@ f_psyc_parse (svalue_t *sp) { break; case PSYC_PARSE_BODY: - if (str) errorf("Got two PSYC methods in the same packet!?\n"); // new_n_tabled gets the shared string for the method put_string(&v->item[PACKET_METHOD], new_n_tabled(name.ptr, name.length)); @@ -357,28 +392,38 @@ f_psyc_parse (svalue_t *sp) { if (ret == PSYC_PARSE_BODY_END) break; case PSYC_PARSE_ENTITY: - // list parsing not supported yet.. TODO if (psyc_isListVar(&name)) { - psyc_initParseListState(&listState); - psyc_setParseListBuffer(&listState, value); - elem = (psycString){0, 0}; - while ((ret = psyc_parseList(&listState, &value, &elem))) { - switch (ret) - { - case PSYC_PARSE_LIST_END: - case PSYC_PARSE_LIST_ELEM: - // TODO: store elem - //write(1, elem.ptr, elem.length); - break; - default: - errorf("Error while parsing PSYC list: %i\n", ret); - /* NOTREACHED */ - return sp; - } - - if (ret == PSYC_PARSE_LIST_END) - break; + size = 0; + if (value.length) { + psyc_initParseListState(&listState); + psyc_setParseListBuffer(&listState, value); + elem = (psycString){0, 0}; + do { + retl = psyc_parseList(&listState, &elem); + switch (retl) { + case PSYC_PARSE_LIST_END: + retl = 0; + case PSYC_PARSE_LIST_ELEM: + if (size >= MAX_LIST_SIZE) { + errorf("Error while parsing PSYC list: max list size reached\n"); + /* NOTREACHED */ + return sp; + } + elems[size++] = elem; + break; + default: + errorf("Error while parsing PSYC list: %i\n", retl); + /* NOTREACHED */ + return sp; + } + } while (retl > 0); } + + list = allocate_array(size); + for (i = 0; i < size; i++) + put_string(&list->item[i], new_n_tabled(elems[i].ptr, elems[i].length)); + + put_array(sv, list); } } } while (ret); diff --git a/src/pkg-psyc.h b/src/pkg-psyc.h index 87d8357..66489be 100644 --- a/src/pkg-psyc.h +++ b/src/pkg-psyc.h @@ -17,6 +17,8 @@ # define PACKET_METHOD 2 # define PACKET_BODY 3 +# define MAX_LIST_SIZE 1024 + typedef struct psyc_state_s { psycParseState *parser; vector_t *packet; diff --git a/src/version.sh b/src/version.sh index 8897d0a..169beee 100644 --- a/src/version.sh +++ b/src/version.sh @@ -17,7 +17,7 @@ version_longtype="stable" # A timestamp, to be used by bumpversion and other scripts. # It can be used, for example, to 'touch' this file on every build, thus # forcing revision control systems to add it on every checkin automatically. -version_stamp="Thu May 12 16:37:59 CEST 2011" +version_stamp="Fri May 13 23:10:29 CEST 2011" # Okay, LDMUD is using 3.x.x so to avoid conflicts let's just use 4.x.x version_major=4