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:
parent
7c87d03d3b
commit
97d5ae6af3
9 changed files with 156 additions and 174 deletions
|
@ -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"
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
|
49
include/psyc/match.h
Normal file
49
include/psyc/match.h
Normal 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);
|
||||
}
|
|
@ -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?
|
||||
|
|
55
src/match.c
55
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
|
||||
if (!(keylen == dict[i].key.length
|
||||
|| (inherit && keylen > dict[i].key.length
|
||||
&& key[dict[i].key.length] == '_'))
|
||||
matching[m++] = i;
|
||||
&& key[dict[i].key.length] == '_')))
|
||||
continue;
|
||||
|
||||
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;
|
||||
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
if (match)
|
||||
return dict[i].value;
|
||||
}
|
||||
|
||||
matching[m] = -1; // mark the end of matching indexes
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
if (m < size)
|
||||
matching[m] = -1; // mark the end of matching indexes
|
||||
|
||||
cursor++;
|
||||
}
|
||||
|
||||
// return first match if found
|
||||
return matching[0] >= 0 ? dict[matching[0]].value : 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CMDTOOL
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
29
test/method.c
Normal file
29
test/method.c
Normal 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;
|
||||
}
|
|
@ -5,16 +5,23 @@
|
|||
#include <lib.h>
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue