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;
}
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
- * that can be set, removed, and checked for.
- *
- * See EXPOSED interface comment below
- */
-#define GMQCC_HASHSET_PRIME0 0x0049
-#define GMQCC_HASHSET_PRIME1 0x1391
-
-static int util_hsput(hash_set_t *set, void *item) {
- size_t hash = (size_t)item; /* shouldn't drop the bits */
- size_t iter;
-
- /* a == 0 || a == 1 */
- if (hash >> 1)
- return -1;
-
- iter = set->mask & (GMQCC_HASHSET_PRIME0 * hash);
-
- /* while (set->items[iter] != 0 && set->items[iter] != 1) */
- while (!(set->items[iter] >> 1)) {
- if (set->items[iter] == hash)
- return 0;
-
- iter = set->mask & (iter + GMQCC_HASHSET_PRIME1);
- }
-
- set->total ++;
- set->items[iter] = hash;
-
- return 1;
-}
-
-static void util_hsupdate(hash_set_t *set) {
- size_t *old;
- size_t end;
- size_t itr;
-
- /* time to rehash? */
- if ((float)set->total >= (size_t)((double)set->capacity * 0.85)) {
- old = set->items;
- end = set->capacity;
-
- set->bits ++;
- set->capacity = (size_t)(1 << set->bits);
- set->mask = set->capacity - 1;
- set->items = (size_t*)mem_a(set->capacity * sizeof(size_t));
- set->total = 0;
-
- /*assert(set->items);*/
-
- /*
- * this shouldn't be slow? if so unroll it a little perhaps
- * (shouldn't be though)
- */
- for (itr = 0; itr < end; itr++)
- util_hsput(set, (void*)old[itr]);
-
- mem_d(old);
- }
-}
-
-/*
- * EXPOSED interface: all of these functions are exposed to the outside
- * for use. The stuff above is static because it's the "internal" mechanics
- * for syncronizing the set for updating, and putting data into the set.
- */
-int util_hsadd(hash_set_t *set, void *item) {
- int run = util_hsput(set, item); /* inlined */
- util_hsupdate(set);
-
- return run;
-}
-
-/* remove item in set */
-int util_hsrem(hash_set_t *set, void *item) {
- size_t hash = (size_t)item;
- size_t iter = set->mask & (GMQCC_HASHSET_PRIME0 * hash);
-
- while (set->items[iter]) {
- if (set->items[iter] == hash) {
- set->items[iter] = 1;
- set->total --;
-
- return 1;
- }
- iter = set->mask & (iter + GMQCC_HASHSET_PRIME1);
- }
-
- return 0;
-}
-
-/* check if item is set */
-int util_hshas(hash_set_t *set, void *item) {
- size_t hash = (size_t)item;
- size_t iter = set->mask & (GMQCC_HASHSET_PRIME0 * hash);
-
- while (set->items[iter]) {
- if (set->items[iter] == hash)
- return 1;
-
- iter = set->mask & (iter + GMQCC_HASHSET_PRIME1);
- }
-
- return 0;
-}
-
-hash_set_t *util_hsnew(void) {
- hash_set_t *set;
-
- if (!(set = (hash_set_t*)mem_a(sizeof(hash_set_t))))
- return NULL;
-
- set->bits = 3;
- set->total = 0;
- set->capacity = (size_t)(1 << set->bits);
- set->mask = set->capacity - 1;
- set->items = (size_t*)mem_a(set->capacity * sizeof(size_t));
-
- if (!set->items) {
- util_hsdel(set);
- return NULL;
- }
-
- return set;
-}
-
-void util_hsdel(hash_set_t *set) {
- if (!set) return;
-
- if (set->items)
- mem_d(set->items);
-
- mem_d(set);
-}
-#undef GMQCC_HASHSET_PRIME0
-#undef GMQCC_HASHSET_PRIME1
-
-
/*
* Portable implementation of vasprintf/asprintf. Assumes vsnprintf
* exists, otherwise compiler error.