1
0
Fork 0
mirror of git://git.psyc.eu/libpsyc synced 2024-08-15 03:19:02 +00:00

better psyc_dict_lookup

This commit is contained in:
Gabor Adam Toth 2012-01-09 11:52:09 +01:00
parent 7c87d03d3b
commit 97d5ae6af3
9 changed files with 156 additions and 174 deletions

View file

@ -109,62 +109,8 @@ typedef struct {
char *data; char *data;
} PsycString; } 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/syntax.h"
#include "psyc/match.h"
#include "psyc/method.h" #include "psyc/method.h"
#include "psyc/packet.h" #include "psyc/packet.h"
#include "psyc/parse.h" #include "psyc/parse.h"

View file

@ -4,7 +4,7 @@ prefix = /usr
includedir = ${prefix}/include includedir = ${prefix}/include
INSTALL = install 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} install: ${HEADERS}

49
include/psyc/match.h Normal file
View file

@ -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);
}

View file

@ -8,7 +8,8 @@
#include "packet.h" #include "packet.h"
/// Routing variables in alphabetical order. /// 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. // Variable types in alphabetical order.
extern const PsycDictInt psyc_var_types[]; extern const PsycDictInt psyc_var_types[];
@ -23,14 +24,22 @@ extern const size_t psyc_methods_num;
/** /**
* Is this a routing variable name? * Is this a routing variable name?
*/ */
PsycBool static inline PsycBool
psyc_var_is_routing (const char *name, size_t len); 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. * Get the type of variable name.
*/ */
PsycType static inline PsycType
psyc_var_type (const char *name, size_t len); 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? * Is this a list variable name?

View file

@ -111,46 +111,39 @@ psyc_matches(char *sho, size_t slen, char *lon, size_t llen)
*/ */
void * void *
psyc_dict_lookup(const PsycDict * dict, size_t size, psyc_dict_lookup(const PsycDict * dict, size_t size,
const char *key, size_t keylen, const char *key, size_t keylen, PsycBool inherit)
PsycBool inherit, int8_t * matching)
{ {
size_t cursor = 1; //size_t cursor = 1;
uint8_t i, m = 0; size_t c = 0;
uint8_t i, match = 0;
if (keylen < 2 || key[0] != '_') if (keylen < 2 || key[0] != '_')
return 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++) { for (i = 0; i < size; i++) {
if (keylen == dict[i].key.length if (!(keylen == dict[i].key.length
|| (inherit && keylen > dict[i].key.length || (inherit && keylen > dict[i].key.length
&& key[dict[i].key.length] == '_')) && key[dict[i].key.length] == '_')))
matching[m++] = i; 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) { match = 0;
for (i = m = 0; i < size; i++) { break;
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
} }
if (match)
if (m < size) return dict[i].value;
matching[m] = -1; // mark the end of matching indexes
cursor++;
} }
// return first match if found return NULL;
return matching[0] >= 0 ? dict[matching[0]].value : 0;
} }
#ifdef CMDTOOL #ifdef CMDTOOL

View file

@ -5,27 +5,28 @@
/// Routing variables in alphabetical order. /// Routing variables in alphabetical order.
const PsycString psyc_routing_vars[] = { //const PsycString psyc_routing_vars[] = {
PSYC_C2STRI("_amount_fragments"), const PsycDictInt psyc_routing_vars[] = {
PSYC_C2STRI("_context"), { PSYC_C2STRI("_amount_fragments"), 1 },
//PSYC_C2STRI("_count"), // older PSYC { PSYC_C2STRI("_context"), 1 },
PSYC_C2STRI("_counter"), //{ PSYC_C2STRI("_count"), 1 }, // older PSYC
PSYC_C2STRI("_fragment"), { PSYC_C2STRI("_counter"), 1 },
//PSYC_C2STRI("_length"), // older PSYC { PSYC_C2STRI("_fragment"), 1 },
PSYC_C2STRI("_source"), //{ PSYC_C2STRI("_length"), 1 }, // older PSYC
//PSYC_C2STRI("_source_identification"), // older PSYC { PSYC_C2STRI("_source"), 1 },
PSYC_C2STRI("_source_identity"), //{ PSYC_C2STRI("_source_identification"), 1 }, // older PSYC
PSYC_C2STRI("_source_relay"), { PSYC_C2STRI("_source_identity"), 1 },
{ PSYC_C2STRI("_source_relay"), 1 },
// until you have a better idea.. is this really in use? // until you have a better idea.. is this really in use?
PSYC_C2STRI("_source_relay_relay"), { PSYC_C2STRI("_source_relay_relay"), 1 },
PSYC_C2STRI("_tag"), { PSYC_C2STRI("_tag"), 1 },
PSYC_C2STRI("_tag_relay"), { PSYC_C2STRI("_tag_relay"), 1 },
//PSYC_C2STRI("_tag_reply"), // older PSYC //{ PSYC_C2STRI("_tag_reply"), 1 }, // older PSYC
PSYC_C2STRI("_target"), { PSYC_C2STRI("_target"), 1 },
PSYC_C2STRI("_target_forward"), { PSYC_C2STRI("_target_forward"), 1 },
PSYC_C2STRI("_target_relay"), { PSYC_C2STRI("_target_relay"), 1 },
//PSYC_C2STRI("_understand_modules"), // older PSYC //{ PSYC_C2STRI("_understand_modules"), 1 }, // older PSYC
//PSYC_C2STRI("_using_modules"), // older PSYC //{ PSYC_C2STRI("_using_modules"), 1 }, // older PSYC
}; };
// Variable types in alphabetical order. // 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_var_types_num = PSYC_NUM_ELEM(psyc_var_types);
const size_t psyc_methods_num = PSYC_NUM_ELEM(psyc_methods); 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. * Get the method, its family and its flags.
*/ */
PsycMethod PsycMethod
psyc_method (char *method, size_t methodlen, PsycMethod *family, unsigned int *flag) 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, int mc = psyc_dict_lookup_int(psyc_methods, psyc_methods_num,
method, methodlen, PSYC_YES, tmp); method, methodlen, PSYC_YES);
switch (mc) { switch (mc) {
case PSYC_MC_DATA: case PSYC_MC_DATA:

View file

@ -3,7 +3,7 @@ DEBUG = 2
CFLAGS = -I../include -I../src -Wall -std=c99 ${OPT} CFLAGS = -I../include -I../src -Wall -std=c99 ${OPT}
LDFLAGS = -L../lib LDFLAGS = -L../lib
LOADLIBES = -lpsyc -lm 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 O = test.o
WRAPPER = WRAPPER =
DIET = diet DIET = diet

29
test/method.c Normal file
View file

@ -0,0 +1,29 @@
#include <psyc.h>
#include <stdio.h>
#include <lib.h>
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;
}

View file

@ -5,16 +5,23 @@
#include <lib.h> #include <lib.h>
int main() { int main() {
unless (psyc_var_type(PSYC_C2ARG("_list"))) return 1; int i;
unless (psyc_var_type(PSYC_C2ARG("_list_foo"))) return 2; for (i = 0; i < psyc_var_types_num; i++)
unless (psyc_var_type(PSYC_C2ARG("_color_red"))) return 3; if (psyc_var_type(PSYC_S2ARG(psyc_var_types[i].key))
if (psyc_var_type(PSYC_C2ARG("_last"))) return 4; != psyc_var_types[i].value)
if (psyc_var_type(PSYC_C2ARG("_lost_foo"))) return 5; return i + 1;
if (psyc_var_type(PSYC_C2ARG("_colorful"))) return 6;
if (psyc_var_type(PSYC_C2ARG("_foo"))) return 7; unless (psyc_var_type(PSYC_C2ARG("_list"))) return 51;
if (psyc_var_type(PSYC_C2ARG("bar"))) return 8; unless (psyc_var_type(PSYC_C2ARG("_list_foo"))) return 52;
if (psyc_var_type(PSYC_C2ARG("______"))) return 9; unless (psyc_var_type(PSYC_C2ARG("_color_red"))) return 53;
if (psyc_var_type(PSYC_C2ARG("_"))) return 10;
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."); puts("psyc_var_type passed all tests.");
return 0; // passed all tests return 0; // passed all tests