[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);
|
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)
|
#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
|
\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))) {
|
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 */
|
/* 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);
|
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));
|
item = (limit_hash_item_t *)switch_core_hash_insert_alloc(globals.limit_hash, hashkey, 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(pvt = switch_channel_get_private(channel, "limit_hash"))) {
|
if (!(pvt = switch_channel_get_private(channel, "limit_hash"))) {
|
||||||
|
@ -433,17 +430,13 @@ SWITCH_STANDARD_APP(hash_function)
|
||||||
free(value);
|
free(value);
|
||||||
switch_core_hash_delete(globals.db_hash, hash_key);
|
switch_core_hash_delete(globals.db_hash, hash_key);
|
||||||
}
|
}
|
||||||
value = strdup(argv[3]);
|
switch_core_hash_insert_dup(globals.db_hash, hash_key, argv[3]);
|
||||||
switch_assert(value);
|
|
||||||
switch_core_hash_insert(globals.db_hash, hash_key, value);
|
|
||||||
} else if (!strcasecmp(argv[0], "insert_ifempty")) {
|
} else if (!strcasecmp(argv[0], "insert_ifempty")) {
|
||||||
if (argc < 4) {
|
if (argc < 4) {
|
||||||
goto usage;
|
goto usage;
|
||||||
}
|
}
|
||||||
if (!(value = switch_core_hash_find(globals.db_hash, hash_key))) {
|
if (!(value = switch_core_hash_find(globals.db_hash, hash_key))) {
|
||||||
value = strdup(argv[3]);
|
switch_core_hash_insert_dup(globals.db_hash, hash_key, argv[3]);
|
||||||
switch_assert(value);
|
|
||||||
switch_core_hash_insert(globals.db_hash, hash_key, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (!strcasecmp(argv[0], "delete")) {
|
} else if (!strcasecmp(argv[0], "delete")) {
|
||||||
|
@ -506,9 +499,7 @@ SWITCH_STANDARD_API(hash_api_function)
|
||||||
switch_safe_free(value);
|
switch_safe_free(value);
|
||||||
switch_core_hash_delete(globals.db_hash, hash_key);
|
switch_core_hash_delete(globals.db_hash, hash_key);
|
||||||
}
|
}
|
||||||
value = strdup(argv[3]);
|
switch_core_hash_insert_dup(globals.db_hash, hash_key, argv[3]);
|
||||||
switch_assert(value);
|
|
||||||
switch_core_hash_insert(globals.db_hash, hash_key, value);
|
|
||||||
stream->write_function(stream, "+OK\n");
|
stream->write_function(stream, "+OK\n");
|
||||||
switch_thread_rwlock_unlock(globals.db_hash_rwlock);
|
switch_thread_rwlock_unlock(globals.db_hash_rwlock);
|
||||||
} else if (!strcasecmp(argv[0], "insert_ifempty")) {
|
} 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))) {
|
if ((value = switch_core_hash_find(globals.db_hash, hash_key))) {
|
||||||
stream->write_function(stream, "-ERR key already exists\n");
|
stream->write_function(stream, "-ERR key already exists\n");
|
||||||
} else {
|
} else {
|
||||||
value = strdup(argv[3]);
|
switch_core_hash_insert_dup(globals.db_hash, hash_key, argv[3]);
|
||||||
switch_assert(value);
|
|
||||||
switch_core_hash_insert(globals.db_hash, hash_key, value);
|
|
||||||
stream->write_function(stream, "+OK\n");
|
stream->write_function(stream, "+OK\n");
|
||||||
}
|
}
|
||||||
switch_thread_rwlock_unlock(globals.db_hash_rwlock);
|
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;
|
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)
|
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);
|
char *dkey = strdup(key);
|
||||||
|
|
|
@ -267,6 +267,53 @@ FST_CORE_BEGIN("./conf")
|
||||||
fst_check_int_equals(switch_safe_atoll(0, 3), 3);
|
fst_check_int_equals(switch_safe_atoll(0, 3), 3);
|
||||||
}
|
}
|
||||||
FST_TEST_END()
|
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()
|
FST_SUITE_END()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue