mirror of
git://git.psyced.org/git/psyclpc
synced 2024-08-15 03:20:16 +00:00
pkg-psyc: parse date & other numeric types, store oper in header mapping
This commit is contained in:
parent
1d35e854e3
commit
773c8b6d0d
2 changed files with 133 additions and 84 deletions
215
src/pkg-psyc.c
215
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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue