Created
October 5, 2009 11:57
-
-
Save nobu/202069 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: include/ruby/st.h | |
=================================================================== | |
--- include/ruby/st.h (revision 25235) | |
+++ include/ruby/st.h (working copy) | |
@@ -67,7 +67,16 @@ typedef int st_compare_func(st_data_t, s | |
typedef st_index_t st_hash_func(st_data_t); | |
+struct st_memfuncs_type { | |
+ void *(*st_malloc)(size_t); | |
+ void *(*st_calloc)(size_t, size_t); | |
+ void *(*st_realloc)(void *, size_t); | |
+ void (*st_free)(void *); | |
+ void (*st_too_big)(st_index_t); | |
+}; | |
+ | |
struct st_hash_type { | |
int (*compare)(ANYARGS /*st_data_t, st_data_t*/); /* st_compare_func* */ | |
st_index_t (*hash)(ANYARGS /*st_data_t*/); /* st_hash_func* */ | |
+ const struct st_memfuncs_type *memfuncs; | |
}; | |
@@ -90,4 +99,7 @@ struct st_table { | |
enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE, ST_CHECK}; | |
+const struct st_memfuncs_type *const st_default_memfuncs; | |
+const struct st_memfuncs_type st_memfuncs_standard; | |
+ | |
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); | |
@@ -113,4 +125,6 @@ st_table *st_copy(st_table *); | |
int st_numcmp(st_data_t, st_data_t); | |
st_index_t st_numhash(st_data_t); | |
+st_index_t st_strhash(st_data_t); | |
+st_index_t st_strcasehash(st_data_t); | |
int st_strcasecmp(const char *s1, const char *s2); | |
int st_strncasecmp(const char *s1, const char *s2, size_t n); | |
Index: st.c | |
=================================================================== | |
--- st.c (revision 25235) | |
+++ st.c (working copy) | |
@@ -8,4 +8,10 @@ | |
#else | |
#include "ruby/ruby.h" | |
+#undef st_init_numtable | |
+#undef st_init_numtable_with_size | |
+#undef st_init_strtable | |
+#undef st_init_strtable_with_size | |
+#undef st_init_strcasetable | |
+#undef st_init_strcasetable_with_size | |
#endif | |
@@ -39,4 +45,11 @@ struct st_table_entry { | |
*/ | |
+const struct st_memfuncs_type st_memfuncs_standard = { | |
+ malloc, calloc, realloc, free, | |
+}; | |
+ | |
+const struct st_memfuncs_type *const st_default_memfuncs = | |
+ &st_memfuncs_standard; | |
+ | |
static const struct st_hash_type type_numhash = { | |
st_numcmp, | |
@@ -45,33 +58,28 @@ static const struct st_hash_type type_nu | |
/* extern int strcmp(const char *, const char *); */ | |
-static st_index_t strhash(st_data_t); | |
static const struct st_hash_type type_strhash = { | |
strcmp, | |
- strhash, | |
+ st_strhash, | |
}; | |
-static st_index_t strcasehash(st_data_t); | |
static const struct st_hash_type type_strcasehash = { | |
st_strcasecmp, | |
- strcasehash, | |
+ st_strcasehash, | |
}; | |
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 Calloc(n,s) (char*)calloc((n),(s)) | |
+#define MEMFUNCS(t) ((t)->memfuncs ? (t)->memfuncs : st_default_memfuncs) | |
+#define alloc(t) (t*)(*memfuncs->st_malloc)(sizeof(t)) | |
+#define Calloc(n,s) (*memfuncs->st_calloc)(n,s) | |
+#define free(x) (*memfuncs->st_free)(x) | |
+#define realloc(p,n) (*memfuncs->st_realloc)(p,n) | |
-#define EQUAL(table,x,y) ((x)==(y) || (*table->type->compare)((x),(y)) == 0) | |
+#define EQUAL(table,x,y) ((x)==(y) || (*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)(st_index_t)(*type->hash)((key)) | |
#define do_hash_bin(key,table) (do_hash(key, table)%(table)->num_bins) | |
@@ -126,5 +134,4 @@ new_size(st_index_t size) | |
if ((1<<i) > size) return 1<<i; | |
} | |
- return -1; | |
#else | |
st_index_t newsize; | |
@@ -133,10 +140,7 @@ new_size(st_index_t size) | |
if (newsize > size) return primes[i]; | |
} | |
- /* Ran out of polynomials */ | |
-#ifndef NOT_RUBY | |
- rb_raise(rb_eRuntimeError, "st_table too big"); | |
#endif | |
+ /* Ran out of polynomials */ | |
return -1; /* should raise exception */ | |
-#endif | |
} | |
@@ -167,5 +171,7 @@ st_table* | |
st_init_table_with_size(const struct st_hash_type *type, st_index_t size) | |
{ | |
+ const struct st_memfuncs_type *const memfuncs = MEMFUNCS(type); | |
st_table *tbl; | |
+ const st_index_t orig_size = size; | |
#ifdef HASH_LOG | |
@@ -183,9 +189,14 @@ st_init_table_with_size(const struct st_ | |
size = new_size(size); /* round up to prime number */ | |
+ if (size < 0) { | |
+ if (memfuncs->st_too_big) memfuncs->st_too_big(orig_size); | |
+ return 0; | |
+ } | |
tbl = alloc(st_table); | |
tbl->type = type; | |
tbl->num_entries = 0; | |
- tbl->entries_packed = type == &type_numhash && size/2 <= MAX_PACKED_NUMHASH; | |
+ tbl->entries_packed = (type->compare == st_numcmp && type->hash == st_numhash) && | |
+ size/2 <= MAX_PACKED_NUMHASH; | |
tbl->num_bins = size; | |
tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*)); | |
@@ -241,4 +252,6 @@ void | |
st_clear(st_table *table) | |
{ | |
+ const struct st_hash_type *const type = table->type; | |
+ const struct st_memfuncs_type *const memfuncs = MEMFUNCS(type); | |
register st_table_entry *ptr, *next; | |
st_index_t i; | |
@@ -266,4 +279,6 @@ void | |
st_free_table(st_table *table) | |
{ | |
+ const struct st_hash_type *const type = table->type; | |
+ const struct st_memfuncs_type *const memfuncs = MEMFUNCS(type); | |
st_clear(table); | |
free(table->bins); | |
@@ -325,4 +340,5 @@ int | |
st_lookup(st_table *table, register st_data_t key, st_data_t *value) | |
{ | |
+ const struct st_hash_type *const type = table->type; | |
st_index_t hash_val, bin_pos; | |
register st_table_entry *ptr; | |
@@ -354,4 +370,5 @@ int | |
st_get_key(st_table *table, register st_data_t key, st_data_t *result) | |
{ | |
+ const struct st_hash_type *const type = table->type; | |
st_index_t hash_val, bin_pos; | |
register st_table_entry *ptr; | |
@@ -433,4 +450,6 @@ int | |
st_insert(register st_table *table, register st_data_t key, st_data_t value) | |
{ | |
+ const struct st_hash_type *const type = table->type; | |
+ const struct st_memfuncs_type *const memfuncs = MEMFUNCS(type); | |
st_index_t hash_val, bin_pos; | |
register st_table_entry *ptr; | |
@@ -472,4 +491,6 @@ st_insert2(register st_table *table, reg | |
st_data_t (*func)(st_data_t)) | |
{ | |
+ const struct st_hash_type *const type = table->type; | |
+ const struct st_memfuncs_type *const memfuncs = MEMFUNCS(type); | |
st_index_t hash_val, bin_pos; | |
register st_table_entry *ptr; | |
@@ -511,4 +532,6 @@ void | |
st_add_direct(st_table *table, st_data_t key, st_data_t value) | |
{ | |
+ const struct st_hash_type *const type = table->type; | |
+ const struct st_memfuncs_type *const memfuncs = MEMFUNCS(type); | |
st_index_t hash_val, bin_pos; | |
@@ -534,4 +557,6 @@ static void | |
rehash(register st_table *table) | |
{ | |
+ const struct st_hash_type *const type = table->type; | |
+ const struct st_memfuncs_type *const memfuncs = MEMFUNCS(type); | |
register st_table_entry *ptr, **new_bins; | |
st_index_t i, new_num_bins, hash_val; | |
@@ -539,5 +564,5 @@ 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; | |
@@ -556,4 +581,6 @@ st_table* | |
st_copy(st_table *old_table) | |
{ | |
+ const struct st_hash_type *const type = old_table->type; | |
+ const struct st_memfuncs_type *const memfuncs = MEMFUNCS(type); | |
st_table *new_table; | |
st_table_entry *ptr, *entry, *prev, **tail; | |
@@ -622,4 +649,6 @@ int | |
st_delete(register st_table *table, register st_data_t *key, st_data_t *value) | |
{ | |
+ const struct st_hash_type *const type = table->type; | |
+ const struct st_memfuncs_type *const memfuncs = MEMFUNCS(type); | |
st_index_t hash_val; | |
st_table_entry **prev; | |
@@ -661,4 +690,5 @@ int | |
st_delete_safe(register st_table *table, register st_data_t *key, st_data_t *value, st_data_t never) | |
{ | |
+ const struct st_hash_type *const type = table->type; | |
st_index_t hash_val; | |
register st_table_entry *ptr; | |
@@ -697,4 +727,6 @@ void | |
st_cleanup_safe(st_table *table, st_data_t never) | |
{ | |
+ const struct st_hash_type *const type = table->type; | |
+ const struct st_memfuncs_type *const memfuncs = MEMFUNCS(type); | |
st_table_entry *ptr, **last, *tmp; | |
st_index_t i; | |
@@ -733,4 +765,6 @@ int | |
st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) | |
{ | |
+ const struct st_hash_type *const type = table->type; | |
+ const struct st_memfuncs_type *const memfuncs = MEMFUNCS(type); | |
st_table_entry *ptr, **last, *tmp; | |
enum st_retval retval; | |
@@ -813,4 +847,5 @@ int | |
st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) | |
{ | |
+ const struct st_hash_type *const type = table->type; | |
st_table_entry *ptr, **last, *tmp; | |
enum st_retval retval; | |
@@ -969,5 +1004,5 @@ st_reverse_foreach(st_table *table, int | |
#ifdef ST_USE_FNV1 | |
static st_index_t | |
-strhash(st_data_t arg) | |
+st_strhash(st_data_t arg) | |
{ | |
register const char *string = (const char *)arg; | |
@@ -1235,6 +1270,6 @@ st_hash_start(st_index_t h) | |
} | |
-static st_index_t | |
-strhash(st_data_t arg) | |
+st_index_t | |
+st_strhash(st_data_t arg) | |
{ | |
register const char *string = (const char *)arg; | |
@@ -1292,6 +1327,6 @@ st_strncasecmp(const char *s1, const cha | |
} | |
-static st_index_t | |
-strcasehash(st_data_t arg) | |
+st_index_t | |
+st_strcasehash(st_data_t arg) | |
{ | |
register const char *string = (const char *)arg; | |
Index: hash.c | |
=================================================================== | |
--- hash.c (revision 25235) | |
+++ hash.c (working copy) | |
@@ -20,4 +20,69 @@ | |
#endif | |
+/* st_table initializers for ruby */ | |
+static void | |
+st_table_too_big(st_index_t size) | |
+{ | |
+ rb_raise(rb_eRuntimeError, "st_table too big %ld", (long)size); | |
+} | |
+ | |
+const struct st_memfuncs_type st_memfuncs_ruby = { | |
+ xmalloc, xcalloc, xrealloc, xfree, st_table_too_big, | |
+}; | |
+ | |
+static const struct st_hash_type ruby_numhash = { | |
+ st_numcmp, | |
+ st_numhash, | |
+ &st_memfuncs_ruby | |
+}; | |
+ | |
+static const struct st_hash_type ruby_strhash = { | |
+ strcmp, | |
+ st_strhash, | |
+ &st_memfuncs_ruby | |
+}; | |
+ | |
+static const struct st_hash_type ruby_strcasehash = { | |
+ st_strcasecmp, | |
+ st_strcasehash, | |
+ &st_memfuncs_ruby | |
+}; | |
+ | |
+st_table * | |
+ruby_init_numtable(void) | |
+{ | |
+ return st_init_table(&ruby_numhash); | |
+} | |
+ | |
+st_table * | |
+ruby_init_numtable_with_size(st_index_t size) | |
+{ | |
+ return st_init_table_with_size(&ruby_numhash, size); | |
+} | |
+ | |
+st_table * | |
+ruby_init_strtable(void) | |
+{ | |
+ return st_init_table(&ruby_strhash); | |
+} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment