From 773c8b6d0dba36e116cc852ff2251b640bf0473a Mon Sep 17 00:00:00 2001 From: Gabor Adam Toth Date: Fri, 20 May 2011 10:36:18 +0200 Subject: [PATCH] pkg-psyc: parse date & other numeric types, store oper in header mapping --- src/pkg-psyc.c | 215 ++++++++++++++++++++++++++++++------------------- src/pkg-psyc.h | 2 +- 2 files changed, 133 insertions(+), 84 deletions(-) diff --git a/src/pkg-psyc.c b/src/pkg-psyc.c index e5fbac2..2a267fe 100644 --- a/src/pkg-psyc.c +++ b/src/pkg-psyc.c @@ -7,31 +7,40 @@ string s, s2; create() { - mixed p, r; - s = ":_context\ttest\n\n:_topic\ttesting\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"; + mixed p, r; + + s = "=_context\ttest\n\n:_topic\ttesting\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"; psyc_parse(s+s+s); - psyc_parse(":_context\ttest\n\n:_topic\ttest"); + psyc_parse("=_context\ttest\n\n:_topic\ttest"); psyc_parse("ing\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"); - p = ({ ([ "_context": "test" ]), ([ "_topic": "testing" ]), + p = ({ ([ "_context": "test"; '=' ]), ([ "_topic": "testing" ]), "_notice_test_libpsyc", "Just [_topic] libpsyc." }); r = psyc_render(p); - debug_message(sprintf("rendering test:\n%s\n", r)); - if (r != s) raise_error("FAIL\n"); + debug_message(sprintf(">> psyc_render returned:\n%s\n", r)); + if (r != s) raise_error(sprintf(">> FAIL, expected:\n%s\n", s)); - s = ":_context\ttest\n\n:_list_foo\t|foo|bar|baz\n:_list_bar\t\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"; - s2 = ":_context\ttest\n\n:_list_bar\t\n:_list_foo\t|foo|bar|baz\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"; + s = "=_context\ttest\n\n:_time_foo\t59\n:_time_bar\t-41\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"; + s2 = "=_context\ttest\n\n:_time_bar\t-41\n:_time_foo\t59\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"; psyc_parse(s); - p = ({ ([ "_context": "test" ]), + s = "=_context\ttest\n\n:_date_foo\t59\n:_date_bar\t-41\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"; + s2 = "=_context\ttest\n\n:_date_bar\t-41\n:_date_foo\t59\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"; + psyc_parse(s); + + s = "=_context\ttest\n\n:_list_foo\t|foo|bar|baz\n:_list_bar\t\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"; + s2 = "=_context\ttest\n\n:_list_bar\t\n:_list_foo\t|foo|bar|baz\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"; + psyc_parse(s); + + p = ({ ([ "_context": "test"; '=' ]), ([ "_list_foo": ({ "foo", "bar", "baz" }), "_list_bar": ({}) ]), "_notice_test_libpsyc", "Just [_topic] libpsyc." }); r = psyc_render(p); - debug_message(sprintf("list rendering test:\n%s\n", r)); - if (r != s) raise_error("FAIL\n"); + debug_message(sprintf(">> psyc_render returned:\n%s\n", r)); + if (r != s) raise_error(sprintf(">> FAIL, expected:\n%s\n", s)); debug_message(sprintf(">> SUCCESS\n")); } @@ -41,7 +50,7 @@ psyc_dispatch(mixed p) { mixed r = psyc_render(p); debug_message(sprintf(">> psyc_render returned:\n%s", r)); - if (r != s && r != s2) raise_error("FAIL\n"); + if (r != s && r != s2) raise_error(sprintf(">> FAIL, expected:\n%s- or -\n%s\n", s, s2)); } */ @@ -70,25 +79,42 @@ psyc_dispatch(mixed p) { void fill_header_from_mapping (svalue_t *key, svalue_t *val, void *extra) { psyc_modifier_t *m = extra; - char *name, *value; + char oper; + char *name, *value, buf[32]; size_t namelen, valuelen, i; + uint8_t type; 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); + type = psyc_getVarType2(name, namelen); + + if (m->num_values > 1) + oper = val[1].u.number; + else + oper = C_GLYPH_OPERATOR_SET; if (val->type == T_STRING) { value = get_txt(val->u.str); valuelen = mstrsize(val->u.str); + } else if (val->type == T_NUMBER) { + if (type == PSYC_TYPE_DATE) + snprintf(buf, 32, "%ld", val->u.number - PSYC_EPOCH); + else + snprintf(buf, 32, "%ld", val->u.number); + valuelen = strlen(buf); + value = pxalloc(valuelen); + if (!value) errorf("Out of memory in fill_header_from_mapping for number\n"); + memcpy(value, buf, valuelen); } 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"); + if (!elems) errorf("Out of memory in fill_header_from_mapping for elems\n"); for (i = 0; i < VEC_SIZE(val->u.vec); i++) { if (val->u.vec->item[i].type == T_STRING) @@ -101,14 +127,14 @@ fill_header_from_mapping (svalue_t *key, svalue_t *val, void *extra) { 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"); + if (!value) errorf("Out of memory in fill_header_from_mapping for list value\n"); 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); + psyc_newModifier2(oper, name, namelen, value, valuelen, m->flag); } /*-------------------------------------------------------------------------*/ @@ -143,11 +169,11 @@ f_psyc_render(svalue_t *sp) { if (i == PACKET_ROUTING) walk_mapping(map, &fill_header_from_mapping, - &(psyc_modifier_t) {&headers[i], C_GLYPH_OPERATOR_SET, + &(psyc_modifier_t) {&headers[i], map->num_values, PSYC_MODIFIER_ROUTING}); else walk_mapping(map, &fill_header_from_mapping, - &(psyc_modifier_t) {&headers[i], C_GLYPH_OPERATOR_SET, + &(psyc_modifier_t) {&headers[i], map->num_values, PSYC_MODIFIER_CHECK_LENGTH}); } } @@ -209,8 +235,9 @@ f_psyc_parse (svalue_t *sp) { char oper = 0; psycString name = {0,0}, value = {0,0}, elems[MAX_LIST_SIZE], elem; psycParseListState listState; - int ret, retl; + int ret, retl, type = -1; size_t size, i; + time_t t; string_t *callback = mstring_new_string("psyc_dispatch"); assert_shadow_sent(current_object); @@ -260,10 +287,10 @@ f_psyc_parse (svalue_t *sp) { if (!state->packet) errorf("Out of memory for psyc_parse array.\n"); v = state->packet; - map = allocate_mapping(0, 1); // empty mapping + map = allocate_mapping(0, 2); // empty mapping if (!map) errorf("Out of memory for psyc_parse routing header.\n"); put_mapping(&v->item[PACKET_ROUTING], map); - map = allocate_mapping(0, 1); // empty mapping + map = allocate_mapping(0, 2); // empty mapping if (!map) errorf("Out of memory for psyc_parse entity header.\n"); put_mapping(&v->item[PACKET_ENTITY], map); } @@ -302,15 +329,13 @@ f_psyc_parse (svalue_t *sp) { switch (ret) { case PSYC_PARSE_ROUTING: - if (oper != ':') { - puts("_failure_unsupported_state"); - continue; - } sv = pxalloc(sizeof(svalue_t)); + // new_n_tabled fetches a reference of a probably existing // shared string put_string(sv, new_n_tabled(name.ptr, name.length)); sv = get_map_lvalue(v->item[PACKET_ROUTING].u.map, sv); + put_number(&sv[1], oper); // strings are capable of containing 0 so we can do this // for binary data too. let's use a tabled string even // for values of routing variables as they repeat a lot @@ -322,31 +347,91 @@ f_psyc_parse (svalue_t *sp) { break; case PSYC_PARSE_ENTITY_END: - if (oper != ':') { - puts("_failure_unsupported_state"); - continue; - } - - sv = pxalloc(sizeof(svalue_t)); - put_string(sv, make_tabled(state->name)); - sv = get_map_lvalue(v->item[PACKET_ENTITY].u.map, sv); - put_string(sv, state->value); - break; - case PSYC_PARSE_ENTITY: - if (oper != ':') { - puts("_failure_unsupported_state"); - continue; - } - sv = pxalloc(sizeof(svalue_t)); - put_string(sv, new_n_tabled(name.ptr, name.length)); - sv = get_map_lvalue(v->item[PACKET_ENTITY].u.map, sv); - // is it good to put entity variable values into the - // shared string table? probably yes.. but it's a guess - //t_string(sv, new_n_mstring(value.ptr, value.length)); - put_string(sv, new_n_tabled(value.ptr, value.length)); + if (ret == PSYC_PARSE_ENTITY) + put_string(sv, new_n_tabled(name.ptr, name.length)); + else // PSYC_PARSE_ENTITY_END + put_string(sv, make_tabled(state->name)); + + sv = get_map_lvalue(v->item[PACKET_ENTITY].u.map, sv); + put_number(&sv[1], oper); + + type = psyc_getVarType(&name); + switch (type) { + case PSYC_TYPE_DATE: // number + PSYC_EPOCH + if (psyc_parseDate(&value, &t)) + put_number(sv, t); + else + errorf("Error while parsing _date value\n"); // TODO: _error_invalid_value? + break; + case PSYC_TYPE_TIME: // number + if (psyc_parseTime(&value, &t)) + put_number(sv, t); + else + errorf("Error while parsing _time value\n"); + break; + case PSYC_TYPE_AMOUNT: // number + if (psyc_parseNumber(&value, &t)) + put_number(sv, t); + else + errorf("Error while parsing _amount value\n"); + break; + case PSYC_TYPE_DEGREE: // first digit + if (value.length && value.ptr[0] >= '0' && value.ptr[0] <= '9') + put_number(sv, value.ptr[0] - '0'); + else + errorf("Error while parsing _degree value\n"); + break; + case PSYC_TYPE_FLAG: // 0 or 1 + if (value.length && value.ptr[0] >= '0' && value.ptr[0] <= '1') + put_number(sv, value.ptr[0] - '0'); + else + errorf("Error while parsing _flag value\n"); + break; + case PSYC_TYPE_LIST: // array + 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); + break; + default: // string + if (ret == PSYC_PARSE_ENTITY) + // is it good to put entity variable values into the + // shared string table? probably yes.. but it's a guess + //t_string(sv, new_n_mstring(value.ptr, value.length)); + put_string(sv, new_n_tabled(value.ptr, value.length)); + else // PSYC_PARSE_ENTITY_END + put_string(sv, state->value); + } break; case PSYC_PARSE_BODY_START: @@ -401,42 +486,6 @@ f_psyc_parse (svalue_t *sp) { state->oper = 0; state->name = NULL; state->value = NULL; - if (ret == PSYC_PARSE_BODY_END) - break; - case PSYC_PARSE_ENTITY: - if (psyc_isListVar(&name)) { - 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 66489be..0cd4545 100644 --- a/src/pkg-psyc.h +++ b/src/pkg-psyc.h @@ -34,7 +34,7 @@ typedef struct psyc_state_s { typedef struct psyc_modifier_s { psycHeader *header; - char oper; + p_int num_values; psycModifierFlag flag; } psyc_modifier_t;