diff --git a/include/psyc.h b/include/psyc.h index 41ace37..b046a58 100644 --- a/include/psyc.h +++ b/include/psyc.h @@ -109,62 +109,8 @@ typedef struct { char *data; } PsycString; -typedef struct { - PsycString key; - void *value; -} PsycDict; - -typedef struct { - PsycString key; - intptr_t value; -} PsycDictInt; - -/** - * Checks if long keyword string inherits from short keyword string. - */ -int -psyc_inherits (char *sho, size_t slen, char *lon, size_t llen); - -/** - * Checks if short keyword string matches long keyword string. - */ -int -psyc_matches (char *sho, size_t slen, char *lon, size_t llen); - -/** - * Look up value associated with a key in a dictionary. - * - * @param dict The dictionary to search, should be ordered alphabetically. - * @param size Size of dict. - * @param key Key to look for. - * @param keylen Length of key. - * @param inherit If true, also look for anything inheriting from key, - otherwise only exact matches are returned. - * @param tmp A temporary array used for keeping track of results. - * Should be the same size as dict. - * - * @return The value of the entry if found, or NULL if not found. - */ - -void * -psyc_dict_lookup (const PsycDict *dict, size_t size, - const char *key, size_t keylen, - PsycBool inherit, int8_t *tmp); - -/** - * Look up value associated with a key in a dictionary of integers. - * @see psyc_dict_lookup - */ -static inline intptr_t -psyc_dict_lookup_int (const PsycDictInt * dict, size_t size, - const char *key, size_t keylen, - PsycBool inherit, int8_t *tmp) -{ - return (intptr_t) psyc_dict_lookup((PsycDict *) dict, size, key, keylen, - inherit, tmp); -} - #include "psyc/syntax.h" +#include "psyc/match.h" #include "psyc/method.h" #include "psyc/packet.h" #include "psyc/parse.h" diff --git a/include/psyc/Makefile b/include/psyc/Makefile index 80d522c..74d0e77 100644 --- a/include/psyc/Makefile +++ b/include/psyc/Makefile @@ -4,7 +4,7 @@ prefix = /usr includedir = ${prefix}/include INSTALL = install -HEADERS = method.h packet.h parse.h render.h syntax.h text.h uniform.h variable.h +HEADERS = match.h method.h packet.h parse.h render.h syntax.h text.h uniform.h variable.h install: ${HEADERS} diff --git a/include/psyc/match.h b/include/psyc/match.h new file mode 100644 index 0000000..2b61f9f --- /dev/null +++ b/include/psyc/match.h @@ -0,0 +1,49 @@ +typedef struct { + PsycString key; + void *value; +} PsycDict; + +typedef struct { + PsycString key; + intptr_t value; +} PsycDictInt; + +/** + * Checks if long keyword string inherits from short keyword string. + */ +int +psyc_inherits (char *sho, size_t slen, char *lon, size_t llen); + +/** + * Checks if short keyword string matches long keyword string. + */ +int +psyc_matches (char *sho, size_t slen, char *lon, size_t llen); + +/** + * Look up value associated with a key in a dictionary. + * + * @param dict The dictionary to search, should be ordered alphabetically. + * @param size Size of dict. + * @param key Key to look for. + * @param keylen Length of key. + * @param inherit If true, also look for anything inheriting from key, + * otherwise only exact matches are returned. + * + * @return The value of the entry if found, or NULL if not found. + */ + +void * +psyc_dict_lookup (const PsycDict *dict, size_t size, + const char *key, size_t keylen, PsycBool inherit); + +/** + * Look up value associated with a key in a dictionary of integers. + * @see psyc_dict_lookup + */ +static inline intptr_t +psyc_dict_lookup_int (const PsycDictInt * dict, size_t size, + const char *key, size_t keylen, PsycBool inherit) +{ + return (intptr_t) psyc_dict_lookup((PsycDict *) dict, size, key, keylen, inherit); +} diff --git a/include/psyc/variable.h b/include/psyc/variable.h index 264a79c..6c8db7c 100644 --- a/include/psyc/variable.h +++ b/include/psyc/variable.h @@ -8,7 +8,8 @@ #include "packet.h" /// Routing variables in alphabetical order. -extern const PsycString psyc_routing_vars[]; +//extern const PsycString psyc_routing_vars[]; +extern const PsycDictInt psyc_routing_vars[]; // Variable types in alphabetical order. extern const PsycDictInt psyc_var_types[]; @@ -23,14 +24,22 @@ extern const size_t psyc_methods_num; /** * Is this a routing variable name? */ -PsycBool -psyc_var_is_routing (const char *name, size_t len); +static inline PsycBool +psyc_var_is_routing (const char *name, size_t len) +{ + return (PsycBool) psyc_dict_lookup((PsycDict *)psyc_routing_vars, + psyc_routing_vars_num, name, len, PSYC_NO); +} /** * Get the type of variable name. */ -PsycType -psyc_var_type (const char *name, size_t len); +static inline PsycType +psyc_var_type (const char *name, size_t len) +{ + return (PsycType) psyc_dict_lookup((PsycDict *)psyc_var_types, + psyc_var_types_num, name, len, PSYC_YES); +} /** * Is this a list variable name? diff --git a/src/match.c b/src/match.c index ac63b5e..ee82401 100644 --- a/src/match.c +++ b/src/match.c @@ -111,46 +111,39 @@ psyc_matches(char *sho, size_t slen, char *lon, size_t llen) */ void * psyc_dict_lookup(const PsycDict * dict, size_t size, - const char *key, size_t keylen, - PsycBool inherit, int8_t * matching) + const char *key, size_t keylen, PsycBool inherit) { - size_t cursor = 1; - uint8_t i, m = 0; + //size_t cursor = 1; + size_t c = 0; + uint8_t i, match = 0; if (keylen < 2 || key[0] != '_') return 0; - // first find the keywords with matching length + //for (c = 0, i = 0; c < keylen && i < size; c++) { for (i = 0; i < size; i++) { - if (keylen == dict[i].key.length - || (inherit && keylen > dict[i].key.length - && key[dict[i].key.length] == '_')) - matching[m++] = i; - } + if (!(keylen == dict[i].key.length + || (inherit && keylen > dict[i].key.length + && key[dict[i].key.length] == '_'))) + continue; - matching[m] = -1; // mark the end of matching indexes + match = 1; + for (c = 0; c < keylen; c++) { + if (c < dict[i].key.length && dict[i].key.data[c] == key[c]) + continue; + else if (c == dict[i].key.length && key[c] == '_') + return dict[i].value; // after the end of a matching prefix + else if (dict[i].key.data[c] > key[c]) + return NULL; - while (cursor < keylen && matching[0] >= 0) { - for (i = m = 0; i < size; i++) { - if (matching[i] < 0) - break; // reached the end of possible matches - if (cursor < dict[matching[i]].key.length && - dict[matching[i]].key.data[cursor] == key[cursor]) - matching[m++] = matching[i]; // found a match, update matching indexes - else if (cursor == dict[matching[i]].key.length && key[cursor] == '_') - return dict[matching[0]].value; // _ after the end of a matching prefix - else if (dict[matching[i]].key.data[cursor] > key[cursor]) - break; // passed the possible matches in alphabetical order in the dict + match = 0; + break; } - - if (m < size) - matching[m] = -1; // mark the end of matching indexes - - cursor++; + if (match) + return dict[i].value; } - // return first match if found - return matching[0] >= 0 ? dict[matching[0]].value : 0; + return NULL; } #ifdef CMDTOOL diff --git a/src/variable.c b/src/variable.c index 99fde96..d972f9b 100644 --- a/src/variable.c +++ b/src/variable.c @@ -5,27 +5,28 @@ /// Routing variables in alphabetical order. -const PsycString psyc_routing_vars[] = { - PSYC_C2STRI("_amount_fragments"), - PSYC_C2STRI("_context"), - //PSYC_C2STRI("_count"), // older PSYC - PSYC_C2STRI("_counter"), - PSYC_C2STRI("_fragment"), - //PSYC_C2STRI("_length"), // older PSYC - PSYC_C2STRI("_source"), - //PSYC_C2STRI("_source_identification"), // older PSYC - PSYC_C2STRI("_source_identity"), - PSYC_C2STRI("_source_relay"), +//const PsycString psyc_routing_vars[] = { +const PsycDictInt psyc_routing_vars[] = { + { PSYC_C2STRI("_amount_fragments"), 1 }, + { PSYC_C2STRI("_context"), 1 }, + //{ PSYC_C2STRI("_count"), 1 }, // older PSYC + { PSYC_C2STRI("_counter"), 1 }, + { PSYC_C2STRI("_fragment"), 1 }, + //{ PSYC_C2STRI("_length"), 1 }, // older PSYC + { PSYC_C2STRI("_source"), 1 }, + //{ PSYC_C2STRI("_source_identification"), 1 }, // older PSYC + { PSYC_C2STRI("_source_identity"), 1 }, + { PSYC_C2STRI("_source_relay"), 1 }, // until you have a better idea.. is this really in use? - PSYC_C2STRI("_source_relay_relay"), - PSYC_C2STRI("_tag"), - PSYC_C2STRI("_tag_relay"), - //PSYC_C2STRI("_tag_reply"), // older PSYC - PSYC_C2STRI("_target"), - PSYC_C2STRI("_target_forward"), - PSYC_C2STRI("_target_relay"), - //PSYC_C2STRI("_understand_modules"), // older PSYC - //PSYC_C2STRI("_using_modules"), // older PSYC + { PSYC_C2STRI("_source_relay_relay"), 1 }, + { PSYC_C2STRI("_tag"), 1 }, + { PSYC_C2STRI("_tag_relay"), 1 }, + //{ PSYC_C2STRI("_tag_reply"), 1 }, // older PSYC + { PSYC_C2STRI("_target"), 1 }, + { PSYC_C2STRI("_target_forward"), 1 }, + { PSYC_C2STRI("_target_relay"), 1 }, + //{ PSYC_C2STRI("_understand_modules"), 1 }, // older PSYC + //{ PSYC_C2STRI("_using_modules"), 1 }, // older PSYC }; // Variable types in alphabetical order. @@ -75,66 +76,14 @@ const size_t psyc_routing_vars_num = PSYC_NUM_ELEM(psyc_routing_vars); const size_t psyc_var_types_num = PSYC_NUM_ELEM(psyc_var_types); const size_t psyc_methods_num = PSYC_NUM_ELEM(psyc_methods); -/** - * Get the type of variable name. - */ -inline PsycBool -psyc_var_is_routing (const char *name, size_t len) -{ - size_t cursor = 1; - uint8_t i, m = 0; - int8_t matching[psyc_routing_vars_num]; // indexes of matching vars - - if (len < 2 || name[0] != '_') - return PSYC_FALSE; - - // first find the vars with matching length - for (i = 0; i < psyc_routing_vars_num; i++) - if (len == psyc_routing_vars[i].length) - matching[m++] = i; - - matching[m] = -1; // mark the end of matching indexes - - while (cursor < len && matching[0] >= 0) { - for (i = m = 0; i < psyc_routing_vars_num; i++) { - if (matching[i] < 0) - break; // reached the end of possible matches - if (psyc_routing_vars[matching[i]].data[cursor] == name[cursor]) - matching[m++] = matching[i]; // found a match, update matching indexes - else if (psyc_routing_vars[matching[i]].data[cursor] > name[cursor]) - break; // passed the possible matches in alphabetical order in the array - } - - if (m < psyc_routing_vars_num) - matching[m] = -1; // mark the end of matching indexes - - cursor++; - } - - return matching[0] >= 0 ? PSYC_TRUE : PSYC_FALSE; -} - -/** - * Get the type of variable name. - */ -inline PsycType -psyc_var_type (const char *name, size_t len) -{ - int8_t m[psyc_var_types_num]; - return (PsycType) psyc_dict_lookup((PsycDict *) psyc_var_types, - psyc_var_types_num, name, len, PSYC_YES, - (int8_t *) &m); -} - /** * Get the method, its family and its flags. */ PsycMethod psyc_method (char *method, size_t methodlen, PsycMethod *family, unsigned int *flag) { - int8_t tmp[PSYC_NUM_ELEM(psyc_methods)]; int mc = psyc_dict_lookup_int(psyc_methods, psyc_methods_num, - method, methodlen, PSYC_YES, tmp); + method, methodlen, PSYC_YES); switch (mc) { case PSYC_MC_DATA: diff --git a/test/Makefile b/test/Makefile index 123de1b..75f15c0 100644 --- a/test/Makefile +++ b/test/Makefile @@ -3,7 +3,7 @@ DEBUG = 2 CFLAGS = -I../include -I../src -Wall -std=c99 ${OPT} LDFLAGS = -L../lib LOADLIBES = -lpsyc -lm -TARGETS = test_psyc test_psyc_speed test_parser test_match test_render test_text var_is_routing var_type uniform_parse test_list test_table test_packet_id +TARGETS = test_psyc test_psyc_speed test_parser test_match test_render test_text var_is_routing var_type uniform_parse test_list test_table test_packet_id method O = test.o WRAPPER = DIET = diet diff --git a/test/method.c b/test/method.c new file mode 100644 index 0000000..408f1ab --- /dev/null +++ b/test/method.c @@ -0,0 +1,29 @@ +#include +#include +#include + +int main() +{ + PsycMethod family = 0; + unsigned int flag = 0; + + int i; + for (i = 0; i < psyc_methods_num; i++) + if (psyc_method(PSYC_S2ARG(psyc_methods[i].key), &family, &flag) + != psyc_methods[i].value) + return i + 1; + + if (psyc_method(PSYC_C2ARG("_echo_hallo"), &family, &flag) != PSYC_MC_UNKNOWN + && family != PSYC_MC_ECHO) + return 101; + + if (psyc_method(PSYC_C2ARG("_foo_bar"), &family, &flag) != PSYC_MC_UNKNOWN) + return 102; + + if (psyc_method(PSYC_C2ARG("_warning_test"), &family, &flag) != PSYC_MC_WARNING + && family != PSYC_MC_WARNING) + return 103; + + printf("psyc_method passed all tests.\n"); + return 0; +} diff --git a/test/var_type.c b/test/var_type.c index 9050398..cc8a1dc 100644 --- a/test/var_type.c +++ b/test/var_type.c @@ -5,16 +5,23 @@ #include int main() { - unless (psyc_var_type(PSYC_C2ARG("_list"))) return 1; - unless (psyc_var_type(PSYC_C2ARG("_list_foo"))) return 2; - unless (psyc_var_type(PSYC_C2ARG("_color_red"))) return 3; - if (psyc_var_type(PSYC_C2ARG("_last"))) return 4; - if (psyc_var_type(PSYC_C2ARG("_lost_foo"))) return 5; - if (psyc_var_type(PSYC_C2ARG("_colorful"))) return 6; - if (psyc_var_type(PSYC_C2ARG("_foo"))) return 7; - if (psyc_var_type(PSYC_C2ARG("bar"))) return 8; - if (psyc_var_type(PSYC_C2ARG("______"))) return 9; - if (psyc_var_type(PSYC_C2ARG("_"))) return 10; + int i; + for (i = 0; i < psyc_var_types_num; i++) + if (psyc_var_type(PSYC_S2ARG(psyc_var_types[i].key)) + != psyc_var_types[i].value) + return i + 1; + + unless (psyc_var_type(PSYC_C2ARG("_list"))) return 51; + unless (psyc_var_type(PSYC_C2ARG("_list_foo"))) return 52; + unless (psyc_var_type(PSYC_C2ARG("_color_red"))) return 53; + + if (psyc_var_type(PSYC_C2ARG("_last"))) return 104; + if (psyc_var_type(PSYC_C2ARG("_lost_foo"))) return 105; + if (psyc_var_type(PSYC_C2ARG("_colorful"))) return 106; + if (psyc_var_type(PSYC_C2ARG("_foo"))) return 107; + if (psyc_var_type(PSYC_C2ARG("bar"))) return 108; + if (psyc_var_type(PSYC_C2ARG("______"))) return 109; + if (psyc_var_type(PSYC_C2ARG("_"))) return 110; puts("psyc_var_type passed all tests."); return 0; // passed all tests