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
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"))) {
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")) {
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")) {
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);
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);
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()
}