From 53bc4eee11cedbca0d541cb29cc8a4cc888cfc14 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 14 May 2012 14:16:02 -0700 Subject: [PATCH] remove viewrange, because it's not used very much (was used for one quest only) add my crit-bit implementation. to be used soon. --- src/attributes/viewrange.c | 75 ---------- src/attributes/viewrange.h | 35 ----- src/build/gamecode.c | 3 - src/build/util.c | 1 + src/gamecode/report.c | 1 - src/kernel.vcxproj | 2 - src/kernel.vcxproj.filters | 6 - src/kernel/reports.c | 9 +- src/util.vcxproj | 3 + src/util.vcxproj.filters | 9 ++ src/util/critbit.c | 286 +++++++++++++++++++++++++++++++++++++ src/util/critbit.h | 55 +++++++ 12 files changed, 357 insertions(+), 128 deletions(-) delete mode 100644 src/attributes/viewrange.c delete mode 100644 src/attributes/viewrange.h create mode 100644 src/util/critbit.c create mode 100644 src/util/critbit.h diff --git a/src/attributes/viewrange.c b/src/attributes/viewrange.c deleted file mode 100644 index be21c0877..000000000 --- a/src/attributes/viewrange.c +++ /dev/null @@ -1,75 +0,0 @@ -/* -Copyright (c) 1998-2010, Enno Rehling - Katja Zedel - -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 -#include "viewrange.h" - -/* util includes */ -#include -#include -#include - -/* libc includes */ -#include - -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); -} diff --git a/src/attributes/viewrange.h b/src/attributes/viewrange.h deleted file mode 100644 index d5e8d57d4..000000000 --- a/src/attributes/viewrange.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -Copyright (c) 1998-2010, Enno Rehling - Katja Zedel - -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 diff --git a/src/build/gamecode.c b/src/build/gamecode.c index 63120bde0..db0797b27 100644 --- a/src/build/gamecode.c +++ b/src/build/gamecode.c @@ -1,4 +1,3 @@ -#include #include #include "stdafx.h" @@ -54,8 +53,6 @@ #include #include #include -#include - #include #include #include diff --git a/src/build/util.c b/src/build/util.c index 8882b9dbc..daddfbcdd 100644 --- a/src/build/util.c +++ b/src/build/util.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/src/gamecode/report.c b/src/gamecode/report.c index 9907dc182..e0ec3cd34 100644 --- a/src/gamecode/report.c +++ b/src/gamecode/report.c @@ -26,7 +26,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* attributes includes */ #include -#include #include #include #include diff --git a/src/kernel.vcxproj b/src/kernel.vcxproj index f71b97588..01d47c948 100644 --- a/src/kernel.vcxproj +++ b/src/kernel.vcxproj @@ -180,7 +180,6 @@ - @@ -281,7 +280,6 @@ - diff --git a/src/kernel.vcxproj.filters b/src/kernel.vcxproj.filters index e5f59818f..5d877a81e 100644 --- a/src/kernel.vcxproj.filters +++ b/src/kernel.vcxproj.filters @@ -288,9 +288,6 @@ attributes - - attributes - kernel @@ -594,8 +591,5 @@ attributes - - attributes - \ No newline at end of file diff --git a/src/kernel/reports.c b/src/kernel/reports.c index f793af654..4a098a25b 100644 --- a/src/kernel/reports.c +++ b/src/kernel/reports.c @@ -67,7 +67,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include -#include 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); } diff --git a/src/util.vcxproj b/src/util.vcxproj index db7f763dc..f0b67638d 100644 --- a/src/util.vcxproj +++ b/src/util.vcxproj @@ -91,6 +91,7 @@ + @@ -125,12 +126,14 @@ + + diff --git a/src/util.vcxproj.filters b/src/util.vcxproj.filters index 685e18404..5f24407e5 100644 --- a/src/util.vcxproj.filters +++ b/src/util.vcxproj.filters @@ -104,6 +104,9 @@ Header Files + + Header Files + @@ -196,5 +199,11 @@ Source Files + + Header Files + + + Source Files + \ No newline at end of file diff --git a/src/util/critbit.c b/src/util/critbit.c new file mode 100644 index 000000000..a9df274f9 --- /dev/null +++ b/src/util/critbit.c @@ -0,0 +1,286 @@ +/* +Copyright (c) 2012, Enno Rehling + +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 +#include +#include + +/* 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->bytebyte || (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 (bytebyte = 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 (nextchild[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; + } + } +} diff --git a/src/util/critbit.h b/src/util/critbit.h new file mode 100644 index 000000000..3eb2b4842 --- /dev/null +++ b/src/util/critbit.h @@ -0,0 +1,55 @@ +/* +Copyright (c) 2012, Enno Rehling + +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 + +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