[Core, mod_hash] Add two APIs switch_core_hash_insert_alloc_destructor and switch_core_hash_insert_dup_destructor. Code cleanup in mod_hash. Add unit-tests.
This commit is contained in:
parent
f92368d2f2
commit
1b048a8a97
|
@ -1457,6 +1457,28 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_auto_free(switch_hash_t
|
|||
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_destructor(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_opt_ const void *data, hashtable_destructor_t destructor);
|
||||
#define switch_core_hash_insert(_h, _k, _d) switch_core_hash_insert_destructor(_h, _k, _d, NULL)
|
||||
|
||||
/*!
|
||||
\brief Allocate memory and insert into a hash
|
||||
\param hash the hash to add data to
|
||||
\param key the name of the key to add the data to
|
||||
\param size the size in bytes to allocate
|
||||
\return pointer to the allocated memory
|
||||
\note the string key must be a constant or a dynamic string
|
||||
*/
|
||||
SWITCH_DECLARE(void *) switch_core_hash_insert_alloc_destructor(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_opt_ size_t size, hashtable_destructor_t destructor);
|
||||
#define switch_core_hash_insert_alloc(_h, _k, _s) switch_core_hash_insert_alloc_destructor(_h, _k, _s, NULL)
|
||||
|
||||
/*!
|
||||
\brief Insert strdup(data) into a hash
|
||||
\param hash the hash to add data to
|
||||
\param key the name of the key to add the data to
|
||||
\param data string to strdup and add
|
||||
\return SWITCH_STATUS_SUCCESS if the data is added
|
||||
\note the string key must be a constant or a dynamic string
|
||||
*/
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_dup_destructor(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_opt_ const char *str, hashtable_destructor_t destructor);
|
||||
#define switch_core_hash_insert_dup(_h, _k, _d) switch_core_hash_insert_dup_destructor(_h, _k, _d, NULL)
|
||||
|
||||
|
||||
/*!
|
||||
\brief Insert data into a hash
|
||||
|
|
|
@ -144,10 +144,7 @@ SWITCH_LIMIT_INCR(limit_incr_hash)
|
|||
if (!(item = (limit_hash_item_t *) switch_core_hash_find(globals.limit_hash, hashkey))) {
|
||||
/* No, create an empty structure and add it, then continue like as if it existed */
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "Creating new limit structure: key: %s\n", hashkey);
|
||||
item = (limit_hash_item_t *) malloc(sizeof(limit_hash_item_t));
|
||||
switch_assert(item);
|
||||
memset(item, 0, sizeof(limit_hash_item_t));
|
||||
switch_core_hash_insert(globals.limit_hash, hashkey, item);
|
||||
item = (limit_hash_item_t *)switch_core_hash_insert_alloc(globals.limit_hash, hashkey, sizeof(limit_hash_item_t));
|
||||
}
|
||||
|
||||
if (!(pvt = switch_channel_get_private(channel, "limit_hash"))) {
|
||||
|
@ -433,17 +430,13 @@ SWITCH_STANDARD_APP(hash_function)
|
|||
free(value);
|
||||
switch_core_hash_delete(globals.db_hash, hash_key);
|
||||
}
|
||||
value = strdup(argv[3]);
|
||||
switch_assert(value);
|
||||
switch_core_hash_insert(globals.db_hash, hash_key, value);
|
||||
switch_core_hash_insert_dup(globals.db_hash, hash_key, argv[3]);
|
||||
} else if (!strcasecmp(argv[0], "insert_ifempty")) {
|
||||
if (argc < 4) {
|
||||
goto usage;
|
||||
}
|
||||
if (!(value = switch_core_hash_find(globals.db_hash, hash_key))) {
|
||||
value = strdup(argv[3]);
|
||||
switch_assert(value);
|
||||
switch_core_hash_insert(globals.db_hash, hash_key, value);
|
||||
switch_core_hash_insert_dup(globals.db_hash, hash_key, argv[3]);
|
||||
}
|
||||
|
||||
} else if (!strcasecmp(argv[0], "delete")) {
|
||||
|
@ -506,9 +499,7 @@ SWITCH_STANDARD_API(hash_api_function)
|
|||
switch_safe_free(value);
|
||||
switch_core_hash_delete(globals.db_hash, hash_key);
|
||||
}
|
||||
value = strdup(argv[3]);
|
||||
switch_assert(value);
|
||||
switch_core_hash_insert(globals.db_hash, hash_key, value);
|
||||
switch_core_hash_insert_dup(globals.db_hash, hash_key, argv[3]);
|
||||
stream->write_function(stream, "+OK\n");
|
||||
switch_thread_rwlock_unlock(globals.db_hash_rwlock);
|
||||
} else if (!strcasecmp(argv[0], "insert_ifempty")) {
|
||||
|
@ -519,9 +510,7 @@ SWITCH_STANDARD_API(hash_api_function)
|
|||
if ((value = switch_core_hash_find(globals.db_hash, hash_key))) {
|
||||
stream->write_function(stream, "-ERR key already exists\n");
|
||||
} else {
|
||||
value = strdup(argv[3]);
|
||||
switch_assert(value);
|
||||
switch_core_hash_insert(globals.db_hash, hash_key, value);
|
||||
switch_core_hash_insert_dup(globals.db_hash, hash_key, argv[3]);
|
||||
stream->write_function(stream, "+OK\n");
|
||||
}
|
||||
switch_thread_rwlock_unlock(globals.db_hash_rwlock);
|
||||
|
|
|
@ -68,6 +68,45 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_auto_free(switch_hash_t
|
|||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(void *) switch_core_hash_insert_alloc_destructor(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_opt_ size_t size, hashtable_destructor_t destructor) {
|
||||
char *dkey;
|
||||
void *data;
|
||||
|
||||
if (!size) return NULL;
|
||||
|
||||
dkey = strdup(key);
|
||||
data = malloc(size);
|
||||
|
||||
assert(data);
|
||||
|
||||
if (switch_hashtable_insert_destructor(hash, dkey, data, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_DUP_CHECK, destructor)) {
|
||||
memset(data, 0, size);
|
||||
return data;
|
||||
}
|
||||
|
||||
free(data);
|
||||
switch_safe_free(dkey);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_dup_destructor(switch_hash_t *hash, const char *key, const char *str, hashtable_destructor_t destructor)
|
||||
{
|
||||
char *dkey = strdup(key);
|
||||
char *dup = strdup(str);
|
||||
|
||||
assert(dup);
|
||||
|
||||
if (switch_hashtable_insert_destructor(hash, dkey, (void *)dup, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_DUP_CHECK, destructor)) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
switch_safe_free(dup);
|
||||
switch_safe_free(dkey);
|
||||
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_destructor(switch_hash_t *hash, const char *key, const void *data, hashtable_destructor_t destructor)
|
||||
{
|
||||
char *dkey = strdup(key);
|
||||
|
|
|
@ -267,6 +267,53 @@ FST_CORE_BEGIN("./conf")
|
|||
fst_check_int_equals(switch_safe_atoll(0, 3), 3);
|
||||
}
|
||||
FST_TEST_END()
|
||||
|
||||
FST_TEST_BEGIN(test_switch_core_hash_insert_dup)
|
||||
{
|
||||
char *magicnumber = malloc(9);
|
||||
switch_hash_index_t *hi;
|
||||
switch_hash_t *hash = NULL;
|
||||
void *hash_val;
|
||||
switch_core_hash_init(&hash);
|
||||
fst_requires(hash);
|
||||
|
||||
snprintf(magicnumber, 9, "%s", "DEADBEEF");
|
||||
switch_core_hash_insert_dup(hash, "test", (const char *)magicnumber);
|
||||
snprintf(magicnumber, 9, "%s", "BAADF00D");
|
||||
|
||||
hi = switch_core_hash_first(hash);
|
||||
switch_core_hash_this(hi, NULL, NULL, &hash_val);
|
||||
fst_check_string_equals(hash_val, "DEADBEEF");
|
||||
switch_safe_free(hash_val);
|
||||
free(magicnumber);
|
||||
free(hi);
|
||||
switch_core_hash_destroy(&hash);
|
||||
fst_requires(hash == NULL);
|
||||
}
|
||||
FST_TEST_END()
|
||||
|
||||
FST_TEST_BEGIN(test_switch_core_hash_insert_alloc)
|
||||
{
|
||||
char *item;
|
||||
switch_hash_index_t *hi;
|
||||
switch_hash_t *hash = NULL;
|
||||
void *hash_val;
|
||||
switch_core_hash_init(&hash);
|
||||
fst_requires(hash);
|
||||
|
||||
item = switch_core_hash_insert_alloc(hash, "test", 10);
|
||||
fst_requires(item);
|
||||
snprintf(item, 9, "%s", "DEADBEEF");
|
||||
|
||||
hi = switch_core_hash_first(hash);
|
||||
switch_core_hash_this(hi, NULL, NULL, &hash_val);
|
||||
fst_check_string_equals(hash_val, "DEADBEEF");
|
||||
free(hi);
|
||||
switch_core_hash_destroy(&hash);
|
||||
fst_requires(hash == NULL);
|
||||
free(item);
|
||||
}
|
||||
FST_TEST_END()
|
||||
}
|
||||
FST_SUITE_END()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue