diff options
| author | Yukihiro Matsumoto <[email protected]> | 2012-04-21 18:59:02 +0900 |
|---|---|---|
| committer | Yukihiro Matsumoto <[email protected]> | 2012-04-21 18:59:02 +0900 |
| commit | 9676edda669a3028c24fd9f1e7364c3b73dc7212 (patch) | |
| tree | 4442e5399f6258a7ca63eb3b022319f7d90412ee /src | |
| parent | 748d762e851e1954b72b7bbd70408353518e0a9d (diff) | |
| download | mruby-9676edda669a3028c24fd9f1e7364c3b73dc7212.tar.gz mruby-9676edda669a3028c24fd9f1e7364c3b73dc7212.zip | |
replace st.[ch] to remove SIZEOF_ST_INDEX_T
Diffstat (limited to 'src')
| -rw-r--r-- | src/encoding.c | 25 | ||||
| -rw-r--r-- | src/st.c | 867 | ||||
| -rw-r--r-- | src/st.h | 66 |
3 files changed, 131 insertions, 827 deletions
diff --git a/src/encoding.c b/src/encoding.c index db9a36425..9c50686c6 100644 --- a/src/encoding.c +++ b/src/encoding.c @@ -922,6 +922,31 @@ enc_name(mrb_state *mrb, mrb_value self) return mrb_usascii_str_new2(mrb, mrb_enc_name((mrb_encoding*)DATA_PTR(self))); } +struct fn_arg { + mrb_state *mrb; + int (*func)(ANYARGS); + void *a; +}; + +static int +fn_i(st_data_t key, st_data_t val, st_data_t arg) { + struct fn_arg *a = (struct fn_arg*)arg; + + return (*a->func)(a->mrb, key, val, a->a); +} + +static int +st_foreachNew(mrb_state *mrb, st_table *tbl, int (*func)(ANYARGS), void *a) +{ + struct fn_arg arg = { + mrb, + func, + a, + }; + + return st_foreach(tbl, fn_i, (st_data_t)&arg); +} + static int enc_names_i(mrb_state *mrb, st_data_t name, st_data_t idx, st_data_t args) { @@ -1,19 +1,13 @@ /* This is a public domain general purpose hash table package written by Peter Moore @ UCB. */ /* static char sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible"; */ -#define NOT_RUBY -#ifdef NOT_RUBY -#include "regint.h" -#include "st.h" -#else -#include "ruby/ruby.h" -#endif #include <stdio.h> #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif #include <string.h> +#include "st.h" #define ST_DEFAULT_MAX_DENSITY 5 #define ST_DEFAULT_INIT_TABLE_SIZE 11 @@ -27,15 +21,16 @@ * allocated initially * */ - -static const struct st_hash_type type_numhash = { - st_numcmp, - st_numhash, +static int numcmp(long, long); +static st_index_t numhash(long); +static struct st_hash_type type_numhash = { + numcmp, + numhash, }; /* extern int strcmp(const char *, const char *); */ -static st_index_t strhash(st_data_t); -static const struct st_hash_type type_strhash = { +static st_index_t strhash(const char *); +static struct st_hash_type type_strhash = { strcmp, strhash, }; @@ -51,18 +46,14 @@ static void rehash(st_table *); #ifdef RUBY #define malloc xmalloc #define calloc xcalloc -#define free(x) xfree(x) #endif -#define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) - -#define alloc(type) (type*)malloc((size_t)sizeof(type)) +#define alloc(type) (type*)malloc((unsigned)sizeof(type)) #define Calloc(n,s) (char*)calloc((n),(s)) #define EQUAL(table,x,y) ((x)==(y) || (*table->type->compare)((x),(y)) == 0) -/* remove cast to unsigned int in the future */ -#define do_hash(key,table) (unsigned int)(st_index_t)(*(table)->type->hash)((key)) +#define do_hash(key,table) (unsigned int)(*(table)->type->hash)((key)) #define do_hash_bin(key,table) (do_hash(key, table)%(table)->num_bins) /* @@ -74,7 +65,7 @@ static void rehash(st_table *); /* Table of prime numbers 2^n+a, 2<=n<=30. */ -static const unsigned int primes[] = { +static long primes[] = { 8 + 3, 16 + 3, 32 + 5, @@ -106,27 +97,32 @@ static const unsigned int primes[] = { 0 }; -static st_index_t -new_size(st_index_t size) +static int +new_size(int size) { int i; - st_index_t newsize; +#if 0 + for (i=3; i<31; i++) { + if ((1<<i) > size) return 1<<i; + } + return -1; +#else + int newsize; - for (i = 0, newsize = MINSIZE; i < numberof(primes); i++, newsize <<= 1) { + for (i = 0, newsize = MINSIZE; + i < sizeof(primes)/sizeof(primes[0]); + i++, newsize <<= 1) + { if (newsize > size) return primes[i]; } /* Ran out of polynomials */ -#ifndef NOT_RUBY - rb_raise(rb_eRuntimeError, "st_table too big"); -#endif return -1; /* should raise exception */ +#endif } -#define MAX_PACKED_NUMHASH (ST_DEFAULT_INIT_TABLE_SIZE/2) - st_table* -st_init_table_with_size(const struct st_hash_type *type, st_index_t size) +st_init_table_with_size(const struct st_hash_type *type, int size) { st_table *tbl; @@ -135,7 +131,6 @@ st_init_table_with_size(const struct st_hash_type *type, st_index_t size) tbl = alloc(st_table); tbl->type = type; tbl->num_entries = 0; - tbl->entries_packed = type == &type_numhash && size/2 <= MAX_PACKED_NUMHASH; tbl->num_bins = size; tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*)); tbl->head = 0; @@ -157,7 +152,7 @@ st_init_numtable(void) } st_table* -st_init_numtable_with_size(st_index_t size) +st_init_numtable_with_size(int size) { return st_init_table_with_size(&type_numhash, size); } @@ -169,7 +164,7 @@ st_init_strtable(void) } st_table* -st_init_strtable_with_size(st_index_t size) +st_init_strtable_with_size(int size) { return st_init_table_with_size(&type_strhash, size); } @@ -192,11 +187,6 @@ st_clear(st_table *table) register st_table_entry *ptr, *next; st_index_t i; - if (table->entries_packed) { - table->num_entries = 0; - return; - } - for(i = 0; i < table->num_bins; i++) { ptr = table->bins[i]; table->bins[i] = 0; @@ -219,29 +209,13 @@ st_free_table(st_table *table) free(table); } -size_t -st_memsize(const st_table *table) -{ - if (table->entries_packed) { - return table->num_bins * sizeof (void *) + sizeof(st_table); - } - else { - return table->num_entries * sizeof(struct st_table_entry) + table->num_bins * sizeof (void *) + sizeof(st_table); - } -} - #define PTR_NOT_EQUAL(table, ptr, hash_val, key) \ ((ptr) != 0 && (ptr->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key))) -#define COLLISION -#define FOUND_ENTRY - #define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\ bin_pos = hash_val%(table)->num_bins;\ ptr = (table)->bins[bin_pos];\ - FOUND_ENTRY;\ if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) {\ - COLLISION;\ while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {\ ptr = ptr->next;\ }\ @@ -249,25 +223,12 @@ st_memsize(const st_table *table) }\ } while (0) -#define collision_check 0 - int -st_lookup(st_table *table, register st_data_t key, st_data_t *value) +st_lookup(st_table *table, st_data_t key, st_data_t *value) { - st_index_t hash_val, bin_pos; + unsigned int hash_val, bin_pos; register st_table_entry *ptr; - if (table->entries_packed) { - st_index_t i; - for (i = 0; i < table->num_entries; i++) { - if ((st_data_t)table->bins[i*2] == key) { - if (value !=0) *value = (st_data_t)table->bins[i*2+1]; - return 1; - } - } - return 0; - } - hash_val = do_hash(key, table); FIND_ENTRY(table, ptr, hash_val, bin_pos); @@ -280,46 +241,10 @@ st_lookup(st_table *table, register st_data_t key, st_data_t *value) } } -int -st_get_key(st_table *table, register st_data_t key, st_data_t *result) -{ - st_index_t hash_val, bin_pos; - register st_table_entry *ptr; - - if (table->entries_packed) { - st_index_t i; - for (i = 0; i < table->num_entries; i++) { - if ((st_data_t)table->bins[i*2] == key) { - if (result !=0) *result = (st_data_t)table->bins[i*2]; - return 1; - } - } - return 0; - } - - hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); - - if (ptr == 0) { - return 0; - } - else { - if (result != 0) *result = ptr->key; - return 1; - } -} - -#undef collision_check -#define collision_check 1 - -#define MORE_PACKABLE_P(table) \ - ((st_index_t)((table)->num_entries+1) * 2 <= (table)->num_bins && \ - (table)->num_entries+1 <= MAX_PACKED_NUMHASH) - #define ADD_DIRECT(table, key, value, hash_val, bin_pos)\ do {\ st_table_entry *entry;\ - if (table->num_entries > ST_DEFAULT_MAX_DENSITY * table->num_bins) {\ + if (table->num_entries/(table->num_bins) > ST_DEFAULT_MAX_DENSITY) {\ rehash(table);\ bin_pos = hash_val % table->num_bins;\ }\ @@ -343,49 +268,12 @@ do {\ table->num_entries++;\ } while (0) -static void -unpack_entries(register st_table *table) -{ - st_index_t i; - struct st_table_entry *packed_bins[MAX_PACKED_NUMHASH*2]; - st_table tmp_table = *table; - - memcpy(packed_bins, table->bins, sizeof(struct st_table_entry *) * table->num_entries*2); - table->bins = packed_bins; - tmp_table.entries_packed = 0; - tmp_table.num_entries = 0; - memset(tmp_table.bins, 0, sizeof(struct st_table_entry *) * tmp_table.num_bins); - for (i = 0; i < table->num_entries; i++) { - st_insert(&tmp_table, (st_data_t)packed_bins[i*2], (st_data_t)packed_bins[i*2+1]); - } - *table = tmp_table; -} - int -st_insert(register st_table *table, register st_data_t key, st_data_t value) +st_insert(st_table *table, st_data_t key, st_data_t value) { - st_index_t hash_val, bin_pos; + unsigned int hash_val, bin_pos; register st_table_entry *ptr; - if (table->entries_packed) { - st_index_t i; - for (i = 0; i < table->num_entries; i++) { - if ((st_data_t)table->bins[i*2] == key) { - table->bins[i*2+1] = (struct st_table_entry*)value; - return 1; - } - } - if (MORE_PACKABLE_P(table)) { - i = table->num_entries++; - table->bins[i*2] = (struct st_table_entry*)key; - table->bins[i*2+1] = (struct st_table_entry*)value; - return 0; - } - else { - unpack_entries(table); - } - } - hash_val = do_hash(key, table); FIND_ENTRY(table, ptr, hash_val, bin_pos); @@ -399,63 +287,10 @@ st_insert(register st_table *table, register st_data_t key, st_data_t value) } } -int -st_insert2(register st_table *table, register st_data_t key, st_data_t value, - st_data_t (*func)(st_data_t)) -{ - st_index_t hash_val, bin_pos; - register st_table_entry *ptr; - - if (table->entries_packed) { - st_index_t i; - for (i = 0; i < table->num_entries; i++) { - if ((st_data_t)table->bins[i*2] == key) { - table->bins[i*2+1] = (struct st_table_entry*)value; - return 1; - } - } - if (MORE_PACKABLE_P(table)) { - i = table->num_entries++; - table->bins[i*2] = (struct st_table_entry*)key; - table->bins[i*2+1] = (struct st_table_entry*)value; - return 0; - } - else { - unpack_entries(table); - } - } - - hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); - - if (ptr == 0) { - key = (*func)(key); - ADD_DIRECT(table, key, value, hash_val, bin_pos); - return 0; - } - else { - ptr->record = value; - return 1; - } -} - void st_add_direct(st_table *table, st_data_t key, st_data_t value) { - st_index_t hash_val, bin_pos; - - if (table->entries_packed) { - int i; - if (MORE_PACKABLE_P(table)) { - i = table->num_entries++; - table->bins[i*2] = (struct st_table_entry*)key; - table->bins[i*2+1] = (struct st_table_entry*)value; - return; - } - else { - unpack_entries(table); - } - } + unsigned int hash_val, bin_pos; hash_val = do_hash(key, table); bin_pos = hash_val % table->num_bins; @@ -470,7 +305,7 @@ rehash(register st_table *table) new_num_bins = new_size(table->num_bins+1); new_bins = (st_table_entry**) - xrealloc(table->bins, new_num_bins * sizeof(st_table_entry*)); + realloc(table->bins, new_num_bins * sizeof(st_table_entry*)); for (i = 0; i < new_num_bins; ++i) new_bins[i] = 0; table->num_bins = new_num_bins; table->bins = new_bins; @@ -506,11 +341,6 @@ st_copy(st_table *old_table) return 0; } - if (old_table->entries_packed) { - memcpy(new_table->bins, old_table->bins, sizeof(struct st_table_entry *) * old_table->num_bins); - return new_table; - } - if ((ptr = old_table->head) != 0) { prev = 0; tail = &new_table->head; @@ -557,23 +387,7 @@ st_delete(register st_table *table, register st_data_t *key, st_data_t *value) st_table_entry **prev; register st_table_entry *ptr; - if (table->entries_packed) { - st_index_t i; - for (i = 0; i < table->num_entries; i++) { - if ((st_data_t)table->bins[i*2] == *key) { - if (value != 0) *value = (st_data_t)table->bins[i*2+1]; - table->num_entries--; - memmove(&table->bins[i*2], &table->bins[(i+1)*2], - sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); - return 1; - } - } - if (value != 0) *value = 0; - return 0; - } - hash_val = do_hash_bin(*key, table); - for (prev = &table->bins[hash_val]; (ptr = *prev) != 0; prev = &ptr->next) { if (EQUAL(table, *key, ptr->key)) { *prev = ptr->next; @@ -590,118 +404,12 @@ st_delete(register st_table *table, register st_data_t *key, st_data_t *value) } int -st_delete_safe(register st_table *table, register st_data_t *key, st_data_t *value, st_data_t never) -{ - st_index_t hash_val; - register st_table_entry *ptr; - - if (table->entries_packed) { - st_index_t i; - for (i = 0; i < table->num_entries; i++) { - if ((st_data_t)table->bins[i*2] == *key) { - if (value != 0) *value = (st_data_t)table->bins[i*2+1]; - table->bins[i*2] = (void *)never; - return 1; - } - } - if (value != 0) *value = 0; - return 0; - } - - hash_val = do_hash_bin(*key, table); - ptr = table->bins[hash_val]; - - for (; ptr != 0; ptr = ptr->next) { - if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) { - REMOVE_ENTRY(table, ptr); - *key = ptr->key; - if (value != 0) *value = ptr->record; - ptr->key = ptr->record = never; - return 1; - } - } - - if (value != 0) *value = 0; - return 0; -} - -void -st_cleanup_safe(st_table *table, st_data_t never) -{ - st_table_entry *ptr, **last, *tmp; - st_index_t i; - - if (table->entries_packed) { - st_index_t i = 0, j = 0; - while ((st_data_t)table->bins[i*2] != never) { - if (i++ == table->num_entries) return; - } - for (j = i; ++i < table->num_entries;) { - if ((st_data_t)table->bins[i*2] == never) continue; - table->bins[j*2] = table->bins[i*2]; - table->bins[j*2+1] = table->bins[i*2+1]; - j++; - } - table->num_entries = j; - return; - } - - for (i = 0; i < table->num_bins; i++) { - ptr = *(last = &table->bins[i]); - while (ptr != 0) { - if (ptr->key == never) { - tmp = ptr; - *last = ptr = ptr->next; - free(tmp); - } - else { - ptr = *(last = &ptr->next); - } - } - } -} - -int st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) { st_table_entry *ptr, **last, *tmp; enum st_retval retval; st_index_t i; - if (table->entries_packed) { - for (i = 0; i < table->num_entries; i++) { - st_index_t j; - st_data_t key, val; - key = (st_data_t)table->bins[i*2]; - val = (st_data_t)table->bins[i*2+1]; - retval = (*func)(key, val, arg); - switch (retval) { - case ST_CHECK: /* check if hash is modified during iteration */ - for (j = 0; j < table->num_entries; j++) { - if ((st_data_t)table->bins[j*2] == key) - break; - } - if (j == table->num_entries) { - /* call func with error notice */ - retval = (*func)(0, 0, arg, 1); - return 1; - } - /* fall through */ - case ST_CONTINUE: - break; - case ST_STOP: - return 0; - case ST_DELETE: - table->num_entries--; - memmove(&table->bins[i*2], &table->bins[(i+1)*2], - sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); - i--; - break; - } - } - return 0; - } - if ((ptr = table->head) != 0) { do { i = ptr->hash % table->num_bins; @@ -716,6 +424,7 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) } } /* fall through */ + default: case ST_CONTINUE: ptr = ptr->fore; break; @@ -740,466 +449,46 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) return 0; } -typedef int st_foreach_func(mrb_sym, void*, void *); - -struct foreach_safe_arg { - st_table *tbl; - st_foreach_func *func; - void *arg; -}; - -static int -foreach_safe_i(mrb_state *mrb, mrb_sym key, void* value, struct foreach_safe_arg *arg) -{ - int status; - - if (key == 0xffffffff/*key == Qundef*/) return ST_CONTINUE; - status = (*arg->func)(key, value, arg->arg); - if (status == ST_CONTINUE) { - return ST_CHECK; - } - return status; -} - -void -st_foreach_safe(mrb_state *mrb, void *table, int (*func)(ANYARGS), void* a) -{ - struct foreach_safe_arg arg; - - arg.tbl = table; - arg.func = (st_foreach_func *)func; - arg.arg = a; - if (st_foreach(table, foreach_safe_i, (st_data_t)&arg)) { - mrb_raise(mrb, mrb->eRuntimeError_class, "hash modified during iteration"); - } -} - -int -st_foreachNew(mrb_state *mrb, st_table *table, int (*func)(ANYARGS), void* arg) -{ - st_table_entry *ptr, **last, *tmp; - enum st_retval retval; - st_index_t i; - - if (table->entries_packed) { - for (i = 0; i < table->num_entries; i++) { - st_index_t j; - st_data_t key, val; - key = (st_data_t)table->bins[i*2]; - val = (st_data_t)table->bins[i*2+1]; - retval = (*func)(mrb, key, val, arg); - switch (retval) { - case ST_CHECK: /* check if hash is modified during iteration */ - for (j = 0; j < table->num_entries; j++) { - if ((st_data_t)table->bins[j*2] == key) - break; - } - if (j == table->num_entries) { - /* call func with error notice */ - retval = (*func)(0, 0, arg, 1); - return 1; - } - /* fall through */ - case ST_CONTINUE: - break; - case ST_STOP: - return 0; - case ST_DELETE: - table->num_entries--; - memmove(&table->bins[i*2], &table->bins[(i+1)*2], - sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); - i--; - break; - } - } - return 0; - } - - if ((ptr = table->head) != 0) { - do { - i = ptr->hash % table->num_bins; - retval = (*func)(mrb, ptr->key, ptr->record, arg); - switch (retval) { - case ST_CHECK: /* check if hash is modified during iteration */ - for (tmp = table->bins[i]; tmp != ptr; tmp = tmp->next) { - if (!tmp) { - /* call func with error notice */ - retval = (*func)(0, 0, arg, 1); - return 1; - } - } - /* fall through */ - case ST_CONTINUE: - ptr = ptr->fore; - break; - case ST_STOP: - return 0; - case ST_DELETE: - last = &table->bins[ptr->hash % table->num_bins]; - for (; (tmp = *last) != 0; last = &tmp->next) { - if (ptr == tmp) { - tmp = ptr->fore; - *last = ptr->next; - REMOVE_ENTRY(table, ptr); - free(ptr); - if (ptr == tmp) return 0; - ptr = tmp; - break; - } - } - } - } while (ptr && table->head); - } - return 0; -} - -/* - * hash_32 - 32 bit Fowler/Noll/Vo FNV-1a hash code - * - * @(#) $Hash32: Revision: 1.1 $ - * @(#) $Hash32: Id: hash_32a.c,v 1.1 2003/10/03 20:38:53 chongo Exp $ - * @(#) $Hash32: Source: /usr/local/src/cmd/fnv/RCS/hash_32a.c,v $ - * - *** - * - * Fowler/Noll/Vo hash - * - * The basis of this hash algorithm was taken from an idea sent - * as reviewer comments to the IEEE POSIX P1003.2 committee by: - * - * Phong Vo (http://www.research.att.com/info/kpv/) - * Glenn Fowler (http://www.research.att.com/~gsf/) - * - * In a subsequent ballot round: - * - * Landon Curt Noll (http://www.isthe.com/chongo/) - * - * improved on their algorithm. Some people tried this hash - * and found that it worked rather well. In an EMail message - * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash. - * - * FNV hashes are designed to be fast while maintaining a low - * collision rate. The FNV speed allows one to quickly hash lots - * of data while maintaining a reasonable collision rate. See: - * - * http://www.isthe.com/chongo/tech/comp/fnv/index.html - * - * for more details as well as other forms of the FNV hash. - *** - * - * To use the recommended 32 bit FNV-1a hash, pass FNV1_32A_INIT as the - * Fnv32_t hashval argument to fnv_32a_buf() or fnv_32a_str(). - * - *** - * - * Please do not copyright this code. This code is in the public domain. - * - * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO - * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF - * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - * - * By: - * chongo <Landon Curt Noll> /\oo/\ - * http://www.isthe.com/chongo/ - * - * Share and Enjoy! :-) - */ - -/* - * 32 bit FNV-1 and FNV-1a non-zero initial basis - * - * The FNV-1 initial basis is the FNV-0 hash of the following 32 octets: - * - * chongo <Landon Curt Noll> /\../\ - * - * NOTE: The \'s above are not back-slashing escape characters. - * They are literal ASCII backslash 0x5c characters. - * - * NOTE: The FNV-1a initial basis is the same value as FNV-1 by definition. - */ -#define FNV1_32A_INIT 0x811c9dc5 - -/* - * 32 bit magic FNV-1a prime - */ -#define FNV_32_PRIME 0x01000193 - -#ifdef ST_USE_FNV1 static st_index_t -strhash(st_data_t arg) +strhash(const char *string) { - register const char *string = (const char *)arg; - register st_index_t hval = FNV1_32A_INIT; + register int c; - /* - * FNV-1a hash each octet in the buffer - */ - while (*string) { - /* xor the bottom with the current octet */ - hval ^= (unsigned int)*string++; +#ifdef HASH_ELFHASH + register unsigned int h = 0, g; - /* multiply by the 32 bit FNV magic prime mod 2^32 */ - hval *= FNV_32_PRIME; + while ((c = *string++) != '\0') { + h = ( h << 4 ) + c; + if ( g = h & 0xF0000000 ) + h ^= g >> 24; + h &= ~g; } - return hval; -} -#else - -#ifndef UNALIGNED_WORD_ACCESS -# if defined __i386__ || defined _M_IX86 -# define UNALIGNED_WORD_ACCESS 1 -# endif -#endif -#ifndef UNALIGNED_WORD_ACCESS -# define UNALIGNED_WORD_ACCESS 0 -#endif - -/* MurmurHash described in http://murmurhash.googlepages.com/ */ -#ifndef MURMUR -#define MURMUR 2 -#endif - -#if MURMUR == 1 -#define MurmurMagic 0xc6a4a793 -#elif MURMUR == 2 -#if SIZEOF_ST_INDEX_T > 4 -#define MurmurMagic 0xc6a4a7935bd1e995 -#else -#define MurmurMagic 0x5bd1e995 -#endif -#endif - -static inline st_index_t -murmur(st_index_t h, st_index_t k, int r) -{ - const st_index_t m = MurmurMagic; -#if MURMUR == 1 - h += k; - h *= m; - h ^= h >> r; -#elif MURMUR == 2 - k *= m; - k ^= k >> r; - k *= m; - - h *= m; - h ^= k; -#endif return h; -} - -static inline st_index_t -murmur_finish(st_index_t h) -{ -#if MURMUR == 1 - h = murmur(h, 0, 10); - h = murmur(h, 0, 17); -#elif MURMUR == 2 - h ^= h >> 13; - h *= MurmurMagic; - h ^= h >> 15; -#endif - return h; -} - -#define murmur_step(h, k) murmur(h, k, 16) - -#if MURMUR == 1 -#define murmur1(h) murmur_step(h, 16) -#else -#define murmur1(h) murmur_step(h, 24) -#endif - -st_index_t -st_hash(const void *ptr, size_t len, st_index_t h) -{ - const char *data = ptr; - st_index_t t = 0; - - h += 0xdeadbeef; - -#define data_at(n) (st_index_t)((unsigned char)data[n]) -#define UNALIGNED_ADD_4 UNALIGNED_ADD(2); UNALIGNED_ADD(1); UNALIGNED_ADD(0) -#if SIZEOF_ST_INDEX_T > 4 -#define UNALIGNED_ADD_8 UNALIGNED_ADD(6); UNALIGNED_ADD(5); UNALIGNED_ADD(4); UNALIGNED_ADD(3); UNALIGNED_ADD_4 -#if SIZEOF_ST_INDEX_T > 8 -#define UNALIGNED_ADD_16 UNALIGNED_ADD(14); UNALIGNED_ADD(13); UNALIGNED_ADD(12); UNALIGNED_ADD(11); \ - UNALIGNED_ADD(10); UNALIGNED_ADD(9); UNALIGNED_ADD(8); UNALIGNED_ADD(7); UNALIGNED_ADD_8 -#define UNALIGNED_ADD_ALL UNALIGNED_ADD_16 -#endif -#define UNALIGNED_ADD_ALL UNALIGNED_ADD_8 -#else -#define UNALIGNED_ADD_ALL UNALIGNED_ADD_4 -#endif - if (len >= sizeof(st_index_t)) { -#if !UNALIGNED_WORD_ACCESS - int align = (int)((st_data_t)data % sizeof(st_index_t)); - if (align) { - st_index_t d = 0; - int sl, sr, pack; - - switch (align) { -#ifdef WORDS_BIGENDIAN -# define UNALIGNED_ADD(n) case SIZEOF_ST_INDEX_T - (n) - 1: \ - t |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 2) -#else -# define UNALIGNED_ADD(n) case SIZEOF_ST_INDEX_T - (n) - 1: \ - t |= data_at(n) << CHAR_BIT*(n) -#endif - UNALIGNED_ADD_ALL; -#undef UNALIGNED_ADD - } - -#ifdef WORDS_BIGENDIAN - t >>= (CHAR_BIT * align) - CHAR_BIT; -#else - t <<= (CHAR_BIT * align); -#endif +#elif defined(HASH_PERL) + register int val = 0; - data += sizeof(st_index_t)-align; - len -= sizeof(st_index_t)-align; - - sl = CHAR_BIT * (SIZEOF_ST_INDEX_T-align); - sr = CHAR_BIT * align; - - while (len >= sizeof(st_index_t)) { - d = *(st_index_t *)data; -#ifdef WORDS_BIGENDIAN - t = (t << sr) | (d >> sl); -#else - t = (t >> sr) | (d << sl); -#endif - h = murmur_step(h, t); - t = d; - data += sizeof(st_index_t); - len -= sizeof(st_index_t); - } - - pack = len < (size_t)align ? (int)len : align; - d = 0; - switch (pack) { -#ifdef WORDS_BIGENDIAN -# define UNALIGNED_ADD(n) case (n) + 1: \ - d |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 1) -#else -# define UNALIGNED_ADD(n) case (n) + 1: \ - d |= data_at(n) << CHAR_BIT*(n) -#endif - UNALIGNED_ADD_ALL; -#undef UNALIGNED_ADD - } -#ifdef WORDS_BIGENDIAN - t = (t << sr) | (d >> sl); -#else - t = (t >> sr) | (d << sl); -#endif - -#if MURMUR == 2 - if (len < (size_t)align) goto skip_tail; -#endif - h = murmur_step(h, t); - data += pack; - len -= pack; - } - else -#endif - { - do { - h = murmur_step(h, *(st_index_t *)data); - data += sizeof(st_index_t); - len -= sizeof(st_index_t); - } while (len >= sizeof(st_index_t)); - } + while ((c = *string++) != '\0') { + val += c; + val += (val << 10); + val ^= (val >> 6); } + val += (val << 3); + val ^= (val >> 11); - t = 0; - switch (len) { -#ifdef WORDS_BIGENDIAN -# define UNALIGNED_ADD(n) case (n) + 1: \ - t |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 1) + return val + (val << 15); #else -# define UNALIGNED_ADD(n) case (n) + 1: \ - t |= data_at(n) << CHAR_BIT*(n) -#endif - UNALIGNED_ADD_ALL; -#undef UNALIGNED_ADD -#if MURMUR == 1 - h = murmur_step(h, t); -#elif MURMUR == 2 -# if !UNALIGNED_WORD_ACCESS - skip_tail: -# endif - h ^= t; - h *= MurmurMagic; -#endif - } - - return murmur_finish(h); -} + register int val = 0; -st_index_t -st_hash_uint32(st_index_t h, uint32_t i) -{ - return murmur_step(h + i, 16); -} + while ((c = *string++) != '\0') { + val = val*997 + c; + } -st_index_t -st_hash_uint(st_index_t h, st_index_t i) -{ - st_index_t v = 0; - h += i; -#ifdef WORDS_BIGENDIAN -#if SIZEOF_ST_INDEX_T*CHAR_BIT > 12*8 - v = murmur1(v + (h >> 12*8)); -#endif -#if SIZEOF_ST_INDEX_T*CHAR_BIT > 8*8 - v = murmur1(v + (h >> 8*8)); -#endif -#if SIZEOF_ST_INDEX_T*CHAR_BIT > 4*8 - v = murmur1(v + (h >> 4*8)); -#endif -#endif - v = murmur1(v + h); -#ifndef WORDS_BIGENDIAN -#if SIZEOF_ST_INDEX_T*CHAR_BIT > 4*8 - v = murmur1(v + (h >> 4*8)); -#endif -#if SIZEOF_ST_INDEX_T*CHAR_BIT > 8*8 - v = murmur1(v + (h >> 8*8)); -#endif -#if SIZEOF_ST_INDEX_T*CHAR_BIT > 12*8 - v = murmur1(v + (h >> 12*8)); + return val + (val>>5); #endif -#endif - return v; -} - -st_index_t -st_hash_end(st_index_t h) -{ - h = murmur_step(h, 10); - h = murmur_step(h, 17); - return h; } -#undef st_hash_start -st_index_t -st_hash_start(st_index_t h) -{ - return h; -} - -static st_index_t -strhash(st_data_t arg) -{ - register const char *string = (const char *)arg; - return st_hash(string, strlen(string), FNV1_32A_INIT); -} -#endif +#define FNV1_32A_INIT 0x811c9dc5 +#define FNV_32_PRIME 0x01000193 int st_strcasecmp(const char *s1, const char *s2) @@ -1270,14 +559,38 @@ strcasehash(st_data_t arg) return hval; } -int -st_numcmp(st_data_t x, st_data_t y) +static int +numcmp(long x, long y) { return x != y; } -st_index_t -st_numhash(st_data_t n) +static st_index_t +numhash(long n) +{ + return n; +} + +#if 0 +static int +f(st_data_t key, st_data_t val, st_data_t a) +{ + printf("tbl=%p key=%s val=%s\n", (st_table*)a, (char*)key, (char*)val); + // return ST_CONTINUE; +} + +void +main(int argc, char **argv) { - return (st_index_t)n; + st_table *tbl = st_init_strtable(); + int i; + + for (i = 1; i<argc; i+=2) { + st_insert(tbl, (st_data_t)argv[i], (st_data_t)argv[i+1]); + } + st_foreach(tbl, f, (st_data_t)tbl); + st_delete(tbl, (st_data_t*)&argv[1], 0); + st_foreach(tbl, f, (st_data_t)tbl); } +#endif + @@ -9,23 +9,8 @@ extern "C" { #endif -#ifndef RUBY_LIB_PREFIX - -#ifdef RUBY_EXTCONF_H -#include RUBY_EXTCONF_H -#endif -#endif - -#if defined STDC_HEADERS -#include <stddef.h> -#elif defined HAVE_STDLIB_H #include <stdlib.h> -#endif - -#ifdef HAVE_STDINT_H -# include <stdint.h> -#endif -#include <inttypes.h> +#include <stdint.h> #ifndef CHAR_BIT # ifdef HAVE_LIMITS_H @@ -35,10 +20,6 @@ extern "C" { # endif #endif -#ifndef _ -# define _(args) args -#endif - #ifndef ANYARGS # ifdef __cplusplus # define ANYARGS ... @@ -69,16 +50,10 @@ struct st_hash_type { st_index_t (*hash)(ANYARGS /*st_data_t*/); /* st_hash_func* */ }; -#define ST_INDEX_BITS (sizeof(st_index_t) * CHAR_BIT) - struct st_table { const struct st_hash_type *type; - st_index_t num_bins; - unsigned int entries_packed : 1; -#ifdef __GNUC__ - __extension__ -#endif - st_index_t num_entries : ST_INDEX_BITS - 1; + int num_bins; + int num_entries; struct st_table_entry **bins; struct st_table_entry *head, *tail; }; @@ -88,46 +63,37 @@ struct st_table { enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE, ST_CHECK}; st_table *st_init_table(const struct st_hash_type *); -st_table *st_init_table_with_size(const struct st_hash_type *, st_index_t); +st_table *st_init_table_with_size(const struct st_hash_type *, int); st_table *st_init_numtable(void); -st_table *st_init_numtable_with_size(st_index_t); +st_table *st_init_numtable_with_size(int); st_table *st_init_strtable(void); -st_table *st_init_strtable_with_size(st_index_t); +st_table *st_init_strtable_with_size(int); st_table *st_init_strcasetable(void); st_table *st_init_strcasetable_with_size(st_index_t); -int st_delete(st_table *, st_data_t *, st_data_t *); /* returns 0:notfound 1:deleted */ +int st_delete(st_table *, st_data_t *, st_data_t *); int st_delete_safe(st_table *, st_data_t *, st_data_t *, st_data_t); int st_insert(st_table *, st_data_t, st_data_t); -int st_insert2(st_table *, st_data_t, st_data_t, st_data_t (*)(st_data_t)); int st_lookup(st_table *, st_data_t, st_data_t *); -int st_get_key(st_table *, st_data_t, st_data_t *); int st_foreach(st_table *, int (*)(ANYARGS), st_data_t); -int st_foreachNew(mrb_state *mrb, st_table *, int (*)(ANYARGS), void*); -int st_reverse_foreach(st_table *, int (*)(ANYARGS), st_data_t); void st_add_direct(st_table *, st_data_t, st_data_t); void st_free_table(st_table *); void st_cleanup_safe(st_table *, st_data_t); -void st_clear(st_table *); st_table *st_copy(st_table *); -int st_numcmp(st_data_t, st_data_t); -st_index_t st_numhash(st_data_t); -int st_strcasecmp(const char *s1, const char *s2); -int st_strncasecmp(const char *s1, const char *s2, size_t n); -size_t st_memsize(const st_table *); -st_index_t st_hash(const void *ptr, size_t len, st_index_t h); -st_index_t st_hash_uint32(st_index_t h, uint32_t i); -st_index_t st_hash_uint(st_index_t h, st_index_t i); -st_index_t st_hash_end(st_index_t h); -st_index_t st_hash_start(st_index_t h); -#define st_hash_start(h) ((st_index_t)(h)) - int st_strcasecmp(const char *s1, const char *s2); int st_strncasecmp(const char *s1, const char *s2, size_t n); #define STRCASECMP(s1, s2) (st_strcasecmp(s1, s2)) #define STRNCASECMP(s1, s2, n) (st_strncasecmp(s1, s2, n)) +#define ST_NUMCMP ((int (*)()) 0) +#define ST_NUMHASH ((int (*)()) -2) + +#define st_numcmp ST_NUMCMP +#define st_numhash ST_NUMHASH + +int st_strhash(); + #if defined(__cplusplus) } /* extern "C" { */ #endif -#endif /* RUBY_ST_H */ +#endif /* ST_INCLUDED */ |
