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;
} 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"

View file

@ -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
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"
/// 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?

View file

@ -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

View file

@ -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:

View file

@ -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
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>
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