forked from github/server
putting the crit-bit tree to use. finding special region resources is faster this way than doing individual strcmp calls.
This commit is contained in:
parent
3a8f682bea
commit
53b9de957c
4 changed files with 90 additions and 39 deletions
|
@ -33,6 +33,7 @@ without prior permission by the authors of Eressea.
|
||||||
|
|
||||||
#include <util/attrib.h>
|
#include <util/attrib.h>
|
||||||
#include <util/base36.h>
|
#include <util/base36.h>
|
||||||
|
#include <util/critbit.h>
|
||||||
#include <util/language.h>
|
#include <util/language.h>
|
||||||
#include <util/log.h>
|
#include <util/log.h>
|
||||||
|
|
||||||
|
@ -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; }
|
#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)
|
static int tolua_region_get_resource(lua_State * L)
|
||||||
{
|
{
|
||||||
region *r;
|
region *r;
|
||||||
const char *type;
|
const char *type;
|
||||||
const resource_type *rtype;
|
const resource_type *rtype;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
const void * matches;
|
||||||
|
critbit_tree * cb = special_resources();
|
||||||
|
|
||||||
r = (region *) tolua_tousertype(L, 1, 0);
|
r = (region *) tolua_tousertype(L, 1, 0);
|
||||||
LUA_ASSERT(r != NULL, "invalid parameter");
|
LUA_ASSERT(r != NULL, "invalid parameter");
|
||||||
type = tolua_tostring(L, 2, 0);
|
type = tolua_tostring(L, 2, 0);
|
||||||
LUA_ASSERT(type != NULL, "invalid parameter");
|
LUA_ASSERT(type != NULL, "invalid parameter");
|
||||||
rtype = rt_find(type);
|
|
||||||
|
|
||||||
if (!rtype) {
|
if (cb_find_prefix(cb, type, strlen(type)+1, &matches, 1, 0)) {
|
||||||
if (strcmp(type, "seed") == 0)
|
cb_get_kv(matches, &result, sizeof(result));
|
||||||
result = rtrees(r, 0);
|
switch (result) {
|
||||||
if (strcmp(type, "sapling") == 0)
|
case 0:
|
||||||
result = rtrees(r, 1);
|
case 1:
|
||||||
if (strcmp(type, "tree") == 0)
|
case 2:
|
||||||
result = rtrees(r, 2);
|
result = rtrees(r, result);
|
||||||
if (strcmp(type, "grave") == 0)
|
break;
|
||||||
|
case 3:
|
||||||
result = deathcount(r);
|
result = deathcount(r);
|
||||||
if (strcmp(type, "chaos") == 0)
|
break;
|
||||||
|
case 4:
|
||||||
result = chaoscount(r);
|
result = chaoscount(r);
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
rtype = rt_find(type);
|
||||||
|
if (rtype) {
|
||||||
result = region_getresource(r, rtype);
|
result = region_getresource(r, rtype);
|
||||||
|
} else {
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tolua_pushnumber(L, (lua_Number) result);
|
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);
|
region *r = (region *) tolua_tousertype(L, 1, 0);
|
||||||
const char *type = tolua_tostring(L, 2, 0);
|
const char *type = tolua_tostring(L, 2, 0);
|
||||||
int value = (int)tolua_tonumber(L, 3, 0);
|
int result, value = (int)tolua_tonumber(L, 3, 0);
|
||||||
const resource_type *rtype = rt_find(type);
|
critbit_tree * cb = special_resources();
|
||||||
|
const void * matches;
|
||||||
|
|
||||||
|
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 {
|
||||||
|
const resource_type *rtype = rt_find(type);
|
||||||
if (rtype != NULL) {
|
if (rtype != NULL) {
|
||||||
region_setresource(r, rtype, value);
|
region_setresource(r, rtype, value);
|
||||||
} 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -355,7 +355,7 @@ resource_type *rt_find(const char *name)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!rtype) {
|
if (!rtype) {
|
||||||
log_error(("rt_find: unknown resource '%s'\n", name));
|
log_warning(("rt_find: unknown resource '%s'\n", name));
|
||||||
}
|
}
|
||||||
return rtype;
|
return rtype;
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,7 @@ int cb_insert(critbit_tree * cb, const void * key, size_t keylen)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (byte==keylen && byte==len) {
|
if (byte==keylen && byte==len) {
|
||||||
return CB_ENOMORE; /* duplicate entry */
|
return 0; /* duplicate entry */
|
||||||
}
|
}
|
||||||
node->byte = byte;
|
node->byte = byte;
|
||||||
mask = *ikey ^ *iptr; /* these are all the bits that differ */
|
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);
|
assert(next<=numresults);
|
||||||
if (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;
|
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;
|
void *ptr, *top = 0;
|
||||||
assert(key);
|
assert(key);
|
||||||
|
@ -228,7 +228,7 @@ int cb_find_prefix(critbit_tree * cb, const void * key, size_t keylen, const cha
|
||||||
return 0;
|
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;
|
void * str;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
@ -237,14 +237,17 @@ int cb_find(critbit_tree * cb, const void * key, size_t keylen)
|
||||||
|
|
||||||
assert(cb);
|
assert(cb);
|
||||||
assert(key);
|
assert(key);
|
||||||
if (!cb->root) return CB_ENOMORE;
|
if (!cb->root) return 0;
|
||||||
for (ptr=cb->root;decode_pointer(&ptr)==INTERNAL_NODE;) {
|
for (ptr=cb->root;decode_pointer(&ptr)==INTERNAL_NODE;) {
|
||||||
struct critbit_node * node = (struct critbit_node *)ptr;
|
struct critbit_node * node = (struct critbit_node *)ptr;
|
||||||
int branch = (keylen<=node->byte) ? 0 : ((1+((bytes[node->byte]|node->mask)&0xFF))>>8);
|
int branch = (keylen<=node->byte) ? 0 : ((1+((bytes[node->byte]|node->mask)&0xFF))>>8);
|
||||||
ptr = node->child[branch];
|
ptr = node->child[branch];
|
||||||
}
|
}
|
||||||
from_external_node(ptr, &str, &len);
|
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)
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -27,27 +27,27 @@ typedef struct critbit_tree {
|
||||||
void * root;
|
void * root;
|
||||||
} critbit_tree;
|
} critbit_tree;
|
||||||
|
|
||||||
#define CB_ENOMORE 0
|
|
||||||
#define CB_SUCCESS 1
|
#define CB_SUCCESS 1
|
||||||
|
|
||||||
#define CRITBIT_TREE() { 0 }
|
#define CRITBIT_TREE() { 0 }
|
||||||
|
|
||||||
int cb_insert(critbit_tree * cb, const void * key, size_t keylen);
|
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_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);
|
void cb_clear(critbit_tree * cb);
|
||||||
|
|
||||||
#define cb_insert_str(cb, key) \
|
#define cb_insert_str(cb, key) \
|
||||||
cb_insert(cb, (void *)key, strlen(key)+1)
|
cb_insert(cb, (void *)key, strlen(key)+1)
|
||||||
#define cb_find_str(cb, key) \
|
#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) \
|
#define cb_erase_str(cb, key) \
|
||||||
cb_erase(cb, (void *)key, strlen(key)+1)
|
cb_erase(cb, (void *)key, strlen(key)+1)
|
||||||
#define cb_find_prefix_str(cb, key, results, numresults, offset) \
|
#define cb_find_prefix_str(cb, key, results, numresults, offset) \
|
||||||
cb_find_prefix(cb, (void *)key, strlen(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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue