diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e5ae8de7a..c8a4c4783 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -116,6 +116,7 @@ set (ERESSEA_SRC magic.c market.c morale.c + orderdb.c orderfile.c randenc.c renumber.c diff --git a/src/eressea.c b/src/eressea.c index 2174450eb..b4ae7890f 100755 --- a/src/eressea.c +++ b/src/eressea.c @@ -8,6 +8,7 @@ #include "creport.h" #include "report.h" #include "names.h" +#include "orderdb.h" #include "reports.h" #include "spells.h" #include "vortex.h" @@ -57,10 +58,12 @@ void game_done(void) free_special_directions(); free_locales(); kernel_done(); + orderdb_close(); } void game_init(void) { + orderdb_open(); kernel_init(); register_triggers(); register_xmas(); diff --git a/src/kernel/order.c b/src/kernel/order.c index 88f6313fa..873169493 100644 --- a/src/kernel/order.c +++ b/src/kernel/order.c @@ -14,6 +14,7 @@ #include #include "order.h" +#include "orderdb.h" #include "skill.h" #include "keyword.h" @@ -33,71 +34,6 @@ # define ORD_KEYWORD(ord) (keyword_t)((ord)->command & 0xFFFF) # define OD_STRING(odata) ((odata) ? (odata)->_str : NULL) -typedef struct order_data { - const char *_str; - int _refcount; -} order_data; - -#include - -static critbit_tree cb_orders = { 0 }; -static int auto_id = 0; - -struct cb_entry { - int id; - order_data *data; -}; - -order_data *load_data(int id) { - void * match; - - if (id > 0) { - if (cb_find_prefix(&cb_orders, &id, sizeof(id), &match, 1, 0) > 0) { - struct cb_entry *ent = (struct cb_entry *)match; - order_data * od = ent->data; - ++od->_refcount; - return od; - } - } - return NULL; -} - -int save_data(keyword_t kwd, order_data *od) { - if (od->_str) { - struct cb_entry ent; - ++od->_refcount; - ent.id = ++auto_id; - ent.data = od; - cb_insert(&cb_orders, &ent, sizeof(ent)); - return ent.id; - } - return 0; -} - -static void release_data(order_data * data) -{ - if (data) { - if (--data->_refcount == 0) { - free(data); - } - } -} - -int free_data_cb(const void *match, const void *key, size_t keylen, void *udata) { - struct cb_entry * ent = (struct cb_entry *)match; - order_data *od = ent->data; - if (od->_refcount > 1) { - log_error("refcount=%d for order %d, %s", od->_refcount, ent->id, od->_str); - } - release_data(od); - return 0; -} - -void free_data(void) { - cb_foreach(&cb_orders, NULL, 0, free_data_cb, NULL); - cb_clear(&cb_orders); -} - void replace_order(order ** dlist, order * orig, const order * src) { assert(src); @@ -159,7 +95,7 @@ char* get_command(const order *ord, const struct locale *lang, char *sbuffer, si assert(kwd == K_STUDY && sk != SK_MAGIC && sk < MAXSKILLS); text = skillname(sk, lang); } else { - od = load_data(ord->id); + od = odata_load(ord->id); text = OD_STRING(od); } if (kwd != NOKEYWORD) { @@ -193,7 +129,7 @@ char* get_command(const order *ord, const struct locale *lang, char *sbuffer, si } } if (od) { - release_data(od); + odata_release(od); } if (size > 0) *bufp = 0; return sbuffer; @@ -268,10 +204,10 @@ static int create_data(keyword_t kwd, const char *s, return ((int)sk)-100; } } - /* TODO: between mkdata and release_data, this object is very + /* TODO: between mkdata and odata_release, this object is very * short-lived. */ mkdata(&data, strlen(s), s); - id = save_data(kwd, data); + id = odata_save(kwd, data); release_data(data); return id; } @@ -556,11 +492,11 @@ char *write_order(const order * ord, const struct locale *lang, char *buffer, si else { keyword_t kwd = ORD_KEYWORD(ord); if (kwd == NOKEYWORD) { - order_data *od = load_data(ord->id); + order_data *od = odata_load(ord->id); const char *text = OD_STRING(od); if (text) strlcpy(buffer, (const char *)text, size); else buffer[0] = 0; - release_data(od); + odata_release(od); } else { get_command(ord, lang, buffer, size); @@ -581,7 +517,7 @@ static order_data *parser_od; keyword_t init_order(const struct order *ord, const struct locale *lang) { if (!ord) { - release_data(parser_od); + odata_release(parser_od); parser_od = NULL; return NOKEYWORD; } @@ -589,7 +525,7 @@ keyword_t init_order(const struct order *ord, const struct locale *lang) keyword_t kwd = ORD_KEYWORD(ord); if (parser_od) { /* TODO: warning */ - release_data(parser_od); + odata_release(parser_od); parser_od = NULL; } if (ord->id < 0) { @@ -600,7 +536,7 @@ keyword_t init_order(const struct order *ord, const struct locale *lang) init_tokens_str(skillname(sk, lang)); } else { - parser_od = load_data(ord->id); + parser_od = odata_load(ord->id); init_tokens_str(OD_STRING(parser_od)); } return kwd; @@ -620,6 +556,5 @@ void close_orders(void) { if (parser_od) { (void)init_order(NULL, NULL); } - free_data(); } diff --git a/src/orderdb.c b/src/orderdb.c new file mode 100644 index 000000000..37faeacc4 --- /dev/null +++ b/src/orderdb.c @@ -0,0 +1,78 @@ +#include +#include "orderdb.h" + +#include + +#include + +#include + +static critbit_tree cb_orders = { 0 }; +static int auto_id = 0; + +struct cb_entry { + int id; + order_data *data; +}; + +order_data *odata_load(int id) +{ + void * match; + + if (id > 0) { + if (cb_find_prefix(&cb_orders, &id, sizeof(id), &match, 1, 0) > 0) { + struct cb_entry *ent = (struct cb_entry *)match; + order_data * od = ent->data; + ++od->_refcount; + return od; + } + } + return NULL; +} + +int odata_save(order_data *od) +{ + if (od->_str) { + struct cb_entry ent; + ++od->_refcount; + ent.id = ++auto_id; + ent.data = od; + cb_insert(&cb_orders, &ent, sizeof(ent)); + return ent.id; + } + return 0; +} + +void odata_release(order_data * od) +{ + if (od) { + if (--od->_refcount == 0) { + free(od); + } + } +} + +int free_data_cb(const void *match, const void *key, size_t keylen, void *udata) { + struct cb_entry * ent = (struct cb_entry *)match; + order_data *od = ent->data; + if (od->_refcount > 1) { + log_error("refcount=%d for order %d, %s", od->_refcount, ent->id, od->_str); + } + odata_release(od); + return 0; +} + +void free_data(void) { + cb_foreach(&cb_orders, NULL, 0, free_data_cb, NULL); + cb_clear(&cb_orders); +} + +void orderdb_open(void) +{ + auto_id = 0; +} + +void orderdb_close(void) +{ + free_data(); +} diff --git a/src/orderdb.h b/src/orderdb.h new file mode 100644 index 000000000..be39a642e --- /dev/null +++ b/src/orderdb.h @@ -0,0 +1,23 @@ +#ifndef H_ORDERDB +#define H_ORDERDB + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct order_data { + const char *_str; + int _refcount; + } order_data; + + void orderdb_open(void); + void orderdb_close(void); + + order_data *odata_load(int id); + int odata_save(order_data *od); + void odata_release(order_data * od); + +#ifdef __cplusplus +} +#endif +#endif