Permalink
Browse files

breaking change to stringmap

  • Loading branch information...
1 parent 3ee4d6d commit 540ef7b4625cfa0f7e145d4d9db0ef2b767cf4d3 @wmorgan committed Mar 27, 2012
Showing with 66 additions and 67 deletions.
  1. +61 −56 stringmap.c
  2. +5 −11 stringmap.h
View
@@ -33,20 +33,15 @@ static inline int string_equals(const char* a, const char* b) {
return strcmp(a, b) == 0;
}
-// set flags, keys and vals to correct locations based on h->n_buckets
-void stringmap_setup(stringmap* h, stringpool* p) {
- h->pool = p;
- h->flags = (uint32_t*)h->boundary;
- h->keys = (uint32_t*)((uint32_t*)h->boundary + ((h->n_buckets >> 4) + 1));
-}
+#define STRINGMAP_FLAGS(h) ((uint32_t*)(h)->boundary)
+#define STRINGMAP_KEYS(h) ((uint32_t*)((uint32_t*)(h)->boundary + (((h)->n_buckets >> 4) + 1)))
-void stringmap_init(stringmap* h, stringpool* p) {
+void stringmap_init(stringmap* h) {
h->n_buckets_idx = INITIAL_N_BUCKETS_IDX;
h->n_buckets = prime_list[h->n_buckets_idx];
h->upper_bound = (uint32_t)(h->n_buckets * HASH_UPPER + 0.5);
h->size = h->n_occupied = 0;
- stringmap_setup(h, p);
- memset(h->flags, 0xaa, ((h->n_buckets>>4) + 1) * sizeof(uint32_t));
+ memset(STRINGMAP_FLAGS(h), 0xaa, ((h->n_buckets>>4) + 1) * sizeof(uint32_t));
}
/*
@@ -66,74 +61,80 @@ static void kh_clear_##name(kh_##name##_t *h) {
}
*/
-uint32_t stringmap_get(stringmap *h, const char* key) {
+uint32_t stringmap_get(stringmap *h, stringpool* pool, const char* key) {
+ uint32_t* flags = STRINGMAP_FLAGS(h);
+ uint32_t* keys = STRINGMAP_KEYS(h);
+
if(h->n_buckets) {
uint32_t inc, k, i, last;
k = string_hash(key); i = k % h->n_buckets;
inc = 1 + k % (h->n_buckets - 1); last = i;
- while (!isempty(h->flags, i) && (isdel(h->flags, i) || !string_equals(stringpool_lookup(h->pool, h->keys[i]), key))) {
+ while (!isempty(flags, i) && (isdel(flags, i) || !string_equals(stringpool_lookup(pool, keys[i]), key))) {
if (i + inc >= h->n_buckets) i = i + inc - h->n_buckets;
else i += inc;
if (i == last) return h->n_buckets;
}
- return iseither(h->flags, i)? h->n_buckets : i;
+ return iseither(flags, i)? h->n_buckets : i;
}
else return 0;
}
-wp_error* stringmap_bump_size(stringmap *h) {
+wp_error* stringmap_bump_size(stringmap *h, stringpool* pool) {
DEBUG("bumping size for string hash at %p with size %u and boundary %p", h, stringmap_size(h), h->boundary);
if(h->n_buckets_idx >= (HASH_PRIME_SIZE - 1)) RAISE_ERROR("stringmap can't be this big");
h->n_buckets_idx++;
uint32_t new_n_buckets = prime_list[h->n_buckets_idx];
- // first make a backup of the oldflags
- size_t oldflagsize = ((h->n_buckets >> 4) + 1) * sizeof(uint32_t);
- uint32_t* oldflags = malloc(oldflagsize);
- memcpy(oldflags, h->flags, oldflagsize);
+ // get pointers to the old locations
+ uint32_t* oldkeys = STRINGMAP_KEYS(h);
+ uint32_t* oldflags = STRINGMAP_FLAGS(h);
- // keep pointers to the old locations
- uint32_t* oldkeys = h->keys;
+ // make a backup of the old flags in a separate memory region
+ size_t flagbaksize = ((h->n_buckets >> 4) + 1) * sizeof(uint32_t);
+ uint32_t* flagbaks = malloc(flagbaksize);
+ memcpy(flagbaks, oldflags, flagbaksize);
- // set pointers to the new locations
- h->keys = (uint32_t*)((uint32_t*)h->boundary + ((new_n_buckets >> 4) + 1));
+ // get a pointer pointers to the new locations
+ //h->keys = (uint32_t*)((uint32_t*)h->boundary + ((new_n_buckets >> 4) + 1));
+ uint32_t* newflags = (uint32_t*)h->boundary; // unchanged, actually
+ uint32_t* newkeys = (uint32_t*)((uint32_t*)h->boundary + ((new_n_buckets >> 4) + 1));
// move the keys
- memmove(h->keys, oldkeys, h->n_buckets * sizeof(uint32_t));
+ memmove(newkeys, oldkeys, h->n_buckets * sizeof(uint32_t));
// clear the new flags
- memset(h->flags, 0xaa, ((new_n_buckets>>4) + 1) * sizeof(uint32_t));
+ memset(STRINGMAP_FLAGS(h), 0xaa, ((new_n_buckets>>4) + 1) * sizeof(uint32_t));
// do the complicated stuff from khash.h
for (unsigned int j = 0; j != h->n_buckets; ++j) {
- if (iseither(oldflags, j) == 0) {
- uint32_t key = h->keys[j];
- set_isdel_true(oldflags, j);
+ if (iseither(flagbaks, j) == 0) {
+ uint32_t key = newkeys[j];
+ set_isdel_true(flagbaks, j);
while (1) {
uint32_t inc, k, i;
- k = string_hash(stringpool_lookup(h->pool, key));
+ k = string_hash(stringpool_lookup(pool, key));
i = k % new_n_buckets;
inc = 1 + k % (new_n_buckets - 1);
- while (!isempty(h->flags, i)) {
+ while (!isempty(newflags, i)) {
if (i + inc >= new_n_buckets) i = i + inc - new_n_buckets;
else i += inc;
}
- set_isempty_false(h->flags, i);
- if (i < h->n_buckets && iseither(oldflags, i) == 0) {
- { uint32_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; }
- set_isdel_true(oldflags, i);
+ set_isempty_false(newflags, i);
+ if (i < h->n_buckets && iseither(flagbaks, i) == 0) {
+ { uint32_t tmp = newkeys[i]; newkeys[i] = key; key = tmp; }
+ set_isdel_true(flagbaks, i);
} else {
- h->keys[i] = key;
+ newkeys[i] = key;
break;
}
}
}
}
- free(oldflags);
- h->n_buckets = new_n_buckets;
+ free(flagbaks);
+ h->n_buckets = new_n_buckets; // STRINGMAP_KEYS now works
h->n_occupied = h->size;
h->upper_bound = (uint32_t)(h->n_buckets * HASH_UPPER + 0.5);
@@ -144,8 +145,10 @@ wp_error* stringmap_bump_size(stringmap *h) {
return NO_ERROR;
}
-uint32_t stringmap_put(stringmap *h, const char* key, int *ret) {
+uint32_t stringmap_put(stringmap *h, stringpool* pool, const char* key, int *ret) {
uint32_t x;
+ uint32_t* flags = STRINGMAP_FLAGS(h);
+ uint32_t* keys = STRINGMAP_KEYS(h);
{
#ifdef DEBUGOUTPUT
@@ -154,27 +157,27 @@ int num_loops = 0;
uint32_t inc, k, i, site, last;
x = site = h->n_buckets; k = string_hash(key); i = k % h->n_buckets;
//DEBUG("asked to hash '%s'. initial hash is %u => %u and n_occupied is %u", key, k, i, h->n_occupied);
- if (isempty(h->flags, i)) x = i;
+ if (isempty(flags, i)) x = i;
else {
inc = 1 + k % (h->n_buckets - 1); last = i;
- while (!isempty(h->flags, i) && (isdel(h->flags, i) || !string_equals(stringpool_lookup(h->pool, h->keys[i]), key))) {
+ while (!isempty(flags, i) && (isdel(flags, i) || !string_equals(stringpool_lookup(pool, keys[i]), key))) {
#ifdef DEBUGOUTPUT
num_loops++;
#endif
- if (isdel(h->flags, i)) site = i;
+ if (isdel(flags, i)) site = i;
if (i + inc >= h->n_buckets) i = i + inc - h->n_buckets;
else i += inc;
if (i == last) { x = site; break; }
}
if ((x == h->n_buckets) && (i == last)) { // out of space
- if(!string_equals(stringpool_lookup(h->pool, h->keys[i]), key)) {
+ if(!string_equals(stringpool_lookup(pool, keys[i]), key)) {
DEBUG("out of space!");
*ret = -1;
return x;
}
}
if (x == h->n_buckets) { // didn't find it on the first try
- if (isempty(h->flags, i) && site != h->n_buckets) x = site;
+ if (isempty(flags, i) && site != h->n_buckets) x = site;
else x = i;
}
}
@@ -185,15 +188,15 @@ num_loops++;
//DEBUG("for pos %u, isempty? %d and isdel %d", x, isempty(h->flags, x), isdel(h->flags, x));
uint32_t idx;
- if(isempty(h->flags, x) || isdel(h->flags, x)) {
- idx = stringpool_add(h->pool, key);
+ if(isempty(flags, x) || isdel(flags, x)) {
+ idx = stringpool_add(pool, key);
if(idx == (uint32_t)-1) {
*ret = -2;
return x;
}
- if (isempty(h->flags, x)) ++h->n_occupied;
- h->keys[x] = idx;
- set_isboth_false(h->flags, x);
+ if (isempty(flags, x)) ++h->n_occupied;
+ keys[x] = idx;
+ set_isboth_false(flags, x);
++h->size;
*ret = 1;
}
@@ -203,8 +206,9 @@ num_loops++;
}
void stringmap_del(stringmap *h, uint32_t x) {
- if (x != h->n_buckets && !iseither(h->flags, x)) {
- set_isdel_true(h->flags, x);
+ uint32_t* flags = STRINGMAP_FLAGS(h);
+ if (x != h->n_buckets && !iseither(flags, x)) {
+ set_isdel_true(flags, x);
--h->size;
}
}
@@ -255,24 +259,25 @@ uint32_t stringmap_next_size(stringmap* h) {
return size(prime_list[next_idx]);
}
-const char* stringmap_int_to_string(stringmap* h, uint32_t i) {
- return stringpool_lookup(h->pool, i);
+const char* stringmap_int_to_string(stringmap* h, stringpool* p, uint32_t i) {
+ (void)h;
+ return stringpool_lookup(p, i);
}
// returns -1 if not found
-uint32_t stringmap_string_to_int(stringmap* h, const char* s) {
- uint32_t idx = stringmap_get(h, s);
+uint32_t stringmap_string_to_int(stringmap* h, stringpool* pool, const char* s) {
+ uint32_t idx = stringmap_get(h, pool, s);
if(idx == h->n_buckets) return (uint32_t)-1; // not there
- return h->keys[idx];
+ return STRINGMAP_KEYS(h)[idx];
}
-wp_error* stringmap_add(stringmap *h, const char* s, uint32_t* id) {
+wp_error* stringmap_add(stringmap *h, stringpool* pool, const char* s, uint32_t* id) {
int status;
- uint32_t idx = stringmap_put(h, s, &status);
+ uint32_t idx = stringmap_put(h, pool, s, &status);
if(status == -1) RAISE_ERROR("out of space in hash put");
if(status == -2) RAISE_ERROR("out of space in pool put");
- *id = h->keys[idx];
+ *id = STRINGMAP_KEYS(h)[idx];
return NO_ERROR;
}
View
@@ -35,9 +35,6 @@
typedef struct stringmap {
uint8_t n_buckets_idx;
uint32_t n_buckets, size, n_occupied, upper_bound;
- uint32_t *flags;
- uint32_t *keys;
- stringpool* pool;
uint8_t boundary[];
// in memory at this point
// ((n_buckets >> 4) + 1) uint32_t's for the flags
@@ -47,21 +44,18 @@ typedef struct stringmap {
// API methods
// public: write a new stringmap to memory
-void stringmap_init(stringmap* h, stringpool* p);
-
-// public: set up an existing stringmap in memory
-void stringmap_setup(stringmap* h, stringpool* p);
+void stringmap_init(stringmap* h);
// public: add a string. sets id to its id. dupes are fine; will just set the
// id correctly.
-wp_error* stringmap_add(stringmap *h, const char* s, uint32_t* id) RAISES_ERROR;
+wp_error* stringmap_add(stringmap *h, stringpool* p, const char* s, uint32_t* id) RAISES_ERROR;
// public: get the int value given a string. returns (uint32_t)-1 if not found.
-uint32_t stringmap_string_to_int(stringmap* h, const char* s);
+uint32_t stringmap_string_to_int(stringmap* h, stringpool* pool, const char* s);
// public: get the string value given an int. returns corrupt data if the int
// is invalid.
-const char* stringmap_int_to_string(stringmap* h, uint32_t i);
+const char* stringmap_int_to_string(stringmap* h, stringpool* p, uint32_t i);
// public: returns the byte size of the stringmap
uint32_t stringmap_size(stringmap* h);
@@ -76,6 +70,6 @@ uint32_t stringmap_next_size(stringmap* h);
int stringmap_needs_bump(stringmap* h);
// public: increases the size of the stringmap
-wp_error* stringmap_bump_size(stringmap *h) RAISES_ERROR;
+wp_error* stringmap_bump_size(stringmap *h, stringpool* pool) RAISES_ERROR;
#endif

0 comments on commit 540ef7b

Please sign in to comment.