forked from github/server
rt_find and it_find use new improved critbit-tree
critbit update testing the test suite
This commit is contained in:
parent
f47f83ceca
commit
7f7c883583
|
@ -1,6 +1,3 @@
|
||||||
/* this file should only be included by laws.c, never compiled on its own
|
|
||||||
* (it does not even include all the headers needed to do so).
|
|
||||||
**/
|
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include <kernel/types.h>
|
#include <kernel/types.h>
|
||||||
#include "laws.h"
|
#include "laws.h"
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
static void market_curse(CuTest * tc)
|
static void test_market_curse(CuTest * tc)
|
||||||
{
|
{
|
||||||
region *r;
|
region *r;
|
||||||
building *b;
|
building *b;
|
||||||
|
@ -26,16 +26,21 @@ static void market_curse(CuTest * tc)
|
||||||
faction *f;
|
faction *f;
|
||||||
int x, y;
|
int x, y;
|
||||||
const char *names[4] = { "herb", "herbs", "balm", "balms" };
|
const char *names[4] = { "herb", "herbs", "balm", "balms" };
|
||||||
terrain_type *terrain;
|
const terrain_type *terrain;
|
||||||
resource_type *hres = new_resourcetype(names, 0, RTF_ITEM | RTF_POOLED);
|
resource_type *hres, *lres;
|
||||||
item_type *htype = new_itemtype(hres, ITF_HERB, 0, 0);
|
item_type *htype, *ltype;
|
||||||
resource_type *lres = new_resourcetype(names + 2, 0, RTF_ITEM | RTF_POOLED);
|
luxury_type *lux;
|
||||||
item_type *ltype = new_itemtype(lres, ITF_NONE, 0, 0);
|
|
||||||
luxury_type *lux = new_luxurytype(ltype, 0);
|
|
||||||
building_type *btype;
|
building_type *btype;
|
||||||
race *rc = rc_add(rc_new("human"));
|
|
||||||
|
|
||||||
free_gamedata();
|
free_gamedata();
|
||||||
|
test_cleanup();
|
||||||
|
test_create_world();
|
||||||
|
|
||||||
|
hres = new_resourcetype(names, 0, RTF_ITEM | RTF_POOLED);
|
||||||
|
htype = new_itemtype(hres, ITF_HERB, 0, 0);
|
||||||
|
lres = new_resourcetype(names + 2, 0, RTF_ITEM | RTF_POOLED);
|
||||||
|
ltype = new_itemtype(lres, ITF_NONE, 0, 0);
|
||||||
|
lux = new_luxurytype(ltype, 0);
|
||||||
|
|
||||||
set_param(&global.parameters, "rules.region_owners", "1");
|
set_param(&global.parameters, "rules.region_owners", "1");
|
||||||
|
|
||||||
|
@ -43,12 +48,16 @@ static void market_curse(CuTest * tc)
|
||||||
btype->_name = "market";
|
btype->_name = "market";
|
||||||
bt_register(btype);
|
bt_register(btype);
|
||||||
|
|
||||||
terrain = test_create_terrain("plain", LAND_REGION | WALK_INTO);
|
terrain = get_terrain("plain");
|
||||||
|
|
||||||
for (x = 0; x != 3; ++x) {
|
for (x = 0; x != 3; ++x) {
|
||||||
for (y = 0; y != 3; ++y) {
|
for (y = 0; y != 3; ++y) {
|
||||||
r = new_region(x, y, NULL, 0);
|
r = findregion(x, y);
|
||||||
terraform_region(r, terrain);
|
if (!r) {
|
||||||
|
r = test_create_region(x, y, terrain);
|
||||||
|
} else {
|
||||||
|
terraform_region(r, terrain);
|
||||||
|
}
|
||||||
rsetpeasants(r, 5000);
|
rsetpeasants(r, 5000);
|
||||||
r_setdemand(r, lux, 0);
|
r_setdemand(r, lux, 0);
|
||||||
rsetherbtype(r, htype);
|
rsetherbtype(r, htype);
|
||||||
|
@ -59,8 +68,8 @@ static void market_curse(CuTest * tc)
|
||||||
b->flags |= BLD_WORKING;
|
b->flags |= BLD_WORKING;
|
||||||
b->size = b->type->maxsize;
|
b->size = b->type->maxsize;
|
||||||
|
|
||||||
f = addfaction("nobody@eressea.de", NULL, rc, default_locale, 0);
|
f = test_create_faction(0);
|
||||||
u = create_unit(r, f, 1, f->race, 0, 0, 0);
|
u = test_create_unit(f, r);
|
||||||
u_set_building(u, b);
|
u_set_building(u, b);
|
||||||
|
|
||||||
do_markets();
|
do_markets();
|
||||||
|
@ -72,6 +81,6 @@ static void market_curse(CuTest * tc)
|
||||||
CuSuite *get_market_suite(void)
|
CuSuite *get_market_suite(void)
|
||||||
{
|
{
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
SUITE_ADD_TEST(suite, market_curse);
|
SUITE_ADD_TEST(suite, test_market_curse);
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
/* util includes */
|
/* util includes */
|
||||||
#include <util/attrib.h>
|
#include <util/attrib.h>
|
||||||
#include <util/base36.h>
|
#include <util/base36.h>
|
||||||
|
#include <util/critbit.h>
|
||||||
#include <util/event.h>
|
#include <util/event.h>
|
||||||
#include <util/functions.h>
|
#include <util/functions.h>
|
||||||
#include <util/goodies.h>
|
#include <util/goodies.h>
|
||||||
|
@ -55,13 +56,11 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
resource_type *resourcetypes;
|
static critbit_tree cb_resources;
|
||||||
|
static critbit_tree cb_items;
|
||||||
luxury_type *luxurytypes;
|
luxury_type *luxurytypes;
|
||||||
potion_type *potiontypes;
|
potion_type *potiontypes;
|
||||||
|
|
||||||
#define IMAXHASH 127
|
|
||||||
static item_type *itemtypes[IMAXHASH];
|
|
||||||
|
|
||||||
static int res_changeaura(unit * u, const resource_type * rtype, int delta)
|
static int res_changeaura(unit * u, const resource_type * rtype, int delta)
|
||||||
{
|
{
|
||||||
assert(rtype != NULL);
|
assert(rtype != NULL);
|
||||||
|
@ -173,14 +172,13 @@ resource_type *new_resourcetype(const char **names, const char **appearances,
|
||||||
|
|
||||||
void it_register(item_type * itype)
|
void it_register(item_type * itype)
|
||||||
{
|
{
|
||||||
int hash = hashstring(itype->rtype->_name[0]);
|
char buffer[64];
|
||||||
int key = hash % IMAXHASH;
|
const char * name = itype->rtype->_name[0];
|
||||||
item_type **p_itype = &itemtypes[key];
|
size_t len = strlen(name);
|
||||||
while (*p_itype && *p_itype != itype)
|
|
||||||
p_itype = &(*p_itype)->next;
|
assert(len<sizeof(buffer)-sizeof(itype));
|
||||||
if (*p_itype == NULL) {
|
cb_new_kv(name, &itype, sizeof(itype), buffer);
|
||||||
itype->rtype->itype = itype;
|
if (cb_insert(&cb_items, buffer, len+1+sizeof(itype))) {
|
||||||
*p_itype = itype;
|
|
||||||
rt_register(itype->rtype);
|
rt_register(itype->rtype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,16 +292,13 @@ potion_type *new_potiontype(item_type * itype, int level)
|
||||||
|
|
||||||
void rt_register(resource_type * rtype)
|
void rt_register(resource_type * rtype)
|
||||||
{
|
{
|
||||||
resource_type **prtype = &resourcetypes;
|
char buffer[64];
|
||||||
|
const char * name = rtype->_name[0];
|
||||||
|
size_t len = strlen(name);
|
||||||
|
|
||||||
if (!rtype->hashkey) {
|
assert(len<sizeof(buffer)-sizeof(rtype));
|
||||||
rtype->hashkey = hashstring(rtype->_name[0]);
|
cb_new_kv(name, &rtype, sizeof(rtype), buffer);
|
||||||
}
|
cb_insert(&cb_resources, buffer, len+1+sizeof(rtype));
|
||||||
while (*prtype && *prtype != rtype)
|
|
||||||
prtype = &(*prtype)->next;
|
|
||||||
if (*prtype == NULL) {
|
|
||||||
*prtype = rtype;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const resource_type *item2resource(const item_type * itype)
|
const resource_type *item2resource(const item_type * itype)
|
||||||
|
@ -347,17 +342,13 @@ const potion_type *resource2potion(const resource_type * rtype)
|
||||||
|
|
||||||
resource_type *rt_find(const char *name)
|
resource_type *rt_find(const char *name)
|
||||||
{
|
{
|
||||||
unsigned int hash = hashstring(name);
|
const void * matches;
|
||||||
resource_type *rtype;
|
resource_type *result = 0;
|
||||||
|
|
||||||
for (rtype = resourcetypes; rtype; rtype = rtype->next) {
|
if (cb_find_prefix(&cb_resources, name, strlen(name)+1, &matches, 1, 0)) {
|
||||||
if (rtype->hashkey == hash && !strcmp(rtype->_name[0], name))
|
cb_get_kv(matches, &result, sizeof(result));
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (!rtype) {
|
return result;
|
||||||
log_warning("rt_find: unknown resource '%s'\n", name);
|
|
||||||
}
|
|
||||||
return rtype;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *it_aliases[][2] = {
|
static const char *it_aliases[][2] = {
|
||||||
|
@ -387,23 +378,13 @@ static const char *it_alias(const char *zname)
|
||||||
item_type *it_find(const char *zname)
|
item_type *it_find(const char *zname)
|
||||||
{
|
{
|
||||||
const char *name = it_alias(zname);
|
const char *name = it_alias(zname);
|
||||||
unsigned int hash = hashstring(name);
|
const void * matches;
|
||||||
item_type *itype;
|
item_type *result = 0;
|
||||||
unsigned int key = hash % IMAXHASH;
|
|
||||||
|
|
||||||
for (itype = itemtypes[key]; itype; itype = itype->next) {
|
if (cb_find_prefix(&cb_items, name, strlen(name)+1, &matches, 1, 0)) {
|
||||||
if (itype->rtype->hashkey == hash
|
cb_get_kv(matches, &result, sizeof(result));
|
||||||
&& strcmp(itype->rtype->_name[0], name) == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (itype == NULL) {
|
return result;
|
||||||
for (itype = itemtypes[key]; itype; itype = itype->next) {
|
|
||||||
if (strcmp(itype->rtype->_name[1], name) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return itype;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item **i_find(item ** i, const item_type * it)
|
item **i_find(item ** i, const item_type * it)
|
||||||
|
@ -1066,10 +1047,11 @@ int change_money(unit * u, int v)
|
||||||
}
|
}
|
||||||
|
|
||||||
static local_names *rnames;
|
static local_names *rnames;
|
||||||
|
#define CB_BATCHSIZE 16
|
||||||
const resource_type *findresourcetype(const char *name,
|
const resource_type *findresourcetype(const char *name,
|
||||||
const struct locale *lang)
|
const struct locale *lang)
|
||||||
{
|
{
|
||||||
|
const void * matches[CB_BATCHSIZE];
|
||||||
local_names *rn = rnames;
|
local_names *rn = rnames;
|
||||||
variant token;
|
variant token;
|
||||||
|
|
||||||
|
@ -1079,21 +1061,30 @@ const resource_type *findresourcetype(const char *name,
|
||||||
rn = rn->next;
|
rn = rn->next;
|
||||||
}
|
}
|
||||||
if (!rn) {
|
if (!rn) {
|
||||||
const resource_type *rtl = resourcetypes;
|
int m, offset = 0;
|
||||||
rn = calloc(sizeof(local_names), 1);
|
rn = (local_names *)calloc(1, sizeof(local_names));
|
||||||
rn->next = rnames;
|
rn->next = rnames;
|
||||||
rn->lang = lang;
|
rn->lang = lang;
|
||||||
while (rtl) {
|
do {
|
||||||
token.v = (void *)rtl;
|
m = cb_find_prefix(&cb_resources, "", 1, matches, CB_BATCHSIZE, offset);
|
||||||
addtoken(&rn->names, locale_string(lang, rtl->_name[0]), token);
|
if (m) {
|
||||||
addtoken(&rn->names, locale_string(lang, rtl->_name[1]), token);
|
int i;
|
||||||
rtl = rtl->next;
|
offset += m;
|
||||||
}
|
for (i=0;i!=m;++i) {
|
||||||
|
resource_type *rtype;
|
||||||
|
cb_get_kv(matches[i], &rtype, sizeof(rtype));
|
||||||
|
token.v = (void *)rtype;
|
||||||
|
addtoken(&rn->names, locale_string(lang, rtype->_name[0]), token);
|
||||||
|
addtoken(&rn->names, locale_string(lang, rtype->_name[1]), token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (m==CB_BATCHSIZE);
|
||||||
rnames = rn;
|
rnames = rn;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (findtoken(rn->names, name, &token) == E_TOK_NOMATCH)
|
if (findtoken(rn->names, name, &token) == E_TOK_NOMATCH) {
|
||||||
return NULL;
|
return 0;
|
||||||
|
}
|
||||||
return (const resource_type *)token.v;
|
return (const resource_type *)token.v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1103,64 +1094,43 @@ attrib_type at_showitem = {
|
||||||
|
|
||||||
static local_names *inames;
|
static local_names *inames;
|
||||||
|
|
||||||
void init_itemnames(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; localenames[i]; ++i) {
|
|
||||||
const struct locale *lang = find_locale(localenames[i]);
|
|
||||||
boolean exist = false;
|
|
||||||
local_names *in = inames;
|
|
||||||
|
|
||||||
while (in != NULL) {
|
|
||||||
if (in->lang == lang) {
|
|
||||||
exist = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
in = in->next;
|
|
||||||
}
|
|
||||||
if (in == NULL)
|
|
||||||
in = calloc(sizeof(local_names), 1);
|
|
||||||
in->next = inames;
|
|
||||||
in->lang = lang;
|
|
||||||
|
|
||||||
if (!exist) {
|
|
||||||
int key;
|
|
||||||
for (key = 0; key != IMAXHASH; ++key) {
|
|
||||||
const item_type *itl;
|
|
||||||
for (itl = itemtypes[key]; itl; itl = itl->next) {
|
|
||||||
variant var;
|
|
||||||
const char *iname = locale_string(lang, itl->rtype->_name[0]);
|
|
||||||
if (findtoken(in->names, iname, &var) == E_TOK_NOMATCH
|
|
||||||
|| var.v != itl) {
|
|
||||||
var.v = (void *)itl;
|
|
||||||
addtoken(&in->names, iname, var);
|
|
||||||
addtoken(&in->names, locale_string(lang, itl->rtype->_name[1]),
|
|
||||||
var);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inames = in;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const item_type *finditemtype(const char *name, const struct locale *lang)
|
const item_type *finditemtype(const char *name, const struct locale *lang)
|
||||||
{
|
{
|
||||||
|
const void * matches[CB_BATCHSIZE];
|
||||||
local_names *in = inames;
|
local_names *in = inames;
|
||||||
variant var;
|
variant token;
|
||||||
|
|
||||||
while (in != NULL) {
|
while (in) {
|
||||||
if (in->lang == lang)
|
if (in->lang == lang)
|
||||||
break;
|
break;
|
||||||
in = in->next;
|
in = in->next;
|
||||||
}
|
}
|
||||||
if (in == NULL) {
|
if (!in) {
|
||||||
init_itemnames();
|
int m, offset = 0;
|
||||||
for (in = inames; in->lang != lang; in = in->next) ;
|
in = (local_names *)calloc(1, sizeof(local_names));
|
||||||
|
in->next = inames;
|
||||||
|
in->lang = lang;
|
||||||
|
do {
|
||||||
|
m = cb_find_prefix(&cb_items, "", 1, matches, CB_BATCHSIZE, offset);
|
||||||
|
if (m) {
|
||||||
|
int i;
|
||||||
|
offset += m;
|
||||||
|
for (i=0;i!=m;++i) {
|
||||||
|
item_type *itype;
|
||||||
|
cb_get_kv(matches[i], &itype, sizeof(itype));
|
||||||
|
token.v = (void *)itype;
|
||||||
|
addtoken(&in->names, locale_string(lang, itype->rtype->_name[0]), token);
|
||||||
|
addtoken(&in->names, locale_string(lang, itype->rtype->_name[1]), token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (m==CB_BATCHSIZE);
|
||||||
|
inames = in;
|
||||||
}
|
}
|
||||||
if (findtoken(in->names, name, &var) == E_TOK_NOMATCH)
|
|
||||||
return NULL;
|
if (findtoken(in->names, name, &token) == E_TOK_NOMATCH) {
|
||||||
return (const item_type *)var.v;
|
return 0;
|
||||||
|
}
|
||||||
|
return (const item_type *)token.v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_resourcelimit(attrib * a)
|
static void init_resourcelimit(attrib * a)
|
||||||
|
@ -1197,31 +1167,38 @@ static item *default_spoil(const struct race *rc, int size)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DISABLE_TESTS
|
#ifndef DISABLE_TESTS
|
||||||
|
int free_itype_cb(const void * match, const void * key, size_t keylen, void *cbdata) {
|
||||||
|
item_type *itype;
|
||||||
|
cb_get_kv(match, &itype, sizeof(itype));
|
||||||
|
free(itype->construction);
|
||||||
|
free(itype);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int free_rtype_cb(const void * match, const void * key, size_t keylen, void *cbdata) {
|
||||||
|
resource_type *rtype;
|
||||||
|
cb_get_kv(match, &rtype, sizeof(rtype));
|
||||||
|
free(rtype->_name[0]);
|
||||||
|
free(rtype->_name[1]);
|
||||||
|
free(rtype->_appearance[0]);
|
||||||
|
free(rtype->_appearance[1]);
|
||||||
|
free(rtype);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void test_clear_resources(void)
|
void test_clear_resources(void)
|
||||||
{
|
{
|
||||||
int i;
|
memset((void *)olditemtype, 0, sizeof(olditemtype));
|
||||||
|
memset((void *)oldresourcetype, 0, sizeof(oldresourcetype));
|
||||||
|
memset((void *)oldpotiontype, 0, sizeof(oldpotiontype));
|
||||||
|
|
||||||
for (i=0;i!=IMAXHASH;++i) {
|
cb_foreach(&cb_items, "", 0, free_itype_cb, 0);
|
||||||
item_type * itype = itemtypes[i];
|
cb_clear(&cb_items);
|
||||||
if (itype) {
|
cb_foreach(&cb_resources, "", 0, free_rtype_cb, 0);
|
||||||
itemtypes[i] = 0;
|
cb_clear(&cb_resources);
|
||||||
free(itype->construction);
|
|
||||||
free(itype);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (resourcetypes) {
|
r_hp = r_silver = r_aura = r_permaura = r_unit = 0;
|
||||||
resource_type * rtype = resourcetypes;
|
i_silver = 0;
|
||||||
resourcetypes = rtype->next;
|
|
||||||
free(rtype->_name[0]);
|
|
||||||
free(rtype->_name[1]);
|
|
||||||
free(rtype->_appearance[0]);
|
|
||||||
free(rtype->_appearance[1]);
|
|
||||||
free(rtype);
|
|
||||||
}
|
|
||||||
resourcetypes = 0;
|
|
||||||
r_hp = 0;
|
|
||||||
init_resources();
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -69,15 +69,13 @@ extern "C" {
|
||||||
rtype_name name;
|
rtype_name name;
|
||||||
/* --- pointers --- */
|
/* --- pointers --- */
|
||||||
struct attrib *attribs;
|
struct attrib *attribs;
|
||||||
struct resource_type *next;
|
|
||||||
unsigned int hashkey;
|
|
||||||
struct item_type *itype;
|
struct item_type *itype;
|
||||||
struct potion_type *ptype;
|
struct potion_type *ptype;
|
||||||
struct luxury_type *ltype;
|
struct luxury_type *ltype;
|
||||||
struct weapon_type *wtype;
|
struct weapon_type *wtype;
|
||||||
struct armor_type *atype;
|
struct armor_type *atype;
|
||||||
} resource_type;
|
} resource_type;
|
||||||
extern resource_type *resourcetypes;
|
|
||||||
extern const char *resourcename(const resource_type * rtype, int flags);
|
extern const char *resourcename(const resource_type * rtype, int flags);
|
||||||
extern const resource_type *findresourcetype(const char *name,
|
extern const resource_type *findresourcetype(const char *name,
|
||||||
const struct locale *lang);
|
const struct locale *lang);
|
||||||
|
@ -142,12 +140,9 @@ extern "C" {
|
||||||
#if SCORE_MODULE
|
#if SCORE_MODULE
|
||||||
int score;
|
int score;
|
||||||
#endif
|
#endif
|
||||||
struct item_type *next;
|
|
||||||
} item_type;
|
} item_type;
|
||||||
|
|
||||||
extern const item_type *finditemtype(const char *name,
|
extern const item_type *finditemtype(const char *name, const struct locale *lang);
|
||||||
const struct locale *lang);
|
|
||||||
extern void init_itemnames(void);
|
|
||||||
|
|
||||||
typedef struct luxury_type {
|
typedef struct luxury_type {
|
||||||
struct luxury_type *next;
|
struct luxury_type *next;
|
||||||
|
|
|
@ -7,19 +7,19 @@
|
||||||
|
|
||||||
void test_resource_type(CuTest * tc)
|
void test_resource_type(CuTest * tc)
|
||||||
{
|
{
|
||||||
resource_type *rtype, *rherp;
|
resource_type *rtype;
|
||||||
const char *names[2] = { 0 , 0 };
|
const char *names[2] = { 0 , 0 };
|
||||||
|
|
||||||
CuAssertPtrEquals(tc, 0, rt_find("herpderp"));
|
CuAssertPtrEquals(tc, 0, rt_find("herpderp"));
|
||||||
|
|
||||||
names[0] = "herpderp";
|
names[0] = "herpderp";
|
||||||
rtype = new_resourcetype(names, NULL, RTF_NONE);
|
new_resourcetype(names, NULL, RTF_NONE);
|
||||||
names[0] = "herp";
|
names[0] = "herp";
|
||||||
rherp = new_resourcetype(names, NULL, RTF_NONE);
|
|
||||||
names[0] = "herpes";
|
|
||||||
rtype = new_resourcetype(names, NULL, RTF_NONE);
|
rtype = new_resourcetype(names, NULL, RTF_NONE);
|
||||||
|
names[0] = "herpes";
|
||||||
|
new_resourcetype(names, NULL, RTF_NONE);
|
||||||
|
|
||||||
CuAssertPtrEquals(tc, rherp, rt_find("herp"));
|
CuAssertPtrEquals(tc, rtype, rt_find("herp"));
|
||||||
}
|
}
|
||||||
|
|
||||||
CuSuite *get_item_suite(void)
|
CuSuite *get_item_suite(void)
|
||||||
|
|
18
src/tests.c
18
src/tests.c
|
@ -4,6 +4,7 @@
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
|
|
||||||
|
#include "tests_test.c"
|
||||||
#include <util/base36_test.c>
|
#include <util/base36_test.c>
|
||||||
#include <util/functions_test.c>
|
#include <util/functions_test.c>
|
||||||
#include <util/quicklist_test.c>
|
#include <util/quicklist_test.c>
|
||||||
|
@ -38,22 +39,26 @@ int RunAllTests(void)
|
||||||
int flags = log_flags;
|
int flags = log_flags;
|
||||||
|
|
||||||
log_flags = LOG_FLUSH | LOG_CPERROR;
|
log_flags = LOG_FLUSH | LOG_CPERROR;
|
||||||
init_resources();
|
|
||||||
|
|
||||||
|
/* self-test */
|
||||||
|
CuSuiteAddSuite(suite, get_tests_suite());
|
||||||
|
/* util */
|
||||||
CuSuiteAddSuite(suite, get_base36_suite());
|
CuSuiteAddSuite(suite, get_base36_suite());
|
||||||
CuSuiteAddSuite(suite, get_quicklist_suite());
|
CuSuiteAddSuite(suite, get_quicklist_suite());
|
||||||
CuSuiteAddSuite(suite, get_functions_suite());
|
CuSuiteAddSuite(suite, get_functions_suite());
|
||||||
CuSuiteAddSuite(suite, get_umlaut_suite());
|
CuSuiteAddSuite(suite, get_umlaut_suite());
|
||||||
|
/* kernel */
|
||||||
CuSuiteAddSuite(suite, get_curse_suite());
|
CuSuiteAddSuite(suite, get_curse_suite());
|
||||||
CuSuiteAddSuite(suite, get_market_suite());
|
|
||||||
CuSuiteAddSuite(suite, get_item_suite());
|
CuSuiteAddSuite(suite, get_item_suite());
|
||||||
CuSuiteAddSuite(suite, get_move_suite());
|
CuSuiteAddSuite(suite, get_move_suite());
|
||||||
CuSuiteAddSuite(suite, get_reports_suite());
|
CuSuiteAddSuite(suite, get_reports_suite());
|
||||||
CuSuiteAddSuite(suite, get_ship_suite());
|
CuSuiteAddSuite(suite, get_ship_suite());
|
||||||
CuSuiteAddSuite(suite, get_building_suite());
|
CuSuiteAddSuite(suite, get_building_suite());
|
||||||
CuSuiteAddSuite(suite, get_spell_suite());
|
CuSuiteAddSuite(suite, get_spell_suite());
|
||||||
CuSuiteAddSuite(suite, get_laws_suite());
|
|
||||||
CuSuiteAddSuite(suite, get_battle_suite());
|
CuSuiteAddSuite(suite, get_battle_suite());
|
||||||
|
/* gamecode */
|
||||||
|
CuSuiteAddSuite(suite, get_market_suite());
|
||||||
|
CuSuiteAddSuite(suite, get_laws_suite());
|
||||||
|
|
||||||
CuSuiteRun(suite);
|
CuSuiteRun(suite);
|
||||||
CuSuiteSummary(suite, output);
|
CuSuiteSummary(suite, output);
|
||||||
|
@ -157,9 +162,12 @@ void test_create_world(void)
|
||||||
building_type *btype;
|
building_type *btype;
|
||||||
ship_type *stype;
|
ship_type *stype;
|
||||||
item_type * itype;
|
item_type * itype;
|
||||||
const char * names[2] = { "horse", "horse_p" };
|
const char * horses[2] = { "horse", "horse_p" };
|
||||||
|
|
||||||
itype = test_create_itemtype(names);
|
init_resources();
|
||||||
|
assert(!olditemtype[I_HORSE]);
|
||||||
|
|
||||||
|
itype = test_create_itemtype(horses);
|
||||||
olditemtype[I_HORSE] = itype;
|
olditemtype[I_HORSE] = itype;
|
||||||
|
|
||||||
t_plain = test_create_terrain("plain", LAND_REGION | FOREST_REGION | WALK_INTO | CAVALRY_REGION);
|
t_plain = test_create_terrain("plain", LAND_REGION | FOREST_REGION | WALK_INTO | CAVALRY_REGION);
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
#include <kernel/item.h>
|
||||||
|
#include <kernel/region.h>
|
||||||
|
|
||||||
|
#include <cutest/CuTest.h>
|
||||||
|
|
||||||
|
static void test_recreate_world(CuTest * tc)
|
||||||
|
{
|
||||||
|
test_cleanup();
|
||||||
|
CuAssertPtrEquals(tc, 0, it_find("money"));
|
||||||
|
CuAssertPtrEquals(tc, 0, it_find("horse"));
|
||||||
|
test_create_world();
|
||||||
|
CuAssertPtrNotNull(tc, it_find("money"));
|
||||||
|
CuAssertPtrNotNull(tc, it_find("horse"));
|
||||||
|
CuAssertPtrNotNull(tc, findregion(0, 0));
|
||||||
|
test_cleanup();
|
||||||
|
CuAssertPtrEquals(tc, 0, it_find("money"));
|
||||||
|
CuAssertPtrEquals(tc, 0, it_find("horse"));
|
||||||
|
CuAssertPtrEquals(tc, 0, findregion(0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
CuSuite *get_tests_suite(void)
|
||||||
|
{
|
||||||
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
SUITE_ADD_TEST(suite, test_recreate_world);
|
||||||
|
return suite;
|
||||||
|
}
|
|
@ -85,6 +85,7 @@ void cb_clear(critbit_tree * cb)
|
||||||
{
|
{
|
||||||
if (cb->root) {
|
if (cb->root) {
|
||||||
cb_free_node(cb->root);
|
cb_free_node(cb->root);
|
||||||
|
cb->root = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,6 +167,36 @@ int cb_insert(critbit_tree * cb, const void * key, size_t keylen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void * cb_find_top_i(critbit_tree * cb, const void * key, size_t keylen)
|
||||||
|
{
|
||||||
|
void *ptr, *top = 0;
|
||||||
|
assert(key);
|
||||||
|
|
||||||
|
if (!cb->root) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for (ptr=cb->root, top=cb->root;;) {
|
||||||
|
void * last = ptr;
|
||||||
|
if (decode_pointer(&ptr)==INTERNAL_NODE) {
|
||||||
|
struct critbit_node * node = (struct critbit_node *)ptr;
|
||||||
|
int branch;
|
||||||
|
if (keylen<=node->byte) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
unsigned char * bytes = (unsigned char *)key;
|
||||||
|
top = last;
|
||||||
|
branch = (1+((bytes[node->byte]|node->mask)&0xFF))>>8;
|
||||||
|
ptr = node->child[branch];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* we reached an external node before exhausting the key length */
|
||||||
|
top = last;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
|
||||||
static int cb_find_prefix_i(void * ptr, const void * key, size_t keylen, const void ** 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);
|
||||||
|
@ -196,34 +227,45 @@ static int cb_find_prefix_i(void * ptr, const void * key, size_t keylen, const v
|
||||||
|
|
||||||
int cb_find_prefix(critbit_tree * cb, const void * key, size_t keylen, const void ** 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;
|
if (numresults>0) {
|
||||||
assert(key);
|
void *top = cb_find_top_i(cb, key, keylen);
|
||||||
|
if (top) {
|
||||||
if (!cb->root || !numresults) {
|
/* recursively add all children except the ones from [0-offset) of top to the results */
|
||||||
return 0;
|
return cb_find_prefix_i(top, key, keylen, results, numresults, &offset, 0);
|
||||||
}
|
|
||||||
for (ptr=cb->root, top=cb->root;;) {
|
|
||||||
void * last = ptr;
|
|
||||||
if (decode_pointer(&ptr)==INTERNAL_NODE) {
|
|
||||||
struct critbit_node * node = (struct critbit_node *)ptr;
|
|
||||||
int branch;
|
|
||||||
if (keylen<=node->byte) {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
unsigned char * bytes = (unsigned char *)key;
|
|
||||||
top = last;
|
|
||||||
branch = (1+((bytes[node->byte]|node->mask)&0xFF))>>8;
|
|
||||||
ptr = node->child[branch];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* we reached an external node before exhausting the key length */
|
|
||||||
top = last;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cb_foreach_i(void * ptr, const void * key, size_t keylen, int (*match_cb)(const void * match, const void * key, size_t keylen, void *), void *data)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if (decode_pointer(&ptr)==INTERNAL_NODE) {
|
||||||
|
struct critbit_node * node = (struct critbit_node *)ptr;
|
||||||
|
result = cb_foreach_i(node->child[0], key, keylen, match_cb, data);
|
||||||
|
if (!result) {
|
||||||
|
result = cb_foreach_i(node->child[1], key, keylen, match_cb, data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* reached an external node */
|
||||||
|
void * match;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
from_external_node(ptr, &match, &len);
|
||||||
|
if (len>=keylen && memcmp(key, match, keylen)==0) {
|
||||||
|
return match_cb(match, key, keylen, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cb_foreach(critbit_tree * cb, const void * key, size_t keylen, int (*match_cb)(const void * match, const void * key, size_t keylen, void *), void *data)
|
||||||
|
{
|
||||||
|
void *top = cb_find_top_i(cb, key, keylen);
|
||||||
if (top) {
|
if (top) {
|
||||||
/* recursively add all children except the ones from [0-offset) of top to the results */
|
/* recursively add all children except the ones from [0-offset) of top to the results */
|
||||||
return cb_find_prefix_i(top, key, keylen, results, numresults, &offset, 0);
|
return cb_foreach_i(top, key, keylen, match_cb, data);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ int cb_insert(critbit_tree * cb, const void * key, size_t keylen);
|
||||||
const void * 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 void ** 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);
|
||||||
|
int cb_foreach(critbit_tree * cb, const void * key, size_t keylen, int (*match_cb)(const void * match, const void * key, size_t keylen, void *), void *data);
|
||||||
void cb_clear(critbit_tree * cb);
|
void cb_clear(critbit_tree * cb);
|
||||||
|
|
||||||
#define cb_insert_str(cb, key) \
|
#define cb_insert_str(cb, key) \
|
||||||
|
|
Loading…
Reference in New Issue