forked from github/server
remove viewrange, because it's not used very much (was used for one quest only)
add my crit-bit implementation. to be used soon.
This commit is contained in:
parent
e272a00994
commit
53bc4eee11
12 changed files with 357 additions and 128 deletions
|
@ -1,75 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (c) 1998-2010, Enno Rehling <enno@eressea.de>
|
|
||||||
Katja Zedel <katze@felidae.kn-bremen.de
|
|
||||||
Christian Schlittchen <corwin@amber.kn-bremen.de>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#include <platform.h>
|
|
||||||
#include "viewrange.h"
|
|
||||||
|
|
||||||
/* util includes */
|
|
||||||
#include <util/attrib.h>
|
|
||||||
#include <util/functions.h>
|
|
||||||
#include <util/storage.h>
|
|
||||||
|
|
||||||
/* libc includes */
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
static void
|
|
||||||
a_writefunction(const struct attrib *a, const void *owner,
|
|
||||||
struct storage *store)
|
|
||||||
{
|
|
||||||
const char *str = get_functionname((pf_generic) a->data.f);
|
|
||||||
store->w_tok(store, str);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int a_readfunction(struct attrib *a, void *owner, struct storage *store)
|
|
||||||
/* return 1 on success, 0 if attrib needs removal */
|
|
||||||
{
|
|
||||||
char buf[64];
|
|
||||||
store->r_tok_buf(store, buf, sizeof(buf));
|
|
||||||
a->data.f = get_function(buf);
|
|
||||||
return AT_READ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
attrib_type at_viewrange = {
|
|
||||||
"viewrange",
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
a_writefunction,
|
|
||||||
a_readfunction,
|
|
||||||
};
|
|
||||||
|
|
||||||
attrib *add_viewrange(attrib ** alist, const char *function)
|
|
||||||
{
|
|
||||||
attrib *a = a_find(*alist, &at_viewrange);
|
|
||||||
if (a == NULL)
|
|
||||||
a = a_add(alist, make_viewrange(function));
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
attrib *make_viewrange(const char *function)
|
|
||||||
{
|
|
||||||
attrib *a = a_new(&at_viewrange);
|
|
||||||
a->data.f = get_function(function);
|
|
||||||
assert(a->data.f);
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_viewrange(void)
|
|
||||||
{
|
|
||||||
at_register(&at_viewrange);
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (c) 1998-2010, Enno Rehling <enno@eressea.de>
|
|
||||||
Katja Zedel <katze@felidae.kn-bremen.de
|
|
||||||
Christian Schlittchen <corwin@amber.kn-bremen.de>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef H_ATTRIBUTE_VIEWRANGE
|
|
||||||
#define H_ATTRIBUTE_VIEWRANGE
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern struct attrib_type at_viewrange;
|
|
||||||
|
|
||||||
extern struct attrib *make_viewrange(const char *function);
|
|
||||||
extern struct attrib *add_viewrange(struct attrib **alist,
|
|
||||||
const char *function);
|
|
||||||
extern void init_viewrange(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
|
@ -1,4 +1,3 @@
|
||||||
#include <settings.h>
|
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
@ -54,8 +53,6 @@
|
||||||
#include <attributes/raceprefix.c>
|
#include <attributes/raceprefix.c>
|
||||||
#include <attributes/reduceproduction.c>
|
#include <attributes/reduceproduction.c>
|
||||||
#include <attributes/targetregion.c>
|
#include <attributes/targetregion.c>
|
||||||
#include <attributes/viewrange.c>
|
|
||||||
|
|
||||||
#include <items/artrewards.c>
|
#include <items/artrewards.c>
|
||||||
#include <items/demonseye.c>
|
#include <items/demonseye.c>
|
||||||
#include <items/itemtypes.c>
|
#include <items/itemtypes.c>
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <util/console.c>
|
#include <util/console.c>
|
||||||
#include <util/attrib.c>
|
#include <util/attrib.c>
|
||||||
#include <util/base36.c>
|
#include <util/base36.c>
|
||||||
|
#include <util/critbit.c>
|
||||||
#include <util/crmessage.c>
|
#include <util/crmessage.c>
|
||||||
#include <util/dice.c>
|
#include <util/dice.c>
|
||||||
#include <util/event.c>
|
#include <util/event.c>
|
||||||
|
|
|
@ -26,7 +26,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
/* attributes includes */
|
/* attributes includes */
|
||||||
#include <attributes/overrideroads.h>
|
#include <attributes/overrideroads.h>
|
||||||
#include <attributes/viewrange.h>
|
|
||||||
#include <attributes/otherfaction.h>
|
#include <attributes/otherfaction.h>
|
||||||
#include <attributes/alliance.h>
|
#include <attributes/alliance.h>
|
||||||
#include <attributes/reduceproduction.h>
|
#include <attributes/reduceproduction.h>
|
||||||
|
|
|
@ -180,7 +180,6 @@
|
||||||
<ClCompile Include="attributes\raceprefix.c" />
|
<ClCompile Include="attributes\raceprefix.c" />
|
||||||
<ClCompile Include="attributes\reduceproduction.c" />
|
<ClCompile Include="attributes\reduceproduction.c" />
|
||||||
<ClCompile Include="attributes\targetregion.c" />
|
<ClCompile Include="attributes\targetregion.c" />
|
||||||
<ClCompile Include="attributes\viewrange.c" />
|
|
||||||
<ClCompile Include="kernel\curse_test.c" />
|
<ClCompile Include="kernel\curse_test.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -281,7 +280,6 @@
|
||||||
<ClInclude Include="attributes\raceprefix.h" />
|
<ClInclude Include="attributes\raceprefix.h" />
|
||||||
<ClInclude Include="attributes\reduceproduction.h" />
|
<ClInclude Include="attributes\reduceproduction.h" />
|
||||||
<ClInclude Include="attributes\targetregion.h" />
|
<ClInclude Include="attributes\targetregion.h" />
|
||||||
<ClInclude Include="attributes\viewrange.h" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
|
|
@ -288,9 +288,6 @@
|
||||||
<ClCompile Include="attributes\targetregion.c">
|
<ClCompile Include="attributes\targetregion.c">
|
||||||
<Filter>attributes</Filter>
|
<Filter>attributes</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="attributes\viewrange.c">
|
|
||||||
<Filter>attributes</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="kernel\curse_test.c" />
|
<ClCompile Include="kernel\curse_test.c" />
|
||||||
<ClCompile Include="kernel\move_test.c">
|
<ClCompile Include="kernel\move_test.c">
|
||||||
<Filter>kernel</Filter>
|
<Filter>kernel</Filter>
|
||||||
|
@ -594,8 +591,5 @@
|
||||||
<ClInclude Include="attributes\targetregion.h">
|
<ClInclude Include="attributes\targetregion.h">
|
||||||
<Filter>attributes</Filter>
|
<Filter>attributes</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="attributes\viewrange.h">
|
|
||||||
<Filter>attributes</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -67,7 +67,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include <attributes/follow.h>
|
#include <attributes/follow.h>
|
||||||
#include <attributes/otherfaction.h>
|
#include <attributes/otherfaction.h>
|
||||||
#include <attributes/racename.h>
|
#include <attributes/racename.h>
|
||||||
#include <attributes/viewrange.h>
|
|
||||||
|
|
||||||
boolean nocr = false;
|
boolean nocr = false;
|
||||||
boolean nonr = false;
|
boolean nonr = false;
|
||||||
|
@ -1485,13 +1484,11 @@ static seen_region **prepare_report(faction * f)
|
||||||
if (sr->mode > see_neighbour) {
|
if (sr->mode > see_neighbour) {
|
||||||
region *r = sr->r;
|
region *r = sr->r;
|
||||||
plane *p = rplane(r);
|
plane *p = rplane(r);
|
||||||
|
|
||||||
void (*view) (struct seen_region **, region *, faction *) = view_default;
|
void (*view) (struct seen_region **, region *, faction *) = view_default;
|
||||||
|
|
||||||
if (p && fval(p, PFL_SEESPECIAL)) {
|
if (p && fval(p, PFL_SEESPECIAL)) {
|
||||||
attrib *a = a_find(p->attribs, &at_viewrange);
|
/* TODO: this is not very customizable */
|
||||||
if (a)
|
view = (strcmp(p->name, "Regatta")==0) ? view_regatta : view_neighbours;
|
||||||
view =
|
|
||||||
(void (*)(struct seen_region **, region *, faction *))a->data.f;
|
|
||||||
}
|
}
|
||||||
view(f->seen, r, f);
|
view(f->seen, r, f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,6 +91,7 @@
|
||||||
<ClInclude Include="util\base36.h" />
|
<ClInclude Include="util\base36.h" />
|
||||||
<ClInclude Include="util\bsdstring.h" />
|
<ClInclude Include="util\bsdstring.h" />
|
||||||
<ClInclude Include="util\console.h" />
|
<ClInclude Include="util\console.h" />
|
||||||
|
<ClInclude Include="util\critbit.h" />
|
||||||
<ClInclude Include="util\crmessage.h" />
|
<ClInclude Include="util\crmessage.h" />
|
||||||
<ClInclude Include="util\event.h" />
|
<ClInclude Include="util\event.h" />
|
||||||
<ClInclude Include="util\eventbus.h" />
|
<ClInclude Include="util\eventbus.h" />
|
||||||
|
@ -125,12 +126,14 @@
|
||||||
<ClCompile Include="util\base36_test.c" />
|
<ClCompile Include="util\base36_test.c" />
|
||||||
<ClCompile Include="util\bsdstring.c" />
|
<ClCompile Include="util\bsdstring.c" />
|
||||||
<ClCompile Include="util\console.c" />
|
<ClCompile Include="util\console.c" />
|
||||||
|
<ClCompile Include="util\critbit.c" />
|
||||||
<ClCompile Include="util\crmessage.c" />
|
<ClCompile Include="util\crmessage.c" />
|
||||||
<ClCompile Include="util\dice.c" />
|
<ClCompile Include="util\dice.c" />
|
||||||
<ClCompile Include="util\event.c" />
|
<ClCompile Include="util\event.c" />
|
||||||
<ClCompile Include="util\eventbus.c" />
|
<ClCompile Include="util\eventbus.c" />
|
||||||
<ClCompile Include="util\filereader.c" />
|
<ClCompile Include="util\filereader.c" />
|
||||||
<ClCompile Include="util\functions.c" />
|
<ClCompile Include="util\functions.c" />
|
||||||
|
<ClCompile Include="util\functions_test.c" />
|
||||||
<ClCompile Include="util\goodies.c" />
|
<ClCompile Include="util\goodies.c" />
|
||||||
<ClCompile Include="util\language.c" />
|
<ClCompile Include="util\language.c" />
|
||||||
<ClCompile Include="util\listbox.c" />
|
<ClCompile Include="util\listbox.c" />
|
||||||
|
|
|
@ -104,6 +104,9 @@
|
||||||
<ClInclude Include="util\os.h">
|
<ClInclude Include="util\os.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="util\critbit.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="util\attrib.c">
|
<ClCompile Include="util\attrib.c">
|
||||||
|
@ -196,5 +199,11 @@
|
||||||
<ClCompile Include="util\os.c">
|
<ClCompile Include="util\os.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="util\critbit.c">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="util\functions_test.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
286
src/util/critbit.c
Normal file
286
src/util/critbit.c
Normal file
|
@ -0,0 +1,286 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2012, Enno Rehling <enno@eressea.de>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "critbit.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
/* see http://cr.yp.to/critbit.html */
|
||||||
|
struct critbit_node {
|
||||||
|
void * child[2];
|
||||||
|
size_t byte;
|
||||||
|
unsigned char mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EXTERNAL_NODE 0
|
||||||
|
#define INTERNAL_NODE 1
|
||||||
|
|
||||||
|
static int decode_pointer(void ** ptr)
|
||||||
|
{
|
||||||
|
ptrdiff_t numvalue = (char*)*ptr - (char*)0;
|
||||||
|
if (numvalue&1) {
|
||||||
|
*ptr = (void*)(numvalue-1);
|
||||||
|
return EXTERNAL_NODE;
|
||||||
|
}
|
||||||
|
return INTERNAL_NODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void * make_external_node(const void * key, size_t keylen)
|
||||||
|
{
|
||||||
|
char * data = (char *)malloc(sizeof(size_t) + keylen + 1);
|
||||||
|
#ifndef NDEBUG
|
||||||
|
ptrdiff_t numvalue = (char *)data - (char*)0;
|
||||||
|
assert((numvalue&1)==0);
|
||||||
|
#endif
|
||||||
|
memcpy(data, &keylen, sizeof(size_t));
|
||||||
|
memcpy(data+sizeof(size_t), key, keylen);
|
||||||
|
return (void*)(data+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_external_node(void * ptr, void **key, size_t *keylen)
|
||||||
|
{
|
||||||
|
unsigned char * bytes = (unsigned char *)ptr;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
ptrdiff_t numvalue = bytes - (unsigned char*)0;
|
||||||
|
assert(numvalue && (numvalue&1)==0);
|
||||||
|
assert(key && keylen);
|
||||||
|
#endif
|
||||||
|
memcpy(keylen, bytes, sizeof(size_t));
|
||||||
|
*key = bytes+sizeof(size_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct critbit_node * make_internal_node(void)
|
||||||
|
{
|
||||||
|
struct critbit_node *node = (struct critbit_node *)malloc(sizeof(struct critbit_node));
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cb_free_node(void * ptr)
|
||||||
|
{
|
||||||
|
if (decode_pointer(&ptr)==INTERNAL_NODE) {
|
||||||
|
struct critbit_node * node = (struct critbit_node *)ptr;
|
||||||
|
cb_free_node(node->child[0]);
|
||||||
|
cb_free_node(node->child[1]);
|
||||||
|
free(node);
|
||||||
|
} else {
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cb_clear(critbit_tree * cb)
|
||||||
|
{
|
||||||
|
if (cb->root) {
|
||||||
|
cb_free_node(cb->root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cb_less(const struct critbit_node * a, const struct critbit_node * b)
|
||||||
|
{
|
||||||
|
return a->byte<b->byte || (a->byte==b->byte && a->mask < b->mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cb_insert(critbit_tree * cb, const void * key, size_t keylen)
|
||||||
|
{
|
||||||
|
assert(cb);
|
||||||
|
assert(key);
|
||||||
|
if (!cb->root) {
|
||||||
|
cb->root = make_external_node(key, keylen);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
void ** iter = &cb->root;
|
||||||
|
struct critbit_node * prev = 0;
|
||||||
|
for (;;) {
|
||||||
|
void * ptr = *iter;
|
||||||
|
if (decode_pointer(&ptr)==INTERNAL_NODE) {
|
||||||
|
struct critbit_node * node = (struct critbit_node *)ptr;
|
||||||
|
unsigned char * bytes = (unsigned char *)key;
|
||||||
|
int branch = (keylen<=node->byte) ? 0 : ((1+((bytes[node->byte]|node->mask)&0xFF))>>8);
|
||||||
|
iter = &node->child[branch];
|
||||||
|
prev = node;
|
||||||
|
} else {
|
||||||
|
unsigned char *iptr, *bytes = (unsigned char *)key, *ikey = bytes;
|
||||||
|
unsigned int mask, branch;
|
||||||
|
unsigned int byte = 0;
|
||||||
|
size_t len;
|
||||||
|
struct critbit_node * node = make_internal_node();
|
||||||
|
|
||||||
|
from_external_node(ptr, (void**)&iptr, &len);
|
||||||
|
|
||||||
|
while (byte<keylen && byte<len && *ikey==*iptr) {
|
||||||
|
++ikey;
|
||||||
|
++iptr;
|
||||||
|
++byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (byte==keylen && byte==len) {
|
||||||
|
return CB_ENOMORE; /* duplicate entry */
|
||||||
|
}
|
||||||
|
node->byte = byte;
|
||||||
|
mask = *ikey ^ *iptr; /* these are all the bits that differ */
|
||||||
|
mask |= mask>>1;
|
||||||
|
mask |= mask>>2;
|
||||||
|
mask |= mask>>4; /* now, every bit up to the MSB is set to 1 */
|
||||||
|
mask = (mask&~(mask>>1))^0xFF;
|
||||||
|
node->mask = (unsigned char)mask;
|
||||||
|
|
||||||
|
/* find the right place to insert, iff prev's crit-bit is later in the string than new crit-bit */
|
||||||
|
if (prev && cb_less(node, prev)) {
|
||||||
|
for (iter = &cb->root;;) {
|
||||||
|
ptr = *iter;
|
||||||
|
if (decode_pointer(&ptr)==INTERNAL_NODE) {
|
||||||
|
struct critbit_node * next = (struct critbit_node *)ptr;
|
||||||
|
if (cb_less(next, node)) {
|
||||||
|
branch = ((1+((bytes[next->byte]|next->mask)&0xFF))>>8);
|
||||||
|
iter = &next->child[branch];
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(!"should never get here");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
branch = ((1+((*ikey|node->mask)&0xFF))>>8);
|
||||||
|
node->child[branch] = make_external_node(key, keylen);
|
||||||
|
node->child[1-branch] = *iter;
|
||||||
|
*iter = (void *)node;
|
||||||
|
|
||||||
|
return CB_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cb_find_prefix_i(void * ptr, const void * key, size_t keylen, const char ** results, int numresults, int * offset, int next)
|
||||||
|
{
|
||||||
|
assert(next<=numresults);
|
||||||
|
if (next==numresults) {
|
||||||
|
return next;
|
||||||
|
} else if (decode_pointer(&ptr)==INTERNAL_NODE) {
|
||||||
|
struct critbit_node * node = (struct critbit_node *)ptr;
|
||||||
|
next = cb_find_prefix_i(node->child[0], key, keylen, results, numresults, offset, next);
|
||||||
|
if (next<numresults) {
|
||||||
|
next = cb_find_prefix_i(node->child[1], key, keylen, results, numresults, offset, next);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* reached an external node */
|
||||||
|
const char * str;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
from_external_node(ptr, (void**)&str, &len);
|
||||||
|
if (len>=keylen && memcmp(key, str, keylen)==0) {
|
||||||
|
if (*offset>0) {
|
||||||
|
--*offset;
|
||||||
|
} else {
|
||||||
|
results[next++] = str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cb_find_prefix(critbit_tree * cb, const void * key, size_t keylen, const char ** results, int numresults, int offset)
|
||||||
|
{
|
||||||
|
void *ptr, *top = 0;
|
||||||
|
assert(key);
|
||||||
|
|
||||||
|
if (!cb->root || !numresults) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (top) {
|
||||||
|
/* 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 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cb_find(critbit_tree * cb, const void * key, size_t keylen)
|
||||||
|
{
|
||||||
|
void * str;
|
||||||
|
size_t len;
|
||||||
|
unsigned char * bytes = (unsigned char *)key;
|
||||||
|
void * ptr;
|
||||||
|
|
||||||
|
assert(cb);
|
||||||
|
assert(key);
|
||||||
|
if (!cb->root) return CB_ENOMORE;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cb_erase(critbit_tree * cb, const void * key, size_t keylen)
|
||||||
|
{
|
||||||
|
void **iter = &cb->root;
|
||||||
|
void *ptr = *iter;
|
||||||
|
unsigned char * bytes = (unsigned char *)key;
|
||||||
|
|
||||||
|
if (!cb->root) return 0;
|
||||||
|
|
||||||
|
if (decode_pointer(&ptr)==EXTERNAL_NODE) {
|
||||||
|
free(ptr);
|
||||||
|
cb->root = 0;
|
||||||
|
return CB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
struct critbit_node *parent = (struct critbit_node *)ptr;
|
||||||
|
int branch, type;
|
||||||
|
|
||||||
|
branch = (keylen<=parent->byte) ? 0 : ((1+((bytes[parent->byte]|parent->mask)&0xFF))>>8);
|
||||||
|
|
||||||
|
ptr = parent->child[branch];
|
||||||
|
type = decode_pointer(&ptr);
|
||||||
|
if (type==INTERNAL_NODE) {
|
||||||
|
iter = &parent->child[branch];
|
||||||
|
} else {
|
||||||
|
void * str;
|
||||||
|
size_t len;
|
||||||
|
from_external_node(ptr, &str, &len);
|
||||||
|
if (len==keylen && memcmp(key, str, len)==0) {
|
||||||
|
free(ptr);
|
||||||
|
*iter = parent->child[1-branch];
|
||||||
|
return CB_SUCCESS;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
55
src/util/critbit.h
Normal file
55
src/util/critbit.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2012, Enno Rehling <enno@eressea.de>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef _CRITBITT_H
|
||||||
|
#define _CRITBITT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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)
|
||||||
|
#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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
Loading…
Reference in a new issue