Skip to content

Instantly share code, notes, and snippets.

@larskanis
Created November 17, 2011 13:44
Show Gist options
  • Save larskanis/1373160 to your computer and use it in GitHub Desktop.
Save larskanis/1373160 to your computer and use it in GitHub Desktop.
Differences between st.h in rbx and st.c in mri-1.9.3 regarding to https://github.com/rubinius/rubinius/pull/1383
--- /home/lars/.rvm/src/ruby-1.9.3-p0/st.c 2011-01-27 15:30:00.000000000 +0100
+++ vm/capi/19/include/ruby/st.h 2011-10-28 23:17:41.741629969 +0200
@@ -1,18 +1,89 @@
/* 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"; */
+/* @(#) st.h 5.1 89/12/14 */
+
+#ifndef RUBY_ST_H
+#define RUBY_ST_H 1
+
+#if defined(__cplusplus)
+extern "C" {
+#if 0
+} /* satisfy cc-mode */
+#endif
+#endif
+
+#if defined __GNUC__ && __GNUC__ >= 4
+#pragma GCC visibility push(default)
+#endif
-#ifdef NOT_RUBY
-#include "regint.h"
-#include "st.h"
+#if SIZEOF_LONG == SIZEOF_VOIDP
+typedef unsigned long st_data_t;
+#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
+typedef unsigned LONG_LONG st_data_t;
#else
-#include "ruby/ruby.h"
+# error ---->> st.c requires sizeof(void*) == sizeof(long) to be compiled. <<----
+#endif
+#define ST_DATA_T_DEFINED
+
+#ifndef CHAR_BIT
+# ifdef HAVE_LIMITS_H
+# include <limits.h>
+# else
+# define CHAR_BIT 8
+# endif
+#endif
+
+typedef struct st_table st_table;
+
+typedef st_data_t st_index_t;
+typedef int st_compare_func(st_data_t, st_data_t);
+typedef st_index_t st_hash_func(st_data_t);
+
+typedef char st_check_for_sizeof_st_index_t[SIZEOF_VOIDP == (int)sizeof(st_index_t) ? 1 : -1];
+#define SIZEOF_ST_INDEX_T SIZEOF_VOIDP
+
+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* */
+};
+
+#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__
+ /*
+ * C spec says,
+ * A bit-field shall have a type that is a qualified or unqualified
+ * version of _Bool, signed int, unsigned int, or some other
+ * implementation-defined type. It is implementation-defined whether
+ * atomic types are permitted.
+ * In short, long and long long bit-field are implementation-defined
+ * feature. Therefore we want to supress a warning explicitly.
+ */
+ __extension__
#endif
+ st_index_t num_entries : ST_INDEX_BITS - 1;
+ struct st_table_entry **bins;
+ struct st_table_entry *head, *tail;
+};
+
+#define st_is_member(table,key) st_lookup((table),(key),(st_data_t *)0)
+
+enum st_retval {ST_CONTINUE = 0, ST_STOP = 1, ST_DELETE = 2, ST_CHECK};
+
+
+/* This is st.c, stuck in here, and with all the functions set to static. */
+
+
+/* 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"; */
#include <stdio.h>
-#ifdef HAVE_STDLIB_H
#include <stdlib.h>
-#endif
#include <string.h>
typedef struct st_table_entry st_table_entry;
@@ -38,53 +109,51 @@
*
*/
+static int st_numcmp(st_data_t, st_data_t);
+static st_index_t st_numhash(st_data_t);
static const struct st_hash_type type_numhash = {
- st_numcmp,
- st_numhash,
+ (int (*)(ANYARGS))st_numcmp,
+ (st_index_t (*)(ANYARGS))st_numhash,
};
/* 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,
+static st_index_t st_internal_strhash(st_data_t);
+static const struct st_hash_type type_st_internal_strhash = {
+ (int (*)(ANYARGS))strcmp,
+ (st_index_t (*)(ANYARGS))st_internal_strhash,
};
-static st_index_t strcasehash(st_data_t);
-static const struct st_hash_type type_strcasehash = {
- st_strcasecmp,
- strcasehash,
+static int st_strcasecmp(const char *, const char *);
+static st_index_t st_internal_strcasehash(st_data_t);
+static const struct st_hash_type type_st_internal_strcasehash = {
+ (int (*)(ANYARGS))st_strcasecmp,
+ (st_index_t (*)(ANYARGS))st_internal_strcasehash,
};
-static void rehash(st_table *);
-
-#ifdef RUBY
-#define malloc xmalloc
-#define calloc xcalloc
-#define free(x) xfree(x)
-#endif
+static void st_internal_rehash(st_table *);
+static int st_insert(register st_table *, register st_data_t, st_data_t);
-#define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
+#define st_internal_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 st_internal_alloc(type) (type*)xmalloc((size_t)sizeof(type))
+#define st_internal_calloc(n,s) (char*)xcalloc((n),(s))
-#define EQUAL(table,x,y) ((x)==(y) || (*(table)->type->compare)((x),(y)) == 0)
+#define ST_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_bin(key,table) (do_hash((key), (table))%(table)->num_bins)
+#define st_do_hash(key,table) (unsigned int)(st_index_t)(*(table)->type->hash)((key))
+#define st_do_hash_bin(key,table) (st_do_hash((key), (table))%(table)->num_bins)
/*
- * MINSIZE is the minimum size of a dictionary.
+ * ST_MINSIZE is the minimum size of a dictionary.
*/
-#define MINSIZE 8
+#define ST_MINSIZE 8
/*
Table of prime numbers 2^n+a, 2<=n<=30.
*/
-static const unsigned int primes[] = {
+static const unsigned int st_internal_primes[] = {
8 + 3,
16 + 3,
32 + 5,
@@ -117,127 +186,84 @@
};
static st_index_t
-new_size(st_index_t size)
+st_internal_new_size(st_index_t size)
{
int i;
-#if 0
- for (i=3; i<31; i++) {
- if ((1<<i) > size) return 1<<i;
- }
- return -1;
-#else
st_index_t newsize;
- for (i = 0, newsize = MINSIZE; i < numberof(primes); i++, newsize <<= 1) {
- if (newsize > size) return primes[i];
+ for (i = 0, newsize = ST_MINSIZE; i < st_internal_numberof(st_internal_primes); i++, newsize <<= 1) {
+ if (newsize > size) return st_internal_primes[i];
}
/* Ran out of polynomials */
-#ifndef NOT_RUBY
rb_raise(rb_eRuntimeError, "st_table too big");
-#endif
return -1; /* should raise exception */
-#endif
-}
-
-#ifdef HASH_LOG
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-static struct {
- int all, total, num, str, strcase;
-} collision;
-static int init_st = 0;
-
-static void
-stat_col(void)
-{
- char fname[10+sizeof(long)*3];
- FILE *f = fopen((snprintf(fname, sizeof(fname), "/tmp/col%ld", (long)getpid()), fname), "w");
- fprintf(f, "collision: %d / %d (%6.2f)\n", collision.all, collision.total,
- ((double)collision.all / (collision.total)) * 100);
- fprintf(f, "num: %d, str: %d, strcase: %d\n", collision.num, collision.str, collision.strcase);
- fclose(f);
}
-#endif
-#define MAX_PACKED_NUMHASH (ST_DEFAULT_INIT_TABLE_SIZE/2)
+#define ST_MAX_PACKED_NUMHASH (ST_DEFAULT_INIT_TABLE_SIZE/2)
-st_table*
+static st_table*
st_init_table_with_size(const struct st_hash_type *type, st_index_t size)
{
st_table *tbl;
-#ifdef HASH_LOG
-# if HASH_LOG+0 < 0
- {
- const char *e = getenv("ST_HASH_LOG");
- if (!e || !*e) init_st = 1;
- }
-# endif
- if (init_st == 0) {
- init_st = 1;
- atexit(stat_col);
- }
-#endif
+ size = st_internal_new_size(size); /* round up to prime number */
- size = new_size(size); /* round up to prime number */
-
- tbl = alloc(st_table);
+ tbl = st_internal_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 == &type_numhash && size/2 <= ST_MAX_PACKED_NUMHASH;
tbl->num_bins = size;
- tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*));
+ tbl->bins = (st_table_entry **)st_internal_calloc(size, sizeof(st_table_entry*));
tbl->head = 0;
tbl->tail = 0;
return tbl;
}
-st_table*
+static st_table*
st_init_table(const struct st_hash_type *type)
{
return st_init_table_with_size(type, 0);
}
-st_table*
+static st_table*
st_init_numtable(void)
{
return st_init_table(&type_numhash);
}
-st_table*
+static st_table*
st_init_numtable_with_size(st_index_t size)
{
return st_init_table_with_size(&type_numhash, size);
}
-st_table*
+static st_table*
st_init_strtable(void)
{
- return st_init_table(&type_strhash);
+ return st_init_table(&type_st_internal_strhash);
}
-st_table*
+static st_table*
st_init_strtable_with_size(st_index_t size)
{
- return st_init_table_with_size(&type_strhash, size);
+ return st_init_table_with_size(&type_st_internal_strhash, size);
}
-st_table*
+static st_table*
st_init_strcasetable(void)
{
- return st_init_table(&type_strcasehash);
+ return st_init_table(&type_st_internal_strcasehash);
}
-st_table*
+static st_table*
st_init_strcasetable_with_size(st_index_t size)
{
- return st_init_table_with_size(&type_strcasehash, size);
+ return st_init_table_with_size(&type_st_internal_strcasehash, size);
}
-void
+static void
st_clear(st_table *table)
{
register st_table_entry *ptr, *next;
@@ -262,7 +288,7 @@
table->tail = 0;
}
-void
+static void
st_free_table(st_table *table)
{
st_clear(table);
@@ -270,7 +296,7 @@
free(table);
}
-size_t
+static size_t
st_memsize(const st_table *table)
{
if (table->entries_packed) {
@@ -281,47 +307,21 @@
}
}
-#define PTR_NOT_EQUAL(table, ptr, hash_val, key) \
-((ptr) != 0 && ((ptr)->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key)))
-
-#ifdef HASH_LOG
-static void
-count_collision(const struct st_hash_type *type)
-{
- collision.all++;
- if (type == &type_numhash) {
- collision.num++;
- }
- else if (type == &type_strhash) {
- collision.strcase++;
- }
- else if (type == &type_strcasehash) {
- collision.str++;
- }
-}
-#define COLLISION (collision_check ? count_collision(table->type) : (void)0)
-#define FOUND_ENTRY (collision_check ? collision.total++ : (void)0)
-#else
-#define COLLISION
-#define FOUND_ENTRY
-#endif
+#define ST_PTR_NOT_EQUAL(table, ptr, hash_val, key) \
+((ptr) != 0 && ((ptr)->hash != (hash_val) || !ST_EQUAL((table), (key), (ptr)->key)))
-#define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\
+#define ST_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)) {\
+ if (ST_PTR_NOT_EQUAL((table), (ptr), (hash_val), key)) {\
+ while (ST_PTR_NOT_EQUAL((table), (ptr)->next, (hash_val), key)) {\
(ptr) = (ptr)->next;\
}\
(ptr) = (ptr)->next;\
}\
} while (0)
-#define collision_check 0
-
-int
+static int
st_lookup(st_table *table, register st_data_t key, st_data_t *value)
{
st_index_t hash_val, bin_pos;
@@ -338,8 +338,8 @@
return 0;
}
- hash_val = do_hash(key, table);
- FIND_ENTRY(table, ptr, hash_val, bin_pos);
+ hash_val = st_do_hash(key, table);
+ ST_FIND_ENTRY(table, ptr, hash_val, bin_pos);
if (ptr == 0) {
return 0;
@@ -350,7 +350,7 @@
}
}
-int
+static int
st_get_key(st_table *table, register st_data_t key, st_data_t *result)
{
st_index_t hash_val, bin_pos;
@@ -367,8 +367,8 @@
return 0;
}
- hash_val = do_hash(key, table);
- FIND_ENTRY(table, ptr, hash_val, bin_pos);
+ hash_val = st_do_hash(key, table);
+ ST_FIND_ENTRY(table, ptr, hash_val, bin_pos);
if (ptr == 0) {
return 0;
@@ -379,22 +379,19 @@
}
}
-#undef collision_check
-#define collision_check 1
-
-#define MORE_PACKABLE_P(table) \
+#define ST_MORE_PACKABLE_P(table) \
((st_index_t)((table)->num_entries+1) * 2 <= (table)->num_bins && \
- (table)->num_entries+1 <= MAX_PACKED_NUMHASH)
+ (table)->num_entries+1 <= ST_MAX_PACKED_NUMHASH)
-#define ADD_DIRECT(table, key, value, hash_val, bin_pos)\
+#define ST_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) {\
- rehash(table);\
+ st_internal_rehash(table);\
(bin_pos) = (hash_val) % (table)->num_bins;\
}\
\
- entry = alloc(st_table_entry);\
+ entry = st_internal_alloc(st_table_entry);\
\
entry->hash = (hash_val);\
entry->key = (key);\
@@ -414,10 +411,10 @@
} while (0)
static void
-unpack_entries(register st_table *table)
+st_internal_unpack_entries(register st_table *table)
{
st_index_t i;
- struct st_table_entry *packed_bins[MAX_PACKED_NUMHASH*2];
+ struct st_table_entry *packed_bins[ST_MAX_PACKED_NUMHASH*2];
st_table tmp_table = *table;
memcpy(packed_bins, table->bins, sizeof(struct st_table_entry *) * table->num_entries*2);
@@ -431,7 +428,7 @@
*table = tmp_table;
}
-int
+static int
st_insert(register st_table *table, register st_data_t key, st_data_t value)
{
st_index_t hash_val, bin_pos;
@@ -445,22 +442,22 @@
return 1;
}
}
- if (MORE_PACKABLE_P(table)) {
+ if (ST_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);
+ st_internal_unpack_entries(table);
}
}
- hash_val = do_hash(key, table);
- FIND_ENTRY(table, ptr, hash_val, bin_pos);
+ hash_val = st_do_hash(key, table);
+ ST_FIND_ENTRY(table, ptr, hash_val, bin_pos);
if (ptr == 0) {
- ADD_DIRECT(table, key, value, hash_val, bin_pos);
+ ST_ADD_DIRECT(table, key, value, hash_val, bin_pos);
return 0;
}
else {
@@ -469,7 +466,7 @@
}
}
-int
+static int
st_insert2(register st_table *table, register st_data_t key, st_data_t value,
st_data_t (*func)(st_data_t))
{
@@ -484,23 +481,23 @@
return 1;
}
}
- if (MORE_PACKABLE_P(table)) {
+ if (ST_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);
+ st_internal_unpack_entries(table);
}
}
- hash_val = do_hash(key, table);
- FIND_ENTRY(table, ptr, hash_val, bin_pos);
+ hash_val = st_do_hash(key, table);
+ ST_FIND_ENTRY(table, ptr, hash_val, bin_pos);
if (ptr == 0) {
key = (*func)(key);
- ADD_DIRECT(table, key, value, hash_val, bin_pos);
+ ST_ADD_DIRECT(table, key, value, hash_val, bin_pos);
return 0;
}
else {
@@ -509,36 +506,36 @@
}
}
-void
+static 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)) {
+ if (ST_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);
+ st_internal_unpack_entries(table);
}
}
- hash_val = do_hash(key, table);
+ hash_val = st_do_hash(key, table);
bin_pos = hash_val % table->num_bins;
- ADD_DIRECT(table, key, value, hash_val, bin_pos);
+ ST_ADD_DIRECT(table, key, value, hash_val, bin_pos);
}
static void
-rehash(register st_table *table)
+st_internal_rehash(register st_table *table)
{
register st_table_entry *ptr, **new_bins;
st_index_t i, new_num_bins, hash_val;
- new_num_bins = new_size(table->num_bins+1);
+ new_num_bins = st_internal_new_size(table->num_bins+1);
new_bins = (st_table_entry**)
xrealloc(table->bins, new_num_bins * sizeof(st_table_entry*));
for (i = 0; i < new_num_bins; ++i) new_bins[i] = 0;
@@ -554,7 +551,7 @@
}
}
-st_table*
+static st_table*
st_copy(st_table *old_table)
{
st_table *new_table;
@@ -562,14 +559,14 @@
st_index_t num_bins = old_table->num_bins;
st_index_t hash_val;
- new_table = alloc(st_table);
+ new_table = st_internal_alloc(st_table);
if (new_table == 0) {
return 0;
}
*new_table = *old_table;
new_table->bins = (st_table_entry**)
- Calloc((unsigned)num_bins, sizeof(st_table_entry*));
+ st_internal_calloc((unsigned)num_bins, sizeof(st_table_entry*));
if (new_table->bins == 0) {
free(new_table);
@@ -585,7 +582,7 @@
prev = 0;
tail = &new_table->head;
do {
- entry = alloc(st_table_entry);
+ entry = st_internal_alloc(st_table_entry);
if (entry == 0) {
st_free_table(new_table);
return 0;
@@ -604,7 +601,7 @@
return new_table;
}
-#define REMOVE_ENTRY(table, ptr) do \
+#define ST_REMOVE_ENTRY(table, ptr) do \
{ \
if ((ptr)->fore == 0 && (ptr)->back == 0) { \
(table)->head = 0; \
@@ -620,7 +617,7 @@
(table)->num_entries--; \
} while (0)
-int
+static int
st_delete(register st_table *table, register st_data_t *key, st_data_t *value)
{
st_index_t hash_val;
@@ -642,12 +639,12 @@
return 0;
}
- hash_val = do_hash_bin(*key, table);
+ hash_val = st_do_hash_bin(*key, table);
for (prev = &table->bins[hash_val]; (ptr = *prev) != 0; prev = &ptr->next) {
- if (EQUAL(table, *key, ptr->key)) {
+ if (ST_EQUAL(table, *key, ptr->key)) {
*prev = ptr->next;
- REMOVE_ENTRY(table, ptr);
+ ST_REMOVE_ENTRY(table, ptr);
if (value != 0) *value = ptr->record;
*key = ptr->key;
free(ptr);
@@ -659,7 +656,7 @@
return 0;
}
-int
+static 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;
@@ -670,7 +667,7 @@
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;
+ table->bins[i*2] = (st_table_entry *)never;
return 1;
}
}
@@ -678,12 +675,12 @@
return 0;
}
- hash_val = do_hash_bin(*key, table);
+ hash_val = st_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);
+ if ((ptr->key != never) && ST_EQUAL(table, ptr->key, *key)) {
+ ST_REMOVE_ENTRY(table, ptr);
*key = ptr->key;
if (value != 0) *value = ptr->record;
ptr->key = ptr->record = never;
@@ -695,7 +692,7 @@
return 0;
}
-void
+static void
st_cleanup_safe(st_table *table, st_data_t never)
{
st_table_entry *ptr, **last, *tmp;
@@ -731,7 +728,7 @@
}
}
-int
+static int
st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg)
{
st_table_entry *ptr, **last, *tmp;
@@ -744,7 +741,7 @@
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);
+ retval = (enum st_retval)func(key, val, arg);
if (!table->entries_packed) goto unpacked;
switch (retval) {
case ST_CHECK: /* check if hash is modified during iteration */
@@ -754,7 +751,7 @@
}
if (j == table->num_entries) {
/* call func with error notice */
- retval = (*func)(0, 0, arg, 1);
+ retval = (enum st_retval)func(0, 0, arg, 1);
return 1;
}
/* fall through */
@@ -784,13 +781,13 @@
if (ptr != 0) {
do {
i = ptr->hash % table->num_bins;
- retval = (*func)(ptr->key, ptr->record, arg);
+ retval = (enum st_retval)func(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);
+ retval = (enum st_retval)func(0, 0, arg, 1);
return 1;
}
}
@@ -806,7 +803,7 @@
if (ptr == tmp) {
tmp = ptr->fore;
*last = ptr->next;
- REMOVE_ENTRY(table, ptr);
+ ST_REMOVE_ENTRY(table, ptr);
free(ptr);
if (ptr == tmp) return 0;
ptr = tmp;
@@ -819,88 +816,6 @@
return 0;
}
-#if 0 /* unused right now */
-int
-st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg)
-{
- st_table_entry *ptr, **last, *tmp;
- enum st_retval retval;
- int i;
-
- if (table->entries_packed) {
- for (i = table->num_entries-1; 0 <= i; i--) {
- int 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));
- break;
- }
- }
- return 0;
- }
-
- if ((ptr = table->head) != 0) {
- ptr = ptr->back;
- do {
- retval = (*func)(ptr->key, ptr->record, arg, 0);
- switch (retval) {
- case ST_CHECK: /* check if hash is modified during iteration */
- i = ptr->hash % table->num_bins;
- 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->back;
- 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->back;
- *last = ptr->next;
- REMOVE_ENTRY(table, ptr);
- free(ptr);
- ptr = tmp;
- break;
- }
- }
- ptr = ptr->next;
- free(tmp);
- table->num_entries--;
- }
- } while (ptr && table->head);
- }
- return 0;
-}
-#endif
/*
* hash_32 - 32 bit Fowler/Noll/Vo FNV-1a hash code
@@ -936,7 +851,7 @@
* 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
+ * To use the recommended 32 bit FNV-1a hash, pass ST_FNV1_32A_INIT as the
* Fnv32_t hashval argument to fnv_32a_buf() or fnv_32a_str().
*
***
@@ -970,19 +885,18 @@
*
* NOTE: The FNV-1a initial basis is the same value as FNV-1 by definition.
*/
-#define FNV1_32A_INIT 0x811c9dc5
+#define ST_FNV1_32A_INIT 0x811c9dc5
/*
* 32 bit magic FNV-1a prime
*/
-#define FNV_32_PRIME 0x01000193
+#define ST_FNV_32_PRIME 0x01000193
-#ifdef ST_USE_FNV1
static st_index_t
-strhash(st_data_t arg)
+st_internal_strhash(st_data_t arg)
{
register const char *string = (const char *)arg;
- register st_index_t hval = FNV1_32A_INIT;
+ register st_index_t hval = ST_FNV1_32A_INIT;
/*
* FNV-1a hash each octet in the buffer
@@ -992,267 +906,12 @@
hval ^= (unsigned int)*string++;
/* multiply by the 32 bit FNV magic prime mod 2^32 */
- hval *= FNV_32_PRIME;
+ hval *= ST_FNV_32_PRIME;
}
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
-
-#define MurmurMagic_1 (st_index_t)0xc6a4a793
-#define MurmurMagic_2 (st_index_t)0x5bd1e995
-#if MURMUR == 1
-#define MurmurMagic MurmurMagic_1
-#elif MURMUR == 2
-#if SIZEOF_ST_INDEX_T > 4
-#define MurmurMagic ((MurmurMagic_1 << 32) | MurmurMagic_2)
-#else
-#define MurmurMagic MurmurMagic_2
-#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
-
- 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));
- }
- }
-
- 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)
-#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);
-}
-
-st_index_t
-st_hash_uint32(st_index_t h, uint32_t i)
-{
- return murmur_step(h + i, 16);
-}
-
-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));
-#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
-
-int
+static int
st_strcasecmp(const char *s1, const char *s2)
{
unsigned int c1, c2;
@@ -1276,7 +935,7 @@
}
}
-int
+static int
st_strncasecmp(const char *s1, const char *s2, size_t n)
{
unsigned int c1, c2;
@@ -1302,10 +961,10 @@
}
static st_index_t
-strcasehash(st_data_t arg)
+st_internal_strcasehash(st_data_t arg)
{
register const char *string = (const char *)arg;
- register st_index_t hval = FNV1_32A_INIT;
+ register st_index_t hval = ST_FNV1_32A_INIT;
/*
* FNV-1a hash each octet in the buffer
@@ -1316,19 +975,34 @@
hval ^= c;
/* multiply by the 32 bit FNV magic prime mod 2^32 */
- hval *= FNV_32_PRIME;
+ hval *= ST_FNV_32_PRIME;
}
return hval;
}
-int
+static int
st_numcmp(st_data_t x, st_data_t y)
{
return x != y;
}
-st_index_t
+static st_index_t
st_numhash(st_data_t n)
{
return (st_index_t)n;
}
+
+
+
+#if defined __GNUC__ && __GNUC__ >= 4
+#pragma GCC visibility pop
+#endif
+
+#if defined(__cplusplus)
+#if 0
+{ /* satisfy cc-mode */
+#endif
+} /* extern "C" { */
+#endif
+
+#endif /* RUBY_ST_H */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment