From 53b9de957c2343f36e0192c56229df983512f6ce Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 14 May 2012 16:36:17 -0700 Subject: [PATCH] putting the crit-bit tree to use. finding special region resources is faster this way than doing individual strcmp calls. --- src/bindings/bind_region.c | 86 ++++++++++++++++++++++++++------------ src/kernel/item.c | 2 +- src/util/critbit.c | 31 +++++++++++--- src/util/critbit.h | 10 ++--- 4 files changed, 90 insertions(+), 39 deletions(-) diff --git a/src/bindings/bind_region.c b/src/bindings/bind_region.c index 1b4244d81..fe3d69ea0 100644 --- a/src/bindings/bind_region.c +++ b/src/bindings/bind_region.c @@ -33,6 +33,7 @@ without prior permission by the authors of Eressea. #include #include +#include #include #include @@ -309,32 +310,58 @@ static int tolua_region_get_resourcelevel(lua_State * L) } #define LUA_ASSERT(c, s) if (!(c)) { log_error(("%s(%d): %s\n", __FILE__, __LINE__, (s))); return 0; } + +static critbit_tree * special_resources(void) +{ + static critbit_tree cb = CRITBIT_TREE(); + if (!cb.root) { + const char * special[] = { "seed", "sapling", "tree", "grave", "chaos", 0 }; + char buffer[32]; + int i; + for (i=0;special[i];++i) { + cb_new_kv(special[i], &i, sizeof(int), buffer); + cb_insert(&cb, buffer, strlen(special[i])+1+sizeof(int)); + } + } + return &cb; +} + static int tolua_region_get_resource(lua_State * L) { region *r; const char *type; const resource_type *rtype; int result = 0; + const void * matches; + critbit_tree * cb = special_resources(); r = (region *) tolua_tousertype(L, 1, 0); LUA_ASSERT(r != NULL, "invalid parameter"); type = tolua_tostring(L, 2, 0); LUA_ASSERT(type != NULL, "invalid parameter"); - rtype = rt_find(type); - if (!rtype) { - if (strcmp(type, "seed") == 0) - result = rtrees(r, 0); - if (strcmp(type, "sapling") == 0) - result = rtrees(r, 1); - if (strcmp(type, "tree") == 0) - result = rtrees(r, 2); - if (strcmp(type, "grave") == 0) + if (cb_find_prefix(cb, type, strlen(type)+1, &matches, 1, 0)) { + cb_get_kv(matches, &result, sizeof(result)); + switch (result) { + case 0: + case 1: + case 2: + result = rtrees(r, result); + break; + case 3: result = deathcount(r); - if (strcmp(type, "chaos") == 0) + break; + case 4: result = chaoscount(r); + break; + } } else { - result = region_getresource(r, rtype); + rtype = rt_find(type); + if (rtype) { + result = region_getresource(r, rtype); + } else { + result = -1; + } } tolua_pushnumber(L, (lua_Number) result); @@ -345,24 +372,29 @@ static int tolua_region_set_resource(lua_State * L) { region *r = (region *) tolua_tousertype(L, 1, 0); const char *type = tolua_tostring(L, 2, 0); - int value = (int)tolua_tonumber(L, 3, 0); - const resource_type *rtype = rt_find(type); + int result, value = (int)tolua_tonumber(L, 3, 0); + critbit_tree * cb = special_resources(); + const void * matches; - if (rtype != NULL) { - region_setresource(r, rtype, value); + if (cb_find_prefix(cb, type, strlen(type)+1, &matches, 1, 0)) { + cb_get_kv(matches, &result, sizeof(result)); + switch (result) { + case 0: + case 1: + case 2: + rsettrees(r, result, value); + break; + case 3: + deathcounts(r, value - deathcount(r)); + break; + case 4: + chaoscounts(r, value - chaoscount(r)); + break; + } } else { - if (strcmp(type, "seed") == 0) { - rsettrees(r, 0, value); - } else if (strcmp(type, "sapling") == 0) { - rsettrees(r, 1, value); - } else if (strcmp(type, "tree") == 0) { - rsettrees(r, 2, value); - } else if (strcmp(type, "grave") == 0) { - int fallen = value - deathcount(r); - deathcounts(r, fallen); - } else if (strcmp(type, "chaos") == 0) { - int fallen = value - chaoscount(r); - chaoscounts(r, fallen); + const resource_type *rtype = rt_find(type); + if (rtype != NULL) { + region_setresource(r, rtype, value); } } return 0; diff --git a/src/kernel/item.c b/src/kernel/item.c index 322fcb3c5..acb03744e 100644 --- a/src/kernel/item.c +++ b/src/kernel/item.c @@ -355,7 +355,7 @@ resource_type *rt_find(const char *name) break; } if (!rtype) { - log_error(("rt_find: unknown resource '%s'\n", name)); + log_warning(("rt_find: unknown resource '%s'\n", name)); } return rtype; } diff --git a/src/util/critbit.c b/src/util/critbit.c index a9df274f9..a4e55950b 100644 --- a/src/util/critbit.c +++ b/src/util/critbit.c @@ -127,7 +127,7 @@ int cb_insert(critbit_tree * cb, const void * key, size_t keylen) } if (byte==keylen && byte==len) { - return CB_ENOMORE; /* duplicate entry */ + return 0; /* duplicate entry */ } node->byte = byte; mask = *ikey ^ *iptr; /* these are all the bits that differ */ @@ -166,7 +166,7 @@ int cb_insert(critbit_tree * cb, const void * key, size_t keylen) } } -static int cb_find_prefix_i(void * ptr, const void * key, size_t keylen, const char ** results, int numresults, int * offset, int next) +static int cb_find_prefix_i(void * ptr, const void * key, size_t keylen, const void ** results, int numresults, int * offset, int next) { assert(next<=numresults); if (next==numresults) { @@ -194,7 +194,7 @@ static int cb_find_prefix_i(void * ptr, const void * key, size_t keylen, const c return next; } -int cb_find_prefix(critbit_tree * cb, const void * key, size_t keylen, const char ** results, int numresults, int offset) +int cb_find_prefix(critbit_tree * cb, const void * key, size_t keylen, const void ** results, int numresults, int offset) { void *ptr, *top = 0; assert(key); @@ -228,7 +228,7 @@ int cb_find_prefix(critbit_tree * cb, const void * key, size_t keylen, const cha return 0; } -int cb_find(critbit_tree * cb, const void * key, size_t keylen) +const void * cb_find(critbit_tree * cb, const void * key, size_t keylen) { void * str; size_t len; @@ -237,14 +237,17 @@ int cb_find(critbit_tree * cb, const void * key, size_t keylen) assert(cb); assert(key); - if (!cb->root) return CB_ENOMORE; + if (!cb->root) return 0; for (ptr=cb->root;decode_pointer(&ptr)==INTERNAL_NODE;) { struct critbit_node * node = (struct critbit_node *)ptr; int branch = (keylen<=node->byte) ? 0 : ((1+((bytes[node->byte]|node->mask)&0xFF))>>8); ptr = node->child[branch]; } from_external_node(ptr, &str, &len); - return len==keylen && memcmp(key, str, keylen)==0; + if (len==keylen && memcmp(key, str, keylen)==0) { + return str; + } + return 0; } int cb_erase(critbit_tree * cb, const void * key, size_t keylen) @@ -284,3 +287,19 @@ int cb_erase(critbit_tree * cb, const void * key, size_t keylen) } } } + +void cb_new_kv(const char *key, void * value, size_t len, void * dst) +{ + size_t keylen = strlen(key)+1; + if (dst!=key) { + memcpy(dst, key, keylen); + } + memcpy((char*)dst+keylen, value, len); +} + +void cb_get_kv(const void *kv, void * value, size_t len) +{ + const char * key = (const char *)kv; + size_t keylen = strlen(key)+1; + memcpy(value, key+keylen, len); +} diff --git a/src/util/critbit.h b/src/util/critbit.h index 3eb2b4842..9240c582d 100644 --- a/src/util/critbit.h +++ b/src/util/critbit.h @@ -27,27 +27,27 @@ typedef struct critbit_tree { void * root; } critbit_tree; -#define CB_ENOMORE 0 #define CB_SUCCESS 1 #define CRITBIT_TREE() { 0 } int cb_insert(critbit_tree * cb, const void * key, size_t keylen); -int cb_find(critbit_tree * cb, const void * key, size_t keylen); +const void * cb_find(critbit_tree * cb, const void * key, size_t keylen); int cb_erase(critbit_tree * cb, const void * key, size_t keylen); -int cb_find_prefix(critbit_tree * cb, const void * key, size_t keylen, const char ** results, int numresults, int offset); +int cb_find_prefix(critbit_tree * cb, const void * key, size_t keylen, const void ** results, int numresults, int offset); void cb_clear(critbit_tree * cb); #define cb_insert_str(cb, key) \ cb_insert(cb, (void *)key, strlen(key)+1) #define cb_find_str(cb, key) \ - cb_find(cb, (void *)key, strlen(key)+1) + (const char *)cb_find(cb, (void *)key, strlen(key)+1) #define cb_erase_str(cb, key) \ cb_erase(cb, (void *)key, strlen(key)+1) #define cb_find_prefix_str(cb, key, results, numresults, offset) \ cb_find_prefix(cb, (void *)key, strlen(key), results, numresults, offset) - +void cb_new_kv(const char *key, void * value, size_t len, void * dst); +void cb_get_kv(const void *kv, void * value, size_t len); #ifdef __cplusplus }