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;
|
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"
|
||||||
|
|
|
@ -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
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"
|
#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?
|
||||||
|
|
51
src/match.c
51
src/match.c
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
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>
|
#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
|
||||||
|
|
Loading…
Reference in a new issue