return ptr;
}
+char *_util_Estrdup_empty(const char *s, const char *file, size_t line) {
+ size_t len = 0;
+ char *ptr = NULL;
+
+ /* in case of -DNOTRACK */
+ (void)file;
+ (void)line;
+
+ if (!s)
+ return NULL;
+
+ len = strlen(s);
+ if ((ptr = (char*)mem_af(len+1, line, file))) {
+ memcpy(ptr, s, len);
+ ptr[len] = '\0';
+ }
+ return ptr;
+}
+
void util_debug(const char *area, const char *ms, ...) {
va_list va;
if (!OPTS_OPTION_BOOL(OPTION_DEBUG))
if (!(node = (hash_node_t*)mem_a(sizeof(hash_node_t))))
return NULL;
- if (!(node->key = util_strdup(key))) {
+ if (!(node->key = util_strdupe(key))) {
mem_d(node);
return NULL;
}
* Free all allocated data in a hashtable, this is quite the amount
* of work.
*/
-void util_htdel(hash_table_t *ht) {
+void util_htrem(hash_table_t *ht, void (*callback)(void *data)) {
size_t i = 0;
for (; i < ht->size; i++) {
hash_node_t *n = ht->table[i];
while (n) {
if (n->key)
mem_d(n->key);
+ if (callback)
+ callback(n->value);
p = n;
n = n->next;
mem_d(p);
mem_d(ht);
}
+void util_htrmh(hash_table_t *ht, const char *key, size_t bin, void (*cb)(void*)) {
+ hash_node_t **pair = &ht->table[bin];
+ hash_node_t *tmp;
+
+ while (*pair && (*pair)->key && strcmp(key, (*pair)->key) > 0)
+ pair = &(*pair)->next;
+
+ tmp = *pair;
+ if (!tmp || !tmp->key || strcmp(key, tmp->key) != 0)
+ return;
+
+ if (cb)
+ (*cb)(tmp->value);
+
+ *pair = tmp->next;
+ mem_d(tmp->key);
+ mem_d(tmp);
+}
+
+void util_htrm(hash_table_t *ht, const char *key, void (*cb)(void*)) {
+ util_htrmh(ht, key, util_hthash(ht, key), cb);
+}
+
+void util_htdel(hash_table_t *ht) {
+ util_htrem(ht, NULL);
+}
+
/*
* A basic implementation of a hash-set. Unlike a hashtable, a hash
* set doesn't maintain key-value pairs. It simply maintains a key