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:
Enno Rehling 2012-05-14 14:16:02 -07:00
parent e272a00994
commit 53bc4eee11
12 changed files with 357 additions and 128 deletions

View file

@ -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);
}

View file

@ -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

View file

@ -1,4 +1,3 @@
#include <settings.h>
#include <platform.h>
#include "stdafx.h"
@ -54,8 +53,6 @@
#include <attributes/raceprefix.c>
#include <attributes/reduceproduction.c>
#include <attributes/targetregion.c>
#include <attributes/viewrange.c>
#include <items/artrewards.c>
#include <items/demonseye.c>
#include <items/itemtypes.c>

View file

@ -8,6 +8,7 @@
#include <util/console.c>
#include <util/attrib.c>
#include <util/base36.c>
#include <util/critbit.c>
#include <util/crmessage.c>
#include <util/dice.c>
#include <util/event.c>

View file

@ -26,7 +26,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* attributes includes */
#include <attributes/overrideroads.h>
#include <attributes/viewrange.h>
#include <attributes/otherfaction.h>
#include <attributes/alliance.h>
#include <attributes/reduceproduction.h>

View file

@ -180,7 +180,6 @@
<ClCompile Include="attributes\raceprefix.c" />
<ClCompile Include="attributes\reduceproduction.c" />
<ClCompile Include="attributes\targetregion.c" />
<ClCompile Include="attributes\viewrange.c" />
<ClCompile Include="kernel\curse_test.c" />
</ItemGroup>
<ItemGroup>
@ -281,7 +280,6 @@
<ClInclude Include="attributes\raceprefix.h" />
<ClInclude Include="attributes\reduceproduction.h" />
<ClInclude Include="attributes\targetregion.h" />
<ClInclude Include="attributes\viewrange.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View file

@ -288,9 +288,6 @@
<ClCompile Include="attributes\targetregion.c">
<Filter>attributes</Filter>
</ClCompile>
<ClCompile Include="attributes\viewrange.c">
<Filter>attributes</Filter>
</ClCompile>
<ClCompile Include="kernel\curse_test.c" />
<ClCompile Include="kernel\move_test.c">
<Filter>kernel</Filter>
@ -594,8 +591,5 @@
<ClInclude Include="attributes\targetregion.h">
<Filter>attributes</Filter>
</ClInclude>
<ClInclude Include="attributes\viewrange.h">
<Filter>attributes</Filter>
</ClInclude>
</ItemGroup>
</Project>

View file

@ -67,7 +67,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <attributes/follow.h>
#include <attributes/otherfaction.h>
#include <attributes/racename.h>
#include <attributes/viewrange.h>
boolean nocr = false;
boolean nonr = false;
@ -1485,13 +1484,11 @@ static seen_region **prepare_report(faction * f)
if (sr->mode > see_neighbour) {
region *r = sr->r;
plane *p = rplane(r);
void (*view) (struct seen_region **, region *, faction *) = view_default;
if (p && fval(p, PFL_SEESPECIAL)) {
attrib *a = a_find(p->attribs, &at_viewrange);
if (a)
view =
(void (*)(struct seen_region **, region *, faction *))a->data.f;
/* TODO: this is not very customizable */
view = (strcmp(p->name, "Regatta")==0) ? view_regatta : view_neighbours;
}
view(f->seen, r, f);
}

View file

@ -91,6 +91,7 @@
<ClInclude Include="util\base36.h" />
<ClInclude Include="util\bsdstring.h" />
<ClInclude Include="util\console.h" />
<ClInclude Include="util\critbit.h" />
<ClInclude Include="util\crmessage.h" />
<ClInclude Include="util\event.h" />
<ClInclude Include="util\eventbus.h" />
@ -125,12 +126,14 @@
<ClCompile Include="util\base36_test.c" />
<ClCompile Include="util\bsdstring.c" />
<ClCompile Include="util\console.c" />
<ClCompile Include="util\critbit.c" />
<ClCompile Include="util\crmessage.c" />
<ClCompile Include="util\dice.c" />
<ClCompile Include="util\event.c" />
<ClCompile Include="util\eventbus.c" />
<ClCompile Include="util\filereader.c" />
<ClCompile Include="util\functions.c" />
<ClCompile Include="util\functions_test.c" />
<ClCompile Include="util\goodies.c" />
<ClCompile Include="util\language.c" />
<ClCompile Include="util\listbox.c" />

View file

@ -104,6 +104,9 @@
<ClInclude Include="util\os.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="util\critbit.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="util\attrib.c">
@ -196,5 +199,11 @@
<ClCompile Include="util\os.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="util\critbit.c">
<Filter>Header Files</Filter>
</ClCompile>
<ClCompile Include="util\functions_test.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

286
src/util/critbit.c Normal file
View 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
View 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