]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
[Core, mod_hash] Add two APIs switch_core_hash_insert_alloc_destructor and switch_cor...
authorAndrey Volk <andywolk@gmail.com>
Tue, 26 Jan 2021 23:53:16 +0000 (02:53 +0300)
committerAndrey Volk <andywolk@gmail.com>
Tue, 19 Oct 2021 17:26:50 +0000 (20:26 +0300)
src/include/switch_core.h
src/mod/applications/mod_hash/mod_hash.c
src/switch_core_hash.c
tests/unit/switch_core.c

index 4f172a928e0225fbcaae2202e55f7c98d5ad3ba0..9c9f6c490ce043fa93025170b46c3327c52693a1 100644 (file)
@@ -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
index 6899922ab64b79cdfdbbd35c5c63f361b70e3c3c..70bffd18e1dcca196d4c7200ed7279cb42c2aaf2 100644 (file)
@@ -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);
index 70102ce9572c21c3e47a693896296ba03ed855de..06d04758525d8960f8ecc0155952416c798c1030 100644 (file)
@@ -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);
index 0e914fa070459bcc8f3ab2daa0d5b5f48d5df2c5..af52ab94950eca158f3018a6b7f3e49378262031 100644 (file)
@@ -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()
 }