diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/db.c | 296 | ||||
-rw-r--r-- | src/common/db.h | 257 | ||||
-rw-r--r-- | src/common/showmsg.c | 2 |
3 files changed, 399 insertions, 156 deletions
diff --git a/src/common/db.c b/src/common/db.c index 481e9db2a..999deea48 100644 --- a/src/common/db.c +++ b/src/common/db.c @@ -40,7 +40,6 @@ * * TODO: * - create test cases to test the database system thoroughly - * - make data an enumeration * - finish this header describing the database system * - create custom database allocator * - make the system thread friendly @@ -48,6 +47,7 @@ * - create a db that organizes itself by splaying * * HISTORY: + * 2012/03/09 - Added enum for data types (int, uint, void*) * 2008/02/19 - Fixed db_obj_get not handling deleted entries correctly. * 2007/11/09 - Added an iterator to the database. * 2006/12/21 - Added 1-node cache to the database. @@ -135,7 +135,7 @@ typedef struct dbn { struct dbn *right; // Node data DBKey key; - void *data; + DBData data; // Other node_color color; unsigned deleted : 1; @@ -221,7 +221,7 @@ typedef struct DBIterator_impl { #if defined(DB_ENABLE_STATS) /** - * Structure with what is counted when the database estatistics are enabled. + * Structure with what is counted when the database statistics are enabled. * @private * @see #DB_ENABLE_STATS * @see #stats @@ -297,6 +297,12 @@ static struct db_stats { uint32 db_i2key; uint32 db_ui2key; uint32 db_str2key; + uint32 db_i2data; + uint32 db_ui2data; + uint32 db_ptr2data; + uint32 db_data2i; + uint32 db_data2ui; + uint32 db_data2ptr; uint32 db_init; uint32 db_final; } stats = { @@ -305,7 +311,8 @@ static struct db_stats { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0 }; #define DB_COUNTSTAT(token) if (stats. ## token != UINT32_MAX) ++stats. ## token #else /* !defined(DB_ENABLE_STATS) */ @@ -399,7 +406,7 @@ static void db_rotate_right(DBNode node, DBNode *root) * @private * @see #db_rotate_left(DBNode,DBNode *) * @see #db_rotate_right(DBNode,DBNode *) - * @see #db_obj_put(DBMap*,DBKey,void *) + * @see #db_obj_put(DBMap*,DBKey,DBData) */ static void db_rebalance(DBNode node, DBNode *root) { @@ -595,13 +602,13 @@ static void db_rebalance_erase(DBNode node, DBNode *root) } /** - * Returns not 0 if the key is considerd to be NULL. + * Returns not 0 if the key is considered to be NULL. * @param type Type of database * @param key Key being tested * @return not 0 if considered NULL, 0 otherwise * @private * @see #db_obj_get(DBMap*,DBKey) - * @see #db_obj_put(DBMap*,DBKey,void *) + * @see #db_obj_put(DBMap*,DBKey,DBData) * @see #db_obj_remove(DBMap*,DBKey) */ static int db_is_key_null(DBType type, DBKey key) @@ -731,7 +738,7 @@ static void db_free_add(DBMap_impl* db, DBNode node, DBNode *root) * @see #struct db_free * @see DBMap_impl#free_list * @see DBMap_impl#free_count - * @see #db_obj_put(DBMap*,DBKey,void*) + * @see #db_obj_put(DBMap*,DBKey,DBData) * @see #db_free_add(DBMap_impl*,DBNode*,DBNode) */ static void db_free_remove(DBMap_impl* db, DBNode node) @@ -1006,7 +1013,7 @@ static unsigned int db_istring_hash(DBKey key, unsigned short maxlen) * @see #DBReleaser * @see #db_default_releaser(DBType,DBOptions) */ -static void db_release_nothing(DBKey key, void *data, DBRelease which) +static void db_release_nothing(DBKey key, DBData data, DBRelease which) { (void)key;(void)data;(void)which;//not used DB_COUNTSTAT(db_release_nothing); @@ -1021,7 +1028,7 @@ static void db_release_nothing(DBKey key, void *data, DBRelease which) * @see #DBReleaser * @see #db_default_release(DBType,DBOptions) */ -static void db_release_key(DBKey key, void *data, DBRelease which) +static void db_release_key(DBKey key, DBData data, DBRelease which) { (void)data;//not used DB_COUNTSTAT(db_release_key); @@ -1034,16 +1041,16 @@ static void db_release_key(DBKey key, void *data, DBRelease which) * @param data Data of the database entry * @param which What is being requested to be released * @protected - * @see #DBKey + * @see #DBData * @see #DBRelease * @see #DBReleaser * @see #db_default_release(DBType,DBOptions) */ -static void db_release_data(DBKey key, void *data, DBRelease which) +static void db_release_data(DBKey key, DBData data, DBRelease which) { (void)key;//not used DB_COUNTSTAT(db_release_data); - if (which&DB_RELEASE_DATA) aFree(data); + if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) aFree(data.u.ptr); } /** @@ -1053,15 +1060,16 @@ static void db_release_data(DBKey key, void *data, DBRelease which) * @param which What is being requested to be released * @protected * @see #DBKey + * @see #DBData * @see #DBRelease * @see #DBReleaser * @see #db_default_release(DBType,DBOptions) */ -static void db_release_both(DBKey key, void *data, DBRelease which) +static void db_release_both(DBKey key, DBData data, DBRelease which) { DB_COUNTSTAT(db_release_both); if (which&DB_RELEASE_KEY) aFree((char*)key.str); // needs to be a pointer - if (which&DB_RELEASE_DATA) aFree(data); + if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) aFree(data.u.ptr); } /*****************************************************************************\ @@ -1075,7 +1083,7 @@ static void db_release_both(DBKey key, void *data, DBRelease which) * dbit_obj_remove - Remove the current entry from the database. * * dbit_obj_destroy - Destroys the iterator, unlocking the database and * * freeing used memory. * - * db_obj_iterator - Return a new databse iterator. * + * db_obj_iterator - Return a new database iterator. * * db_obj_exists - Checks if an entry exists. * * db_obj_get - Get the data identified by the key. * * db_obj_vgetall - Get the data of the matched entries. * @@ -1107,7 +1115,7 @@ static void db_release_both(DBKey key, void *data, DBRelease which) * @protected * @see DBIterator#first */ -void* dbit_obj_first(DBIterator* self, DBKey* out_key) +DBData* dbit_obj_first(DBIterator* self, DBKey* out_key) { DBIterator_impl* it = (DBIterator_impl*)self; @@ -1129,7 +1137,7 @@ void* dbit_obj_first(DBIterator* self, DBKey* out_key) * @protected * @see DBIterator#last */ -void* dbit_obj_last(DBIterator* self, DBKey* out_key) +DBData* dbit_obj_last(DBIterator* self, DBKey* out_key) { DBIterator_impl* it = (DBIterator_impl*)self; @@ -1151,7 +1159,7 @@ void* dbit_obj_last(DBIterator* self, DBKey* out_key) * @protected * @see DBIterator#next */ -void* dbit_obj_next(DBIterator* self, DBKey* out_key) +DBData* dbit_obj_next(DBIterator* self, DBKey* out_key) { DBIterator_impl* it = (DBIterator_impl*)self; DBNode node; @@ -1209,7 +1217,7 @@ void* dbit_obj_next(DBIterator* self, DBKey* out_key) it->node = node; if( out_key ) memcpy(out_key, &node->key, sizeof(DBKey)); - return node->data; + return &node->data; } } } @@ -1227,7 +1235,7 @@ void* dbit_obj_next(DBIterator* self, DBKey* out_key) * @protected * @see DBIterator#prev */ -void* dbit_obj_prev(DBIterator* self, DBKey* out_key) +DBData* dbit_obj_prev(DBIterator* self, DBKey* out_key) { DBIterator_impl* it = (DBIterator_impl*)self; DBNode node; @@ -1286,7 +1294,7 @@ void* dbit_obj_prev(DBIterator* self, DBKey* out_key) it->node = node; if( out_key ) memcpy(out_key, &node->key, sizeof(DBKey)); - return node->data; + return &node->data; } } } @@ -1299,7 +1307,7 @@ void* dbit_obj_prev(DBIterator* self, DBKey* out_key) * The databases entries might have NULL data, so use this to to test if * the iterator is done. * @param self Iterator - * @return true is the entry exists + * @return true if the entry exists * @protected * @see DBIterator#exists */ @@ -1314,19 +1322,20 @@ bool dbit_obj_exists(DBIterator* self) /** * Removes the current entry from the database. * NOTE: {@link DBIterator#exists} will return false until another entry - * is fethed - * Returns the data of the entry. + * is fetched + * Puts data of the removed entry in out_data, if out_data is not NULL. * @param self Iterator - * @return The data of the entry or NULL if not found + * @param out_data Data of the removed entry. + * @return 1 if entry was removed, 0 otherwise * @protected * @see DBMap#remove * @see DBIterator#remove */ -void* dbit_obj_remove(DBIterator* self) +int dbit_obj_remove(DBIterator* self, DBData *out_data) { DBIterator_impl* it = (DBIterator_impl*)self; DBNode node; - void* data = NULL; + int retval = 0; DB_COUNTSTAT(dbit_remove); node = it->node; @@ -1335,11 +1344,13 @@ void* dbit_obj_remove(DBIterator* self) DBMap_impl* db = it->db; if( db->cache == node ) db->cache = NULL; - data = node->data; + if( out_data ) + memcpy(out_data, &node->data, sizeof(DBData)); + retval = 1; db->release(node->key, node->data, DB_RELEASE_DATA); db_free_add(db, node, &db->ht[it->ht_index]); } - return data; + return retval; } /** @@ -1443,19 +1454,19 @@ static bool db_obj_exists(DBMap* self, DBKey key) } /** - * Get the data of the entry identifid by the key. + * Get the data of the entry identified by the key. * @param self Interface of the database * @param key Key that identifies the entry * @return Data of the entry or NULL if not found * @protected * @see DBMap#get */ -static void* db_obj_get(DBMap* self, DBKey key) +static DBData* db_obj_get(DBMap* self, DBKey key) { DBMap_impl* db = (DBMap_impl*)self; DBNode node; int c; - void *data = NULL; + DBData *data = NULL; DB_COUNTSTAT(db_get); if (db == NULL) return NULL; // nullpo candidate @@ -1471,7 +1482,7 @@ static void* db_obj_get(DBMap* self, DBKey key) return NULL; } #endif - return db->cache->data; // cache hit + return &db->cache->data; // cache hit } db_free_lock(db); @@ -1480,7 +1491,7 @@ static void* db_obj_get(DBMap* self, DBKey key) c = db->cmp(key, node->key, db->maxlen); if (c == 0) { if (!(node->deleted)) { - data = node->data; + data = &node->data; db->cache = node; } break; @@ -1510,7 +1521,7 @@ static void* db_obj_get(DBMap* self, DBKey key) * @protected * @see DBMap#vgetall */ -static unsigned int db_obj_vgetall(DBMap* self, void **buf, unsigned int max, DBMatcher match, va_list args) +static unsigned int db_obj_vgetall(DBMap* self, DBData **buf, unsigned int max, DBMatcher match, va_list args) { DBMap_impl* db = (DBMap_impl*)self; unsigned int i; @@ -1534,7 +1545,7 @@ static unsigned int db_obj_vgetall(DBMap* self, void **buf, unsigned int max, DB va_copy(argscopy, args); if (match(node->key, node->data, argscopy) == 0) { if (buf && ret < max) - buf[ret] = node->data; + buf[ret] = &node->data; ret++; } va_end(argscopy); @@ -1579,7 +1590,7 @@ static unsigned int db_obj_vgetall(DBMap* self, void **buf, unsigned int max, DB * @see DBMap#vgetall * @see DBMap#getall */ -static unsigned int db_obj_getall(DBMap* self, void **buf, unsigned int max, DBMatcher match, ...) +static unsigned int db_obj_getall(DBMap* self, DBData **buf, unsigned int max, DBMatcher match, ...) { va_list args; unsigned int ret; @@ -1605,14 +1616,14 @@ static unsigned int db_obj_getall(DBMap* self, void **buf, unsigned int max, DBM * @protected * @see DBMap#vensure */ -static void *db_obj_vensure(DBMap* self, DBKey key, DBCreateData create, va_list args) +static DBData* db_obj_vensure(DBMap* self, DBKey key, DBCreateData create, va_list args) { DBMap_impl* db = (DBMap_impl*)self; DBNode node; DBNode parent = NULL; unsigned int hash; int c = 0; - void *data = NULL; + DBData *data = NULL; DB_COUNTSTAT(db_vensure); if (db == NULL) return NULL; // nullpo candidate @@ -1626,7 +1637,7 @@ static void *db_obj_vensure(DBMap* self, DBKey key, DBCreateData create, va_list } if (db->cache && db->cmp(key, db->cache->key, db->maxlen) == 0) - return db->cache->data; // cache hit + return &db->cache->data; // cache hit db_free_lock(db); hash = db->hash(key, db->maxlen)%HASH_SIZE; @@ -1677,7 +1688,7 @@ static void *db_obj_vensure(DBMap* self, DBKey key, DBCreateData create, va_list if (db->options&DB_OPT_DUP_KEY) { node->key = db_dup_key(db, key); if (db->options&DB_OPT_RELEASE_KEY) - db->release(key, data, DB_RELEASE_KEY); + db->release(key, *data, DB_RELEASE_KEY); } else { node->key = key; } @@ -1685,7 +1696,7 @@ static void *db_obj_vensure(DBMap* self, DBKey key, DBCreateData create, va_list node->data = create(key, argscopy); va_end(argscopy); } - data = node->data; + data = &node->data; db->cache = node; db_free_unlock(db); return data; @@ -1705,13 +1716,13 @@ static void *db_obj_vensure(DBMap* self, DBKey key, DBCreateData create, va_list * @see DBMap#vensure * @see DBMap#ensure */ -static void *db_obj_ensure(DBMap* self, DBKey key, DBCreateData create, ...) +static DBData* db_obj_ensure(DBMap* self, DBKey key, DBCreateData create, ...) { va_list args; - void *ret; + DBData *ret = NULL; DB_COUNTSTAT(db_ensure); - if (self == NULL) return 0; // nullpo candidate + if (self == NULL) return NULL; // nullpo candidate va_start(args, create); ret = self->vensure(self, key, create, args); @@ -1721,47 +1732,47 @@ static void *db_obj_ensure(DBMap* self, DBKey key, DBCreateData create, ...) /** * Put the data identified by the key in the database. - * Returns the previous data if the entry exists or NULL. + * Puts the previous data in out_data, if out_data is not NULL. * NOTE: Uses the new key, the old one is released. * @param self Interface of the database * @param key Key that identifies the data * @param data Data to be put in the database - * @return The previous data if the entry exists or NULL + * @param out_data Previous data if the entry exists + * @return 1 if if the entry already exists, 0 otherwise * @protected * @see #db_malloc_dbn(void) * @see DBMap#put */ -static void *db_obj_put(DBMap* self, DBKey key, void *data) +static int db_obj_put(DBMap* self, DBKey key, DBData data, DBData *out_data) { DBMap_impl* db = (DBMap_impl*)self; DBNode node; DBNode parent = NULL; - int c = 0; + int c = 0, retval = 0; unsigned int hash; - void *old_data = NULL; DB_COUNTSTAT(db_put); - if (db == NULL) return NULL; // nullpo candidate + if (db == NULL) return 0; // nullpo candidate if (db->global_lock) { ShowError("db_put: Database is being destroyed, aborting entry insertion.\n" "Database allocated at %s:%d\n", db->alloc_file, db->alloc_line); - return NULL; // nullpo candidate + return 0; // nullpo candidate } if (!(db->options&DB_OPT_ALLOW_NULL_KEY) && db_is_key_null(db->type, key)) { ShowError("db_put: Attempted to use non-allowed NULL key for db allocated at %s:%d\n",db->alloc_file, db->alloc_line); - return NULL; // nullpo candidate + return 0; // nullpo candidate } - if (!(data || db->options&DB_OPT_ALLOW_NULL_DATA)) { + if (!(db->options&DB_OPT_ALLOW_NULL_DATA) && (data.type == DB_DATA_PTR && data.u.ptr == NULL)) { ShowError("db_put: Attempted to use non-allowed NULL data for db allocated at %s:%d\n",db->alloc_file, db->alloc_line); - return NULL; // nullpo candidate + return 0; // nullpo candidate } if (db->item_count == UINT32_MAX) { ShowError("db_put: item_count overflow, aborting item insertion.\n" "Database allocated at %s:%d", db->alloc_file, db->alloc_line); - return NULL; + return 0; } // search for an equal node db_free_lock(db); @@ -1773,8 +1784,10 @@ static void *db_obj_put(DBMap* self, DBKey key, void *data) db_free_remove(db, node); } else { db->release(node->key, node->data, DB_RELEASE_BOTH); + if (out_data) + memcpy(out_data, &node->data, sizeof(*out_data)); + retval = 1; } - old_data = node->data; break; } parent = node; @@ -1820,39 +1833,39 @@ static void *db_obj_put(DBMap* self, DBKey key, void *data) node->data = data; db->cache = node; db_free_unlock(db); - return old_data; + return retval; } /** * Remove an entry from the database. - * Returns the data of the entry. + * Puts the previous data in out_data, if out_data is not NULL. * NOTE: The key (of the database) is released in {@link #db_free_add(DBMap_impl*,DBNode,DBNode *)}. * @param self Interface of the database * @param key Key that identifies the entry - * @return The data of the entry or NULL if not found + * @param out_data Previous data if the entry exists + * @return 1 if if the entry already exists, 0 otherwise * @protected * @see #db_free_add(DBMap_impl*,DBNode,DBNode *) * @see DBMap#remove */ -static void *db_obj_remove(DBMap* self, DBKey key) +static int db_obj_remove(DBMap* self, DBKey key, DBData *out_data) { DBMap_impl* db = (DBMap_impl*)self; - void *data = NULL; DBNode node; unsigned int hash; - int c = 0; + int c = 0, retval = 0; DB_COUNTSTAT(db_remove); - if (db == NULL) return NULL; // nullpo candidate + if (db == NULL) return 0; // nullpo candidate if (db->global_lock) { ShowError("db_remove: Database is being destroyed. Aborting entry deletion.\n" "Database allocated at %s:%d\n", db->alloc_file, db->alloc_line); - return NULL; // nullpo candidate + return 0; // nullpo candidate } if (!(db->options&DB_OPT_ALLOW_NULL_KEY) && db_is_key_null(db->type, key)) { ShowError("db_remove: Attempted to use non-allowed NULL key for db allocated at %s:%d\n",db->alloc_file, db->alloc_line); - return NULL; // nullpo candidate + return 0; // nullpo candidate } db_free_lock(db); @@ -1863,7 +1876,9 @@ static void *db_obj_remove(DBMap* self, DBKey key) if (!(node->deleted)) { if (db->cache == node) db->cache = NULL; - data = node->data; + if (out_data) + memcpy(out_data, &node->data, sizeof(*out_data)); + retval = 1; db->release(node->key, node->data, DB_RELEASE_DATA); db_free_add(db, node, &db->ht[hash]); } @@ -1875,14 +1890,14 @@ static void *db_obj_remove(DBMap* self, DBKey key) node = node->right; } db_free_unlock(db); - return data; + return retval; } /** * Apply <code>func</code> to every entry in the database. * Returns the sum of values returned by func. * @param self Interface of the database - * @param func Function to be applyed + * @param func Function to be applied * @param args Extra arguments for func * @return Sum of the values returned by func * @protected @@ -1913,7 +1928,7 @@ static int db_obj_vforeach(DBMap* self, DBApply func, va_list args) { va_list argscopy; va_copy(argscopy, args); - sum += func(node->key, node->data, argscopy); + sum += func(node->key, &node->data, argscopy); va_end(argscopy); } if (node->left) { @@ -1966,11 +1981,11 @@ static int db_obj_foreach(DBMap* self, DBApply func, ...) /** * Removes all entries from the database. - * Before deleting an entry, func is applyed to it. + * Before deleting an entry, func is applied to it. * Releases the key and the data. * Returns the sum of values returned by func, if it exists. * @param self Interface of the database - * @param func Function to be applyed to every entry before deleting + * @param func Function to be applied to every entry before deleting * @param args Extra arguments for func * @return Sum of values returned by func * @protected @@ -2010,7 +2025,7 @@ static int db_obj_vclear(DBMap* self, DBApply func, va_list args) { va_list argscopy; va_copy(argscopy, args); - sum += func(node->key, node->data, argscopy); + sum += func(node->key, &node->data, argscopy); va_end(argscopy); } db->release(node->key, node->data, DB_RELEASE_BOTH); @@ -2037,13 +2052,13 @@ static int db_obj_vclear(DBMap* self, DBApply func, va_list args) /** * Just calls {@link DBMap#vclear}. * Removes all entries from the database. - * Before deleting an entry, func is applyed to it. + * Before deleting an entry, func is applied to it. * Releases the key and the data. * Returns the sum of values returned by func, if it exists. * NOTE: This locks the database globally. Any attempt to insert or remove * a database entry will give an error and be aborted (except for clearing). * @param self Interface of the database - * @param func Function to be applyed to every entry before deleting + * @param func Function to be applied to every entry before deleting * @param ... Extra arguments for func * @return Sum of values returned by func * @protected @@ -2066,12 +2081,12 @@ static int db_obj_clear(DBMap* self, DBApply func, ...) /** * Finalize the database, feeing all the memory it uses. - * Before deleting an entry, func is applyed to it. + * Before deleting an entry, func is applied to it. * Returns the sum of values returned by func, if it exists. * NOTE: This locks the database globally. Any attempt to insert or remove * a database entry will give an error and be aborted (except for clearing). * @param self Interface of the database - * @param func Function to be applyed to every entry before deleting + * @param func Function to be applied to every entry before deleting * @param args Extra arguments for func * @return Sum of values returned by func * @protected @@ -2118,13 +2133,13 @@ static int db_obj_vdestroy(DBMap* self, DBApply func, va_list args) /** * Just calls {@link DBMap#db_vdestroy}. * Finalize the database, feeing all the memory it uses. - * Before deleting an entry, func is applyed to it. + * Before deleting an entry, func is applied to it. * Releases the key and the data. * Returns the sum of values returned by func, if it exists. * NOTE: This locks the database globally. Any attempt to insert or remove * a database entry will give an error and be aborted. * @param self Database - * @param func Function to be applyed to every entry before deleting + * @param func Function to be applied to every entry before deleting * @param ... Extra arguments for func * @return Sum of values returned by func * @protected @@ -2225,6 +2240,12 @@ static DBOptions db_obj_options(DBMap* self) * db_i2key - Manual cast from 'int' to 'DBKey'. * db_ui2key - Manual cast from 'unsigned int' to 'DBKey'. * db_str2key - Manual cast from 'unsigned char *' to 'DBKey'. + * db_i2data - Manual cast from 'int' to 'DBData'. + * db_ui2data - Manual cast from 'unsigned int' to 'DBData'. + * db_ptr2data - Manual cast from 'void*' to 'DBData'. + * db_data2i - Gets 'int' value from 'DBData'. + * db_data2ui - Gets 'unsigned int' value from 'DBData'. + * db_data2ptr - Gets 'void*' value from 'DBData'. * db_init - Initializes the database system. * db_final - Finalizes the database system. \*****************************************************************************/ @@ -2313,10 +2334,10 @@ DBHasher db_default_hash(DBType type) * @param options Options of the database * @return Default releaser for the type of database with the specified options * @public - * @see #db_release_nothing(DBKey,void *,DBRelease) - * @see #db_release_key(DBKey,void *,DBRelease) - * @see #db_release_data(DBKey,void *,DBRelease) - * @see #db_release_both(DBKey,void *,DBRelease) + * @see #db_release_nothing(DBKey,DBData,DBRelease) + * @see #db_release_key(DBKey,DBData,DBRelease) + * @see #db_release_data(DBKey,DBData,DBRelease) + * @see #db_release_both(DBKey,DBData,DBRelease) * @see #db_custom_release(DBRelease) */ DBReleaser db_default_release(DBType type, DBOptions options) @@ -2338,10 +2359,10 @@ DBReleaser db_default_release(DBType type, DBOptions options) * @param which Options that specified what the releaser releases * @return Releaser for the specified release options * @public - * @see #db_release_nothing(DBKey,void *,DBRelease) - * @see #db_release_key(DBKey,void *,DBRelease) - * @see #db_release_data(DBKey,void *,DBRelease) - * @see #db_release_both(DBKey,void *,DBRelease) + * @see #db_release_nothing(DBKey,DBData,DBRelease) + * @see #db_release_key(DBKey,DBData,DBRelease) + * @see #db_release_data(DBKey,DBData,DBRelease) + * @see #db_release_both(DBKey,DBData,DBRelease) * @see #db_default_release(DBType,DBOptions) */ DBReleaser db_custom_release(DBRelease which) @@ -2483,6 +2504,99 @@ DBKey db_str2key(const char *key) } /** + * Manual cast from 'int' to the struct DBData. + * @param data Data to be casted + * @return The data as a DBData struct + * @public + */ +DBData db_i2data(int data) +{ + DBData ret; + + DB_COUNTSTAT(db_i2data); + ret.type = DB_DATA_INT; + ret.u.i = data; + return ret; +} + +/** + * Manual cast from 'unsigned int' to the struct DBData. + * @param data Data to be casted + * @return The data as a DBData struct + * @public + */ +DBData db_ui2data(unsigned int data) +{ + DBData ret; + + DB_COUNTSTAT(db_ui2data); + ret.type = DB_DATA_UINT; + ret.u.ui = data; + return ret; +} + +/** + * Manual cast from 'void *' to the struct DBData. + * @param data Data to be casted + * @return The data as a DBData struct + * @public + */ +DBData db_ptr2data(void *data) +{ + DBData ret; + + DB_COUNTSTAT(db_ptr2data); + ret.type = DB_DATA_PTR; + ret.u.ptr = data; + return ret; +} + +/** + * Gets int type data from struct DBData. + * If data is not int type, returns 0. + * @param data Data + * @return Integer value of the data. + * @public + */ +int db_data2i(DBData *data) +{ + DB_COUNTSTAT(db_data2i); + if (data && DB_DATA_INT == data->type) + return data->u.i; + return 0; +} + +/** + * Gets unsigned int type data from struct DBData. + * If data is not unsigned int type, returns 0. + * @param data Data + * @return Unsigned int value of the data. + * @public + */ +unsigned int db_data2ui(DBData *data) +{ + DB_COUNTSTAT(db_data2ui); + if (data && DB_DATA_UINT == data->type) + return data->u.ui; + return 0; +} + +/** + * Gets void* type data from struct DBData. + * If data is not void* type, returns NULL. + * @param data Data + * @return Void* value of the data. + * @public + */ +void* db_data2ptr(DBData *data) +{ + DB_COUNTSTAT(db_data2ptr); + if (data && DB_DATA_PTR == data->type) + return data->u.ptr; + return NULL; +} + +/** * Initializes the database system. * @public * @see #db_final(void) @@ -2543,6 +2657,9 @@ void db_final(void) "db_default_release %10u, db_custom_release %10u,\n" "db_alloc %10u, db_i2key %10u,\n" "db_ui2key %10u, db_str2key %10u,\n" + "db_i2data %10u, db_ui2data %10u,\n" + "db_ptr2data %10u, db_data2i %10u,\n" + "db_data2ui %10u, db_data2ptr %10u,\n" "db_init %10u, db_final %10u\n", stats.db_rotate_left, stats.db_rotate_right, stats.db_rebalance, stats.db_rebalance_erase, @@ -2573,6 +2690,9 @@ void db_final(void) stats.db_default_release, stats.db_custom_release, stats.db_alloc, stats.db_i2key, stats.db_ui2key, stats.db_str2key, + stats.db_i2data, stats.db_ui2data, + stats.db_ptr2data, stats.db_data2i, + stats.db_data2ui, stats.db_data2ptr, stats.db_init, stats.db_final); #endif /* DB_ENABLE_STATS */ } diff --git a/src/common/db.h b/src/common/db.h index e53ace0e6..49a95a135 100644 --- a/src/common/db.h +++ b/src/common/db.h @@ -16,12 +16,12 @@ * released. * * * * TODO: * - * - create an enum for the data (with int, unsigned int and void *) * * - create a custom database allocator * * - see what functions need or should be added to the database interface * * * * HISTORY: * - * 2007/11/09 - Added an iterator to the database. + * 2012/03/09 - Added enum for data types (int, uint, void*) * + * 2007/11/09 - Added an iterator to the database. * * 2.1 (Athena build #???#) - Portability fix * * - Fixed the portability of casting to union and added the functions * * {@link DBMap#ensure(DBMap,DBKey,DBCreateData,...)} and * @@ -50,7 +50,9 @@ * DBType - Enumeration of database types. * * DBOptions - Bitfield enumeration of database options. * * DBKey - Union of used key types. * - * DBApply - Format of functions applyed to the databases. * + * DBDataType - Enumeration of data types. * + * DBData - Struct for used data types. * + * DBApply - Format of functions applied to the databases. * * DBMatcher - Format of matchers used in DBMap::getall. * * DBComparator - Format of the comparators used by the databases. * * DBHasher - Format of the hashers used by the databases. * @@ -146,33 +148,65 @@ typedef union DBKey { } DBKey; /** - * Format of funtions that create the data for the key when the entry doesn't + * Supported types of database data. + * @param DB_DATA_INT Uses ints for data. + * @param DB_DATA_UINT Uses unsigned ints for data. + * @param DB_DATA_PTR Uses void pointers for data. + * @public + * @see #DBData + */ +typedef enum DBDataType { + DB_DATA_INT, + DB_DATA_UINT, + DB_DATA_PTR +} DBDataType; + +/** + * Struct for data types used by the database. + * @param type Type of data + * @param u Union of available data types + * @param u.i Data of int type + * @param u.ui Data of unsigned int type + * @param u.ptr Data of void* type + * @public + */ +typedef struct DBData { + DBDataType type; + union { + int i; + unsigned int ui; + void *ptr; + } u; +} DBData; + +/** + * Format of functions that create the data for the key when the entry doesn't * exist in the database yet. * @param key Key of the database entry - * @param args Extra arguments of the funtion + * @param args Extra arguments of the function * @return Data identified by the key to be put in the database * @public * @see DBMap#vensure * @see DBMap#ensure */ -typedef void* (*DBCreateData)(DBKey key, va_list args); +typedef DBData (*DBCreateData)(DBKey key, va_list args); /** - * Format of functions to be applyed to an unspecified quantity of entries of + * Format of functions to be applied to an unspecified quantity of entries of * a database. * Any function that applies this function to the database will return the sum * of values returned by this function. * @param key Key of the database entry * @param data Data of the database entry - * @param args Extra arguments of the funtion - * @return Value to be added up by the funtion that is applying this + * @param args Extra arguments of the function + * @return Value to be added up by the function that is applying this * @public * @see DBMap#vforeach * @see DBMap#foreach * @see DBMap#vdestroy * @see DBMap#destroy */ -typedef int (*DBApply)(DBKey key, void* data, va_list args); +typedef int (*DBApply)(DBKey key, DBData *data, va_list args); /** * Format of functions that match database entries. @@ -185,7 +219,7 @@ typedef int (*DBApply)(DBKey key, void* data, va_list args); * @public * @see DBMap#getall */ -typedef int (*DBMatcher)(DBKey key, void* data, va_list args); +typedef int (*DBMatcher)(DBKey key, DBData data, va_list args); /** * Format of the comparators used internally by the database system. @@ -225,7 +259,7 @@ typedef unsigned int (*DBHasher)(DBKey key, unsigned short maxlen); * @see #db_default_releaser(DBType,DBOptions) * @see #db_custom_release(DBRelease) */ -typedef void (*DBReleaser)(DBKey key, void* data, DBRelease which); +typedef void (*DBReleaser)(DBKey key, DBData data, DBRelease which); @@ -255,7 +289,7 @@ struct DBIterator * @return Data of the entry * @protected */ - void* (*first)(DBIterator* self, DBKey* out_key); + DBData* (*first)(DBIterator* self, DBKey* out_key); /** * Fetches the last entry in the database. @@ -266,7 +300,7 @@ struct DBIterator * @return Data of the entry * @protected */ - void* (*last)(DBIterator* self, DBKey* out_key); + DBData* (*last)(DBIterator* self, DBKey* out_key); /** * Fetches the next entry in the database. @@ -277,7 +311,7 @@ struct DBIterator * @return Data of the entry * @protected */ - void* (*next)(DBIterator* self, DBKey* out_key); + DBData* (*next)(DBIterator* self, DBKey* out_key); /** * Fetches the previous entry in the database. @@ -288,7 +322,7 @@ struct DBIterator * @return Data of the entry * @protected */ - void* (*prev)(DBIterator* self, DBKey* out_key); + DBData* (*prev)(DBIterator* self, DBKey* out_key); /** * Returns true if the fetched entry exists. @@ -303,14 +337,15 @@ struct DBIterator /** * Removes the current entry from the database. * NOTE: {@link DBIterator#exists} will return false until another entry - * is fethed - * Returns the data of the entry. + * is fetched + * Puts data of the removed entry in out_data, if out_data is not NULL. * @param self Iterator - * @return The data of the entry or NULL if not found + * @param out_data Data of the removed entry. + * @return 1 if entry was removed, 0 otherwise * @protected * @see DBMap#remove */ - void* (*remove)(DBIterator* self); + int (*remove)(DBIterator* self, DBData *out_data); /** * Destroys this iterator and unlocks the database. @@ -350,13 +385,13 @@ struct DBMap { bool (*exists)(DBMap* self, DBKey key); /** - * Get the data of the entry identifid by the key. + * Get the data of the entry identified by the key. * @param self Database * @param key Key that identifies the entry * @return Data of the entry or NULL if not found * @protected */ - void* (*get)(DBMap* self, DBKey key); + DBData* (*get)(DBMap* self, DBKey key); /** * Just calls {@link DBMap#vgetall}. @@ -375,7 +410,7 @@ struct DBMap { * @protected * @see DBMap#vgetall(DBMap*,void **,unsigned int,DBMatcher,va_list) */ - unsigned int (*getall)(DBMap* self, void** buf, unsigned int max, DBMatcher match, ...); + unsigned int (*getall)(DBMap* self, DBData** buf, unsigned int max, DBMatcher match, ...); /** * Get the data of the entries matched by <code>match</code>. @@ -393,7 +428,7 @@ struct DBMap { * @protected * @see DBMap#getall(DBMap*,void **,unsigned int,DBMatcher,...) */ - unsigned int (*vgetall)(DBMap* self, void** buf, unsigned int max, DBMatcher match, va_list args); + unsigned int (*vgetall)(DBMap* self, DBData** buf, unsigned int max, DBMatcher match, va_list args); /** * Just calls {@link DBMap#vensure}. @@ -408,7 +443,7 @@ struct DBMap { * @protected * @see DBMap#vensure(DBMap*,DBKey,DBCreateData,va_list) */ - void* (*ensure)(DBMap* self, DBKey key, DBCreateData create, ...); + DBData* (*ensure)(DBMap* self, DBKey key, DBCreateData create, ...); /** * Get the data of the entry identified by the key. @@ -422,37 +457,39 @@ struct DBMap { * @protected * @see DBMap#ensure(DBMap*,DBKey,DBCreateData,...) */ - void* (*vensure)(DBMap* self, DBKey key, DBCreateData create, va_list args); + DBData* (*vensure)(DBMap* self, DBKey key, DBCreateData create, va_list args); /** * Put the data identified by the key in the database. - * Returns the previous data if the entry exists or NULL. + * Puts the previous data in out_data, if out_data is not NULL. * NOTE: Uses the new key, the old one is released. * @param self Database * @param key Key that identifies the data * @param data Data to be put in the database - * @return The previous data if the entry exists or NULL + * @param out_data Previous data if the entry exists + * @return 1 if if the entry already exists, 0 otherwise * @protected */ - void* (*put)(DBMap* self, DBKey key, void* data); + int (*put)(DBMap* self, DBKey key, DBData data, DBData *out_data); /** * Remove an entry from the database. - * Returns the data of the entry. + * Puts the previous data in out_data, if out_data is not NULL. * NOTE: The key (of the database) is released. * @param self Database * @param key Key that identifies the entry - * @return The data of the entry or NULL if not found + * @param out_data Previous data if the entry exists + * @return 1 if if the entry already exists, 0 otherwise * @protected */ - void* (*remove)(DBMap* self, DBKey key); + int (*remove)(DBMap* self, DBKey key, DBData *out_data); /** * Just calls {@link DBMap#vforeach}. * Apply <code>func</code> to every entry in the database. * Returns the sum of values returned by func. * @param self Database - * @param func Function to be applyed + * @param func Function to be applied * @param ... Extra arguments for func * @return Sum of the values returned by func * @protected @@ -464,7 +501,7 @@ struct DBMap { * Apply <code>func</code> to every entry in the database. * Returns the sum of values returned by func. * @param self Database - * @param func Function to be applyed + * @param func Function to be applied * @param args Extra arguments for func * @return Sum of the values returned by func * @protected @@ -475,11 +512,11 @@ struct DBMap { /** * Just calls {@link DBMap#vclear}. * Removes all entries from the database. - * Before deleting an entry, func is applyed to it. + * Before deleting an entry, func is applied to it. * Releases the key and the data. * Returns the sum of values returned by func, if it exists. * @param self Database - * @param func Function to be applyed to every entry before deleting + * @param func Function to be applied to every entry before deleting * @param ... Extra arguments for func * @return Sum of values returned by func * @protected @@ -489,11 +526,11 @@ struct DBMap { /** * Removes all entries from the database. - * Before deleting an entry, func is applyed to it. + * Before deleting an entry, func is applied to it. * Releases the key and the data. * Returns the sum of values returned by func, if it exists. * @param self Database - * @param func Function to be applyed to every entry before deleting + * @param func Function to be applied to every entry before deleting * @param args Extra arguments for func * @return Sum of values returned by func * @protected @@ -504,13 +541,13 @@ struct DBMap { /** * Just calls {@link DBMap#vdestroy}. * Finalize the database, feeing all the memory it uses. - * Before deleting an entry, func is applyed to it. + * Before deleting an entry, func is applied to it. * Releases the key and the data. * Returns the sum of values returned by func, if it exists. * NOTE: This locks the database globally. Any attempt to insert or remove * a database entry will give an error and be aborted (except for clearing). * @param self Database - * @param func Function to be applyed to every entry before deleting + * @param func Function to be applied to every entry before deleting * @param ... Extra arguments for func * @return Sum of values returned by func * @protected @@ -520,12 +557,12 @@ struct DBMap { /** * Finalize the database, feeing all the memory it uses. - * Before deleting an entry, func is applyed to it. + * Before deleting an entry, func is applied to it. * Returns the sum of values returned by func, if it exists. * NOTE: This locks the database globally. Any attempt to insert or remove * a database entry will give an error and be aborted (except for clearing). * @param self Database - * @param func Function to be applyed to every entry before deleting + * @param func Function to be applied to every entry before deleting * @param args Extra arguments for func * @return Sum of values returned by func * @protected @@ -559,33 +596,61 @@ struct DBMap { }; -//For easy access to the common functions. +// For easy access to the common functions. + #define db_exists(db,k) ( (db)->exists((db),(k)) ) #define idb_exists(db,k) ( (db)->exists((db),db_i2key(k)) ) #define uidb_exists(db,k) ( (db)->exists((db),db_ui2key(k)) ) #define strdb_exists(db,k) ( (db)->exists((db),db_str2key(k)) ) -#define db_get(db,k) ( (db)->get((db),(k)) ) -#define idb_get(db,k) ( (db)->get((db),db_i2key(k)) ) -#define uidb_get(db,k) ( (db)->get((db),db_ui2key(k)) ) -#define strdb_get(db,k) ( (db)->get((db),db_str2key(k)) ) - -#define db_put(db,k,d) ( (db)->put((db),(k),(d)) ) -#define idb_put(db,k,d) ( (db)->put((db),db_i2key(k),(d)) ) -#define uidb_put(db,k,d) ( (db)->put((db),db_ui2key(k),(d)) ) -#define strdb_put(db,k,d) ( (db)->put((db),db_str2key(k),(d)) ) - -#define db_remove(db,k) ( (db)->remove((db),(k)) ) -#define idb_remove(db,k) ( (db)->remove((db),db_i2key(k)) ) -#define uidb_remove(db,k) ( (db)->remove((db),db_ui2key(k)) ) -#define strdb_remove(db,k) ( (db)->remove((db),db_str2key(k)) ) +// Get pointer-type data from DBMaps of various key types +#define db_get(db,k) ( db_data2ptr((db)->get((db),(k))) ) +#define idb_get(db,k) ( db_data2ptr((db)->get((db),db_i2key(k))) ) +#define uidb_get(db,k) ( db_data2ptr((db)->get((db),db_ui2key(k))) ) +#define strdb_get(db,k) ( db_data2ptr((db)->get((db),db_str2key(k))) ) + +// Get int-type data from DBMaps of various key types +#define db_iget(db,k) ( db_data2i((db)->get((db),(k))) ) +#define idb_iget(db,k) ( db_data2i((db)->get((db),db_i2key(k))) ) +#define uidb_iget(db,k) ( db_data2i((db)->get((db),db_ui2key(k))) ) +#define strdb_iget(db,k) ( db_data2i((db)->get((db),db_str2key(k))) ) + +// Get uint-type data from DBMaps of various key types +#define db_uiget(db,k) ( db_data2ui((db)->get((db),(k))) ) +#define idb_uiget(db,k) ( db_data2ui((db)->get((db),db_i2key(k))) ) +#define uidb_uiget(db,k) ( db_data2ui((db)->get((db),db_ui2key(k))) ) +#define strdb_uiget(db,k) ( db_data2ui((db)->get((db),db_str2key(k))) ) + +// Put pointer-type data into DBMaps of various key types +#define db_put(db,k,d) ( (db)->put((db),(k),db_ptr2data(d),NULL) ) +#define idb_put(db,k,d) ( (db)->put((db),db_i2key(k),db_ptr2data(d),NULL) ) +#define uidb_put(db,k,d) ( (db)->put((db),db_ui2key(k),db_ptr2data(d),NULL) ) +#define strdb_put(db,k,d) ( (db)->put((db),db_str2key(k),db_ptr2data(d),NULL) ) + +// Put int-type data into DBMaps of various key types +#define db_iput(db,k,d) ( (db)->put((db),(k),db_i2data(d)) ) +#define idb_iput(db,k,d) ( (db)->put((db),db_i2key(k),db_i2data(d)) ) +#define uidb_iput(db,k,d) ( (db)->put((db),db_ui2key(k),db_i2data(d)) ) +#define strdb_iput(db,k,d) ( (db)->put((db),db_str2key(k),db_i2data(d)) ) + +// Put uint-type data into DBMaps of various key types +#define db_uiput(db,k,d) ( (db)->put((db),(k),db_ui2data(d)) ) +#define idb_uiput(db,k,d) ( (db)->put((db),db_i2key(k),db_ui2data(d)) ) +#define uidb_uiput(db,k,d) ( (db)->put((db),db_ui2key(k),db_ui2data(d)) ) +#define strdb_uiput(db,k,d) ( (db)->put((db),db_str2key(k),db_ui2data(d)) ) + +// Remove entry from DBMaps of various key types +#define db_remove(db,k) ( (db)->remove((db),(k),NULL) ) +#define idb_remove(db,k) ( (db)->remove((db),db_i2key(k),NULL) ) +#define uidb_remove(db,k) ( (db)->remove((db),db_ui2key(k),NULL) ) +#define strdb_remove(db,k) ( (db)->remove((db),db_str2key(k),NULL) ) //These are discarding the possible vargs you could send to the function, so those //that require vargs must not use these defines. -#define db_ensure(db,k,f) ( (db)->ensure((db),(k),(f)) ) -#define idb_ensure(db,k,f) ( (db)->ensure((db),db_i2key(k),(f)) ) -#define uidb_ensure(db,k,f) ( (db)->ensure((db),db_ui2key(k),(f)) ) -#define strdb_ensure(db,k,f) ( (db)->ensure((db),db_str2key(k),(f)) ) +#define db_ensure(db,k,f) ( db_data2ptr((db)->ensure((db),(k),(f))) ) +#define idb_ensure(db,k,f) ( db_data2ptr((db)->ensure((db),db_i2key(k),(f))) ) +#define uidb_ensure(db,k,f) ( db_data2ptr((db)->ensure((db),db_ui2key(k),(f))) ) +#define strdb_ensure(db,k,f) ( db_data2ptr((db)->ensure((db),db_str2key(k),(f))) ) // Database creation and destruction macros #define idb_alloc(opt) db_alloc(__FILE__,__LINE__,DB_INT,(opt),sizeof(int)) @@ -597,10 +662,11 @@ struct DBMap { #define db_clear(db) ( (db)->clear(db,NULL) ) #define db_size(db) ( (db)->size(db) ) #define db_iterator(db) ( (db)->iterator(db) ) -#define dbi_first(dbi) ( (dbi)->first(dbi,NULL) ) -#define dbi_last(dbi) ( (dbi)->last(dbi,NULL) ) -#define dbi_next(dbi) ( (dbi)->next(dbi,NULL) ) -#define dbi_prev(dbi) ( (dbi)->prev(dbi,NULL) ) +#define dbi_first(dbi) ( db_data2ptr((dbi)->first(dbi,NULL)) ) +#define dbi_last(dbi) ( db_data2ptr((dbi)->last(dbi,NULL)) ) +#define dbi_next(dbi) ( db_data2ptr((dbi)->next(dbi,NULL)) ) +#define dbi_prev(dbi) ( db_data2ptr((dbi)->prev(dbi,NULL)) ) +#define dbi_remove(dbi) ( (dbi)->remove(dbi,NULL) ) #define dbi_exists(dbi) ( (dbi)->exists(dbi) ) #define dbi_destroy(dbi) ( (dbi)->destroy(dbi) ) @@ -616,8 +682,14 @@ struct DBMap { * db_i2key - Manual cast from 'int' to 'DBKey'. * * db_ui2key - Manual cast from 'unsigned int' to 'DBKey'. * * db_str2key - Manual cast from 'unsigned char *' to 'DBKey'. * - * db_init - Initialise the database system. * - * db_final - Finalise the database system. * + * db_i2data - Manual cast from 'int' to 'DBData'. * + * db_ui2data - Manual cast from 'unsigned int' to 'DBData'. * + * db_ptr2data - Manual cast from 'void*' to 'DBData'. * + * db_data2i - Gets 'int' value from 'DBData'. * + * db_data2ui - Gets 'unsigned int' value from 'DBData'. * + * db_data2ptr - Gets 'void*' value from 'DBData'. * + * db_init - Initializes the database system. * + * db_final - Finalizes the database system. * \*****************************************************************************/ /** @@ -730,6 +802,57 @@ DBKey db_ui2key(unsigned int key); DBKey db_str2key(const char *key); /** + * Manual cast from 'int' to the struct DBData. + * @param data Data to be casted + * @return The data as a DBData struct + * @public + */ +DBData db_i2data(int data); + +/** + * Manual cast from 'unsigned int' to the struct DBData. + * @param data Data to be casted + * @return The data as a DBData struct + * @public + */ +DBData db_ui2data(unsigned int data); + +/** + * Manual cast from 'void *' to the struct DBData. + * @param data Data to be casted + * @return The data as a DBData struct + * @public + */ +DBData db_ptr2data(void *data); + +/** + * Gets int type data from struct DBData. + * If data is not int type, returns 0. + * @param data Data + * @return Integer value of the data. + * @public + */ +int db_data2i(DBData *data); + +/** + * Gets unsigned int type data from struct DBData. + * If data is not unsigned int type, returns 0. + * @param data Data + * @return Unsigned int value of the data. + * @public + */ +unsigned int db_data2ui(DBData *data); + +/** + * Gets void* type data from struct DBData. + * If data is not void* type, returns NULL. + * @param data Data + * @return Void* value of the data. + * @public + */ +void* db_data2ptr(DBData *data); + +/** * Initialize the database system. * @public * @see #db_final(void) diff --git a/src/common/showmsg.c b/src/common/showmsg.c index 4d09e2c53..dce0a8dbb 100644 --- a/src/common/showmsg.c +++ b/src/common/showmsg.c @@ -59,7 +59,7 @@ int console_msg_log = 0;//[Ind] msg error logging /////////////////////////////////////////////////////////////////////////////// /// static/dynamic buffer for the messages -#define SBUF_SIZE 2048 // never put less that what's required for the debug message +#define SBUF_SIZE 2054 // never put less that what's required for the debug message #define NEWBUF(buf) \ struct { \ |