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;
|
string s, s2;
|
||||||
|
|
||||||
create() {
|
create() {
|
||||||
mixed p, r;
|
mixed p, r;
|
||||||
s = ":_context\ttest\n\n:_topic\ttesting\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n";
|
|
||||||
|
s = "=_context\ttest\n\n:_topic\ttesting\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n";
|
||||||
psyc_parse(s+s+s);
|
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");
|
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." });
|
"_notice_test_libpsyc", "Just [_topic] libpsyc." });
|
||||||
r = psyc_render(p);
|
r = psyc_render(p);
|
||||||
|
|
||||||
debug_message(sprintf("rendering test:\n%s\n", r));
|
debug_message(sprintf(">> psyc_render returned:\n%s\n", r));
|
||||||
if (r != s) raise_error("FAIL\n");
|
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";
|
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:_list_bar\t\n:_list_foo\t|foo|bar|baz\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);
|
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": ({}) ]),
|
([ "_list_foo": ({ "foo", "bar", "baz" }), "_list_bar": ({}) ]),
|
||||||
"_notice_test_libpsyc", "Just [_topic] libpsyc." });
|
"_notice_test_libpsyc", "Just [_topic] libpsyc." });
|
||||||
r = psyc_render(p);
|
r = psyc_render(p);
|
||||||
|
|
||||||
debug_message(sprintf("list rendering test:\n%s\n", r));
|
debug_message(sprintf(">> psyc_render returned:\n%s\n", r));
|
||||||
if (r != s) raise_error("FAIL\n");
|
if (r != s) raise_error(sprintf(">> FAIL, expected:\n%s\n", s));
|
||||||
|
|
||||||
debug_message(sprintf(">> SUCCESS\n"));
|
debug_message(sprintf(">> SUCCESS\n"));
|
||||||
}
|
}
|
||||||
|
@ -41,7 +50,7 @@ psyc_dispatch(mixed p) {
|
||||||
|
|
||||||
mixed r = psyc_render(p);
|
mixed r = psyc_render(p);
|
||||||
debug_message(sprintf(">> psyc_render returned:\n%s", r));
|
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
|
void
|
||||||
fill_header_from_mapping (svalue_t *key, svalue_t *val, void *extra) {
|
fill_header_from_mapping (svalue_t *key, svalue_t *val, void *extra) {
|
||||||
psyc_modifier_t *m = extra;
|
psyc_modifier_t *m = extra;
|
||||||
char *name, *value;
|
char oper;
|
||||||
|
char *name, *value, buf[32];
|
||||||
size_t namelen, valuelen, i;
|
size_t namelen, valuelen, i;
|
||||||
|
uint8_t type;
|
||||||
|
|
||||||
if (key->type != T_STRING)
|
if (key->type != T_STRING)
|
||||||
errorf("fill_header_from_mapping: key type %d not supported\n", key->type);
|
errorf("fill_header_from_mapping: key type %d not supported\n", key->type);
|
||||||
|
|
||||||
name = get_txt(key->u.str);
|
name = get_txt(key->u.str);
|
||||||
namelen = mstrsize(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) {
|
if (val->type == T_STRING) {
|
||||||
value = get_txt(val->u.str);
|
value = get_txt(val->u.str);
|
||||||
valuelen = mstrsize(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) {
|
} else if (val->type == T_POINTER) {
|
||||||
psycList list;
|
psycList list;
|
||||||
psycString *elems = NULL;
|
psycString *elems = NULL;
|
||||||
|
|
||||||
if (VEC_SIZE(val->u.vec)) {
|
if (VEC_SIZE(val->u.vec)) {
|
||||||
elems = pxalloc(sizeof(psycString) * 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++) {
|
for (i = 0; i < VEC_SIZE(val->u.vec); i++) {
|
||||||
if (val->u.vec->item[i].type == T_STRING)
|
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);
|
list = psyc_newList(elems, VEC_SIZE(val->u.vec), PSYC_LIST_CHECK_LENGTH);
|
||||||
valuelen = list.length;
|
valuelen = list.length;
|
||||||
value = pxalloc(valuelen);
|
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);
|
psyc_renderList(&list, value, valuelen);
|
||||||
} else
|
} else
|
||||||
errorf("fill_header_from_mapping: value type %d not supported\n", key->type);
|
errorf("fill_header_from_mapping: value type %d not supported\n", key->type);
|
||||||
|
|
||||||
m->header->modifiers[m->header->lines++] =
|
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)
|
if (i == PACKET_ROUTING)
|
||||||
walk_mapping(map, &fill_header_from_mapping,
|
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});
|
PSYC_MODIFIER_ROUTING});
|
||||||
else
|
else
|
||||||
walk_mapping(map, &fill_header_from_mapping,
|
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});
|
PSYC_MODIFIER_CHECK_LENGTH});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,8 +235,9 @@ f_psyc_parse (svalue_t *sp) {
|
||||||
char oper = 0;
|
char oper = 0;
|
||||||
psycString name = {0,0}, value = {0,0}, elems[MAX_LIST_SIZE], elem;
|
psycString name = {0,0}, value = {0,0}, elems[MAX_LIST_SIZE], elem;
|
||||||
psycParseListState listState;
|
psycParseListState listState;
|
||||||
int ret, retl;
|
int ret, retl, type = -1;
|
||||||
size_t size, i;
|
size_t size, i;
|
||||||
|
time_t t;
|
||||||
string_t *callback = mstring_new_string("psyc_dispatch");
|
string_t *callback = mstring_new_string("psyc_dispatch");
|
||||||
|
|
||||||
assert_shadow_sent(current_object);
|
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");
|
if (!state->packet) errorf("Out of memory for psyc_parse array.\n");
|
||||||
v = state->packet;
|
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");
|
if (!map) errorf("Out of memory for psyc_parse routing header.\n");
|
||||||
put_mapping(&v->item[PACKET_ROUTING], map);
|
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");
|
if (!map) errorf("Out of memory for psyc_parse entity header.\n");
|
||||||
put_mapping(&v->item[PACKET_ENTITY], map);
|
put_mapping(&v->item[PACKET_ENTITY], map);
|
||||||
}
|
}
|
||||||
|
@ -302,15 +329,13 @@ f_psyc_parse (svalue_t *sp) {
|
||||||
|
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case PSYC_PARSE_ROUTING:
|
case PSYC_PARSE_ROUTING:
|
||||||
if (oper != ':') {
|
|
||||||
puts("_failure_unsupported_state");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
sv = pxalloc(sizeof(svalue_t));
|
sv = pxalloc(sizeof(svalue_t));
|
||||||
|
|
||||||
// new_n_tabled fetches a reference of a probably existing
|
// new_n_tabled fetches a reference of a probably existing
|
||||||
// shared string
|
// shared string
|
||||||
put_string(sv, new_n_tabled(name.ptr, name.length));
|
put_string(sv, new_n_tabled(name.ptr, name.length));
|
||||||
sv = get_map_lvalue(v->item[PACKET_ROUTING].u.map, sv);
|
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
|
// strings are capable of containing 0 so we can do this
|
||||||
// for binary data too. let's use a tabled string even
|
// for binary data too. let's use a tabled string even
|
||||||
// for values of routing variables as they repeat a lot
|
// for values of routing variables as they repeat a lot
|
||||||
|
@ -322,31 +347,91 @@ f_psyc_parse (svalue_t *sp) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PSYC_PARSE_ENTITY_END:
|
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:
|
case PSYC_PARSE_ENTITY:
|
||||||
if (oper != ':') {
|
|
||||||
puts("_failure_unsupported_state");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
sv = pxalloc(sizeof(svalue_t));
|
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
|
if (ret == PSYC_PARSE_ENTITY)
|
||||||
// shared string table? probably yes.. but it's a guess
|
put_string(sv, new_n_tabled(name.ptr, name.length));
|
||||||
//t_string(sv, new_n_mstring(value.ptr, value.length));
|
else // PSYC_PARSE_ENTITY_END
|
||||||
put_string(sv, new_n_tabled(value.ptr, value.length));
|
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;
|
break;
|
||||||
|
|
||||||
case PSYC_PARSE_BODY_START:
|
case PSYC_PARSE_BODY_START:
|
||||||
|
@ -401,42 +486,6 @@ f_psyc_parse (svalue_t *sp) {
|
||||||
state->oper = 0;
|
state->oper = 0;
|
||||||
state->name = NULL;
|
state->name = NULL;
|
||||||
state->value = 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);
|
} while (ret);
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ typedef struct psyc_state_s {
|
||||||
|
|
||||||
typedef struct psyc_modifier_s {
|
typedef struct psyc_modifier_s {
|
||||||
psycHeader *header;
|
psycHeader *header;
|
||||||
char oper;
|
p_int num_values;
|
||||||
psycModifierFlag flag;
|
psycModifierFlag flag;
|
||||||
} psyc_modifier_t;
|
} psyc_modifier_t;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue