Skip to content

Instantly share code, notes, and snippets.

@nobu
Created October 5, 2009 11:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nobu/202069 to your computer and use it in GitHub Desktop.
Save nobu/202069 to your computer and use it in GitHub Desktop.
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