2000-01-04 23:41:21 -05:00
|
|
|
/* This is a public domain general purpose hash table package written by Peter Moore @ UCB. */
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-05-29 01:20:39 -04:00
|
|
|
/* static char sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible"; */
|
1998-01-16 07:13:05 -05:00
|
|
|
|
* ascii.c, euc_jp.c, hash.c, oniggnu.h, oniguruma.h, regcomp.c, regenc.c, regenc.h, regerror.c, regexec.c, reggnu.c, regint.h, regparse.c, regparse.h, sjis.c, st.c, st.h, utf8.c: imported Oni Guruma 3.5.4.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7846 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-01-28 10:21:48 -05:00
|
|
|
#ifdef NOT_RUBY
|
|
|
|
#include "regint.h"
|
|
|
|
#include "st.h"
|
2007-06-09 23:06:15 -04:00
|
|
|
#else
|
2008-09-18 06:44:09 -04:00
|
|
|
#include "ruby/ruby.h"
|
2007-06-09 23:06:15 -04:00
|
|
|
#endif
|
* ascii.c, euc_jp.c, hash.c, oniggnu.h, oniguruma.h, regcomp.c, regenc.c, regenc.h, regerror.c, regexec.c, reggnu.c, regint.h, regparse.c, regparse.h, sjis.c, st.c, st.h, utf8.c: imported Oni Guruma 3.5.4.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7846 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-01-28 10:21:48 -05:00
|
|
|
|
2007-12-13 23:47:57 -05:00
|
|
|
#include <stdio.h>
|
|
|
|
#ifdef HAVE_STDLIB_H
|
|
|
|
#include <stdlib.h>
|
|
|
|
#endif
|
|
|
|
#include <string.h>
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
typedef struct st_table_entry st_table_entry;
|
|
|
|
|
|
|
|
struct st_table_entry {
|
2009-09-22 03:34:35 -04:00
|
|
|
st_index_t hash;
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 10:55:43 -05:00
|
|
|
st_data_t key;
|
|
|
|
st_data_t record;
|
1999-01-19 23:59:39 -05:00
|
|
|
st_table_entry *next;
|
2007-08-21 00:43:51 -04:00
|
|
|
st_table_entry *fore, *back;
|
1999-01-19 23:59:39 -05:00
|
|
|
};
|
|
|
|
|
2012-02-07 05:37:40 -05:00
|
|
|
typedef struct st_packed_entry {
|
2012-03-10 09:52:30 -05:00
|
|
|
st_index_t hash;
|
2012-02-07 05:37:40 -05:00
|
|
|
st_data_t key, val;
|
|
|
|
} st_packed_entry;
|
|
|
|
|
|
|
|
#define STATIC_ASSERT(name, expr) typedef int static_assert_##name##_check[(expr) ? 1 : -1];
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
#define ST_DEFAULT_MAX_DENSITY 5
|
2014-03-22 19:34:21 -04:00
|
|
|
#define ST_DEFAULT_INIT_TABLE_SIZE 16
|
2012-03-10 09:52:30 -05:00
|
|
|
#define ST_DEFAULT_PACKED_TABLE_SIZE 18
|
2012-02-07 05:37:40 -05:00
|
|
|
#define PACKED_UNIT (int)(sizeof(st_packed_entry) / sizeof(st_table_entry*))
|
|
|
|
#define MAX_PACKED_HASH (int)(ST_DEFAULT_PACKED_TABLE_SIZE * sizeof(st_table_entry*) / sizeof(st_packed_entry))
|
|
|
|
|
|
|
|
STATIC_ASSERT(st_packed_entry, sizeof(st_packed_entry) == sizeof(st_table_entry*[PACKED_UNIT]))
|
2012-03-10 09:52:06 -05:00
|
|
|
STATIC_ASSERT(st_packed_bins, sizeof(st_packed_entry[MAX_PACKED_HASH]) <= sizeof(st_table_entry*[ST_DEFAULT_PACKED_TABLE_SIZE]))
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
/*
|
|
|
|
* DEFAULT_MAX_DENSITY is the default for the largest we allow the
|
|
|
|
* average number of items per bin before increasing the number of
|
|
|
|
* bins
|
|
|
|
*
|
|
|
|
* DEFAULT_INIT_TABLE_SIZE is the default for the number of bins
|
|
|
|
* allocated initially
|
|
|
|
*
|
|
|
|
*/
|
* ascii.c, euc_jp.c, hash.c, oniggnu.h, oniguruma.h, regcomp.c, regenc.c, regenc.h, regerror.c, regexec.c, reggnu.c, regint.h, regparse.c, regparse.h, sjis.c, st.c, st.h, utf8.c: imported Oni Guruma 3.5.4.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7846 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-01-28 10:21:48 -05:00
|
|
|
|
2011-10-18 10:28:58 -04:00
|
|
|
#define type_numhash st_hashtype_num
|
|
|
|
const struct st_hash_type st_hashtype_num = {
|
2006-09-11 04:09:19 -04:00
|
|
|
st_numcmp,
|
|
|
|
st_numhash,
|
1998-01-16 07:13:05 -05:00
|
|
|
};
|
|
|
|
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 10:55:43 -05:00
|
|
|
/* extern int strcmp(const char *, const char *); */
|
2009-09-08 09:18:13 -04:00
|
|
|
static st_index_t strhash(st_data_t);
|
2007-07-04 21:06:49 -04:00
|
|
|
static const struct st_hash_type type_strhash = {
|
2003-01-08 23:28:28 -05:00
|
|
|
strcmp,
|
|
|
|
strhash,
|
* ascii.c, euc_jp.c, hash.c, oniggnu.h, oniguruma.h, regcomp.c, regenc.c, regenc.h, regerror.c, regexec.c, reggnu.c, regint.h, regparse.c, regparse.h, sjis.c, st.c, st.h, utf8.c: imported Oni Guruma 3.5.4.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7846 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-01-28 10:21:48 -05:00
|
|
|
};
|
2000-05-15 22:46:57 -04:00
|
|
|
|
2009-09-08 09:18:13 -04:00
|
|
|
static st_index_t strcasehash(st_data_t);
|
2007-09-28 15:27:10 -04:00
|
|
|
static const struct st_hash_type type_strcasehash = {
|
2013-07-16 19:15:41 -04:00
|
|
|
st_locale_insensitive_strcasecmp,
|
2007-09-28 15:27:10 -04:00
|
|
|
strcasehash,
|
|
|
|
};
|
|
|
|
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 10:55:43 -05:00
|
|
|
static void rehash(st_table *);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2006-07-14 12:13:41 -04:00
|
|
|
#ifdef RUBY
|
2014-06-05 01:16:46 -04:00
|
|
|
#undef malloc
|
|
|
|
#undef realloc
|
|
|
|
#undef calloc
|
|
|
|
#undef free
|
2006-07-14 12:13:41 -04:00
|
|
|
#define malloc xmalloc
|
|
|
|
#define calloc xcalloc
|
2012-01-15 10:46:37 -05:00
|
|
|
#define realloc xrealloc
|
* array.c, bignum.c, cont.c, dir.c, dln.c, encoding.c, enumerator.c,
enumerator.c (enumerator_allocate), eval_jump.c, file.c, hash.c,
io.c, load.c, pack.c, proc.c, random.c, re.c, ruby.c, st.c,
string.c, thread.c, thread_pthread.c, time.c, util.c, variable.c,
vm.c, gc.c:
allocated memory objects by xmalloc (ruby_xmalloc) should be
freed by xfree (ruby_xfree).
* ext/curses/curses.c, ext/dbm/dbm.c, ext/digest/digest.c,
ext/gdbm/gdbm.c, ext/json/ext/parser/parser.c,
ext/json/ext/parser/unicode.c, ext/openssl/ossl_cipher.c,
ext/openssl/ossl_hmac.c, ext/openssl/ossl_pkey_ec.c,
ext/sdbm/init.c, ext/strscan/strscan.c, ext/zlib/zlib.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17017 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-06-08 06:01:40 -04:00
|
|
|
#define free(x) xfree(x)
|
2006-07-14 12:13:41 -04:00
|
|
|
#endif
|
|
|
|
|
2010-12-30 20:28:41 -05:00
|
|
|
#define EQUAL(table,x,y) ((x)==(y) || (*(table)->type->compare)((x),(y)) == 0)
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2012-01-16 20:54:50 -05:00
|
|
|
#define do_hash(key,table) (st_index_t)(*(table)->type->hash)((key))
|
2014-03-22 19:34:21 -04:00
|
|
|
#define hash_pos(h,n) ((h) & (n - 1))
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2012-01-15 10:46:37 -05:00
|
|
|
/* preparation for possible allocation improvements */
|
|
|
|
#define st_alloc_entry() (st_table_entry *)malloc(sizeof(st_table_entry))
|
|
|
|
#define st_free_entry(entry) free(entry)
|
|
|
|
#define st_alloc_table() (st_table *)malloc(sizeof(st_table))
|
|
|
|
#define st_dealloc_table(table) free(table)
|
|
|
|
#define st_alloc_bins(size) (st_table_entry **)calloc(size, sizeof(st_table_entry *))
|
|
|
|
#define st_free_bins(bins, size) free(bins)
|
|
|
|
static inline st_table_entry**
|
|
|
|
st_realloc_bins(st_table_entry **bins, st_index_t newsize, st_index_t oldsize)
|
|
|
|
{
|
2012-02-07 05:37:40 -05:00
|
|
|
bins = (st_table_entry **)realloc(bins, newsize * sizeof(st_table_entry *));
|
|
|
|
MEMZERO(bins, st_table_entry*, newsize);
|
2012-01-15 10:46:37 -05:00
|
|
|
return bins;
|
|
|
|
}
|
|
|
|
|
2013-04-19 10:32:29 -04:00
|
|
|
/* Shortcut */
|
2012-03-04 22:44:05 -05:00
|
|
|
#define bins as.big.bins
|
|
|
|
#define head as.big.head
|
|
|
|
#define tail as.big.tail
|
2012-03-10 09:52:06 -05:00
|
|
|
#define real_entries as.packed.real_entries
|
2012-03-04 22:44:05 -05:00
|
|
|
|
2012-01-15 10:46:34 -05:00
|
|
|
/* preparation for possible packing improvements */
|
2012-03-10 09:52:06 -05:00
|
|
|
#define PACKED_BINS(table) ((table)->as.packed.entries)
|
|
|
|
#define PACKED_ENT(table, i) PACKED_BINS(table)[i]
|
2012-02-07 05:37:40 -05:00
|
|
|
#define PKEY(table, i) PACKED_ENT((table), (i)).key
|
|
|
|
#define PVAL(table, i) PACKED_ENT((table), (i)).val
|
2012-03-10 09:52:30 -05:00
|
|
|
#define PHASH(table, i) PACKED_ENT((table), (i)).hash
|
2012-02-07 05:37:40 -05:00
|
|
|
#define PKEY_SET(table, i, v) (PKEY((table), (i)) = (v))
|
|
|
|
#define PVAL_SET(table, i, v) (PVAL((table), (i)) = (v))
|
2012-03-10 09:52:30 -05:00
|
|
|
#define PHASH_SET(table, i, v) (PHASH((table), (i)) = (v))
|
2012-03-04 22:44:05 -05:00
|
|
|
|
2012-01-15 10:46:34 -05:00
|
|
|
/* this function depends much on packed layout, so that it placed here */
|
|
|
|
static inline void
|
|
|
|
remove_packed_entry(st_table *table, st_index_t i)
|
|
|
|
{
|
2012-03-10 09:52:06 -05:00
|
|
|
table->real_entries--;
|
2012-01-15 10:46:34 -05:00
|
|
|
table->num_entries--;
|
2012-03-10 09:52:06 -05:00
|
|
|
if (i < table->real_entries) {
|
2012-02-07 05:37:40 -05:00
|
|
|
MEMMOVE(&PACKED_ENT(table, i), &PACKED_ENT(table, i+1),
|
2012-03-10 09:52:06 -05:00
|
|
|
st_packed_entry, table->real_entries - i);
|
2012-01-15 10:46:34 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-30 18:53:26 -04:00
|
|
|
static inline void
|
|
|
|
remove_safe_packed_entry(st_table *table, st_index_t i, st_data_t never)
|
|
|
|
{
|
|
|
|
table->num_entries--;
|
|
|
|
PKEY_SET(table, i, never);
|
|
|
|
PVAL_SET(table, i, never);
|
|
|
|
PHASH_SET(table, i, 0);
|
|
|
|
}
|
|
|
|
|
2014-10-02 17:17:13 -04:00
|
|
|
static st_index_t
|
|
|
|
next_pow2(st_index_t x)
|
|
|
|
{
|
|
|
|
x |= x >> 1;
|
|
|
|
x |= x >> 2;
|
|
|
|
x |= x >> 4;
|
|
|
|
x |= x >> 8;
|
|
|
|
x |= x >> 16;
|
|
|
|
#if SIZEOF_ST_INDEX_T == 8
|
|
|
|
x |= x >> 32;
|
|
|
|
#endif
|
|
|
|
return x + 1;
|
|
|
|
}
|
|
|
|
|
2009-09-08 09:18:13 -04:00
|
|
|
static st_index_t
|
|
|
|
new_size(st_index_t size)
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
2014-10-02 17:17:13 -04:00
|
|
|
st_index_t n;
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2014-10-02 17:17:13 -04:00
|
|
|
if (size && (size & ~(size - 1)) == size) /* already a power-of-two? */
|
|
|
|
return size;
|
|
|
|
|
|
|
|
n = next_pow2(size);
|
|
|
|
if (n > size)
|
|
|
|
return n;
|
2008-09-18 06:44:09 -04:00
|
|
|
#ifndef NOT_RUBY
|
|
|
|
rb_raise(rb_eRuntimeError, "st_table too big");
|
|
|
|
#endif
|
1999-01-19 23:59:39 -05:00
|
|
|
return -1; /* should raise exception */
|
2000-02-23 00:23:12 -05:00
|
|
|
}
|
|
|
|
|
2000-02-24 22:51:23 -05:00
|
|
|
#ifdef HASH_LOG
|
2009-09-26 04:53:15 -04:00
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
static struct {
|
|
|
|
int all, total, num, str, strcase;
|
|
|
|
} collision;
|
2000-02-23 00:23:12 -05:00
|
|
|
static int init_st = 0;
|
|
|
|
|
|
|
|
static void
|
* cont.c (rb_fiber_current), dln.c (dln_print_undef, dln_undefined),
eval.c (rb_iterator_p, rb_need_block), load.c: (Init_load), ruby.c
(uscore_get, rb_f_chop), st.c (stat_col), signal.c
(rb_signal_buff_size, ruby_sig_finalize), thread.c
(rb_thread_sleep_forever, rb_thread_sleep_deadly, rb_thread_alone):
protoized.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21929 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-02-01 07:51:44 -05:00
|
|
|
stat_col(void)
|
2000-02-23 00:23:12 -05:00
|
|
|
{
|
2009-09-26 04:53:15 -04:00
|
|
|
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);
|
2000-02-23 00:23:12 -05:00
|
|
|
fclose(f);
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2000-02-24 22:51:23 -05:00
|
|
|
#endif
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
st_table*
|
2009-09-08 09:18:13 -04:00
|
|
|
st_init_table_with_size(const struct st_hash_type *type, st_index_t size)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
st_table *tbl;
|
|
|
|
|
2000-02-24 22:51:23 -05:00
|
|
|
#ifdef HASH_LOG
|
2009-09-26 04:53:15 -04:00
|
|
|
# if HASH_LOG+0 < 0
|
|
|
|
{
|
|
|
|
const char *e = getenv("ST_HASH_LOG");
|
|
|
|
if (!e || !*e) init_st = 1;
|
|
|
|
}
|
|
|
|
# endif
|
2000-02-23 00:23:12 -05:00
|
|
|
if (init_st == 0) {
|
|
|
|
init_st = 1;
|
|
|
|
atexit(stat_col);
|
|
|
|
}
|
2000-02-23 00:43:57 -05:00
|
|
|
#endif
|
2000-02-23 00:23:12 -05:00
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2012-01-15 10:46:37 -05:00
|
|
|
tbl = st_alloc_table();
|
1998-01-16 07:13:05 -05:00
|
|
|
tbl->type = type;
|
|
|
|
tbl->num_entries = 0;
|
2012-03-10 09:52:30 -05:00
|
|
|
tbl->entries_packed = size <= MAX_PACKED_HASH;
|
|
|
|
if (tbl->entries_packed) {
|
|
|
|
size = ST_DEFAULT_PACKED_TABLE_SIZE;
|
|
|
|
}
|
|
|
|
else {
|
2014-03-30 21:34:19 -04:00
|
|
|
size = new_size(size); /* round up to power-of-two */
|
2012-03-10 09:52:30 -05:00
|
|
|
}
|
2002-02-28 01:53:33 -05:00
|
|
|
tbl->num_bins = size;
|
2012-01-15 10:46:37 -05:00
|
|
|
tbl->bins = st_alloc_bins(size);
|
2007-08-21 00:43:51 -04:00
|
|
|
tbl->head = 0;
|
2009-02-08 09:34:13 -05:00
|
|
|
tbl->tail = 0;
|
1999-01-19 23:59:39 -05:00
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
return tbl;
|
|
|
|
}
|
|
|
|
|
|
|
|
st_table*
|
2007-07-04 21:06:49 -04:00
|
|
|
st_init_table(const struct st_hash_type *type)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
return st_init_table_with_size(type, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
st_table*
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 10:55:43 -05:00
|
|
|
st_init_numtable(void)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
return st_init_table(&type_numhash);
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
st_table*
|
2009-09-08 09:18:13 -04:00
|
|
|
st_init_numtable_with_size(st_index_t size)
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
|
|
|
return st_init_table_with_size(&type_numhash, size);
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
st_table*
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 10:55:43 -05:00
|
|
|
st_init_strtable(void)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
return st_init_table(&type_strhash);
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
st_table*
|
2009-09-08 09:18:13 -04:00
|
|
|
st_init_strtable_with_size(st_index_t size)
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
|
|
|
return st_init_table_with_size(&type_strhash, size);
|
|
|
|
}
|
|
|
|
|
2007-09-28 15:27:10 -04:00
|
|
|
st_table*
|
|
|
|
st_init_strcasetable(void)
|
|
|
|
{
|
|
|
|
return st_init_table(&type_strcasehash);
|
|
|
|
}
|
|
|
|
|
|
|
|
st_table*
|
2009-09-08 09:18:13 -04:00
|
|
|
st_init_strcasetable_with_size(st_index_t size)
|
2007-09-28 15:27:10 -04:00
|
|
|
{
|
|
|
|
return st_init_table_with_size(&type_strcasehash, size);
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
void
|
2007-08-21 00:43:51 -04:00
|
|
|
st_clear(st_table *table)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
register st_table_entry *ptr, *next;
|
2009-03-12 04:56:31 -04:00
|
|
|
st_index_t i;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2007-08-28 22:36:54 -04:00
|
|
|
if (table->entries_packed) {
|
|
|
|
table->num_entries = 0;
|
2012-03-10 09:52:06 -05:00
|
|
|
table->real_entries = 0;
|
2007-08-28 22:36:54 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-02-07 05:37:40 -05:00
|
|
|
for (i = 0; i < table->num_bins; i++) {
|
1998-01-16 07:13:05 -05:00
|
|
|
ptr = table->bins[i];
|
2007-08-21 00:43:51 -04:00
|
|
|
table->bins[i] = 0;
|
1999-01-19 23:59:39 -05:00
|
|
|
while (ptr != 0) {
|
1998-01-16 07:13:05 -05:00
|
|
|
next = ptr->next;
|
2012-01-15 10:46:37 -05:00
|
|
|
st_free_entry(ptr);
|
1998-01-16 07:13:05 -05:00
|
|
|
ptr = next;
|
|
|
|
}
|
|
|
|
}
|
2007-08-21 02:00:25 -04:00
|
|
|
table->num_entries = 0;
|
2007-08-21 00:43:51 -04:00
|
|
|
table->head = 0;
|
2009-02-08 09:34:13 -05:00
|
|
|
table->tail = 0;
|
2007-08-21 00:43:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
st_free_table(st_table *table)
|
|
|
|
{
|
|
|
|
st_clear(table);
|
2012-01-15 10:46:37 -05:00
|
|
|
st_free_bins(table->bins, table->num_bins);
|
|
|
|
st_dealloc_table(table);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
2009-06-16 18:03:12 -04:00
|
|
|
size_t
|
2009-09-09 00:10:42 -04:00
|
|
|
st_memsize(const st_table *table)
|
2009-06-16 18:03:12 -04:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
#define PTR_NOT_EQUAL(table, ptr, hash_val, key) \
|
2010-12-30 20:28:41 -05:00
|
|
|
((ptr) != 0 && ((ptr)->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key)))
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2000-02-24 22:51:23 -05:00
|
|
|
#ifdef HASH_LOG
|
2009-09-26 04:53:15 -04:00
|
|
|
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)
|
2000-02-24 22:51:23 -05:00
|
|
|
#else
|
|
|
|
#define COLLISION
|
2009-09-26 04:53:15 -04:00
|
|
|
#define FOUND_ENTRY
|
2000-02-24 22:51:23 -05:00
|
|
|
#endif
|
|
|
|
|
2012-02-07 00:29:20 -05:00
|
|
|
#define FIND_ENTRY(table, ptr, hash_val, bin_pos) \
|
2014-01-18 00:47:38 -05:00
|
|
|
((ptr) = find_entry((table), key, (hash_val), ((bin_pos) = hash_pos(hash_val, (table)->num_bins))))
|
2012-02-07 00:29:20 -05:00
|
|
|
|
2012-01-15 10:46:30 -05:00
|
|
|
static st_table_entry *
|
|
|
|
find_entry(st_table *table, st_data_t key, st_index_t hash_val, st_index_t bin_pos)
|
|
|
|
{
|
|
|
|
register st_table_entry *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;
|
|
|
|
}
|
|
|
|
ptr = ptr->next;
|
|
|
|
}
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline st_index_t
|
2014-04-19 23:58:22 -04:00
|
|
|
find_packed_index_from(st_table *table, st_index_t hash_val, st_data_t key, st_index_t i)
|
2012-01-15 10:46:30 -05:00
|
|
|
{
|
2012-03-10 09:52:30 -05:00
|
|
|
while (i < table->real_entries &&
|
|
|
|
(PHASH(table, i) != hash_val || !EQUAL(table, key, PKEY(table, i)))) {
|
|
|
|
i++;
|
|
|
|
}
|
2012-01-15 10:46:30 -05:00
|
|
|
return i;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2014-04-19 23:58:22 -04:00
|
|
|
static inline st_index_t
|
|
|
|
find_packed_index(st_table *table, st_index_t hash_val, st_data_t key)
|
|
|
|
{
|
|
|
|
return find_packed_index_from(table, hash_val, key, 0);
|
|
|
|
}
|
|
|
|
|
2009-09-26 04:53:15 -04:00
|
|
|
#define collision_check 0
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
int
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 06:44:21 -04:00
|
|
|
st_lookup(st_table *table, register st_data_t key, st_data_t *value)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2012-01-15 10:46:30 -05:00
|
|
|
st_index_t hash_val;
|
1998-01-16 07:13:05 -05:00
|
|
|
register st_table_entry *ptr;
|
|
|
|
|
2012-03-10 09:52:30 -05:00
|
|
|
hash_val = do_hash(key, table);
|
|
|
|
|
2007-08-28 22:36:54 -04:00
|
|
|
if (table->entries_packed) {
|
2012-03-10 09:52:30 -05:00
|
|
|
st_index_t i = find_packed_index(table, hash_val, key);
|
2012-03-10 09:52:06 -05:00
|
|
|
if (i < table->real_entries) {
|
2012-01-15 10:46:34 -05:00
|
|
|
if (value != 0) *value = PVAL(table, i);
|
2012-01-15 10:46:30 -05:00
|
|
|
return 1;
|
|
|
|
}
|
2007-08-28 22:36:54 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-01-18 00:47:38 -05:00
|
|
|
ptr = find_entry(table, key, hash_val, hash_pos(hash_val, table->num_bins));
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
if (ptr == 0) {
|
1998-01-16 07:13:05 -05:00
|
|
|
return 0;
|
2001-05-02 00:22:21 -04:00
|
|
|
}
|
|
|
|
else {
|
2012-02-07 05:37:40 -05:00
|
|
|
if (value != 0) *value = ptr->record;
|
1998-01-16 07:13:05 -05:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-24 03:06:16 -05:00
|
|
|
int
|
|
|
|
st_get_key(st_table *table, register st_data_t key, st_data_t *result)
|
|
|
|
{
|
2012-01-15 10:46:30 -05:00
|
|
|
st_index_t hash_val;
|
2007-12-24 03:06:16 -05:00
|
|
|
register st_table_entry *ptr;
|
|
|
|
|
2012-03-10 09:52:30 -05:00
|
|
|
hash_val = do_hash(key, table);
|
|
|
|
|
2007-12-24 03:06:16 -05:00
|
|
|
if (table->entries_packed) {
|
2012-03-10 09:52:30 -05:00
|
|
|
st_index_t i = find_packed_index(table, hash_val, key);
|
2012-03-10 09:52:06 -05:00
|
|
|
if (i < table->real_entries) {
|
2012-01-15 10:46:34 -05:00
|
|
|
if (result != 0) *result = PKEY(table, i);
|
2012-01-15 10:46:30 -05:00
|
|
|
return 1;
|
|
|
|
}
|
2007-12-24 03:06:16 -05:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-01-18 00:47:38 -05:00
|
|
|
ptr = find_entry(table, key, hash_val, hash_pos(hash_val, table->num_bins));
|
2007-12-24 03:06:16 -05:00
|
|
|
|
|
|
|
if (ptr == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (result != 0) *result = ptr->key;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-26 04:53:15 -04:00
|
|
|
#undef collision_check
|
|
|
|
#define collision_check 1
|
|
|
|
|
2012-03-04 22:44:14 -05:00
|
|
|
static inline st_table_entry *
|
|
|
|
new_entry(st_table * table, st_data_t key, st_data_t value,
|
|
|
|
st_index_t hash_val, register st_index_t bin_pos)
|
|
|
|
{
|
|
|
|
register st_table_entry *entry = st_alloc_entry();
|
|
|
|
|
|
|
|
entry->next = table->bins[bin_pos];
|
|
|
|
table->bins[bin_pos] = entry;
|
|
|
|
entry->hash = hash_val;
|
|
|
|
entry->key = key;
|
|
|
|
entry->record = value;
|
|
|
|
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
|
2012-01-15 10:46:44 -05:00
|
|
|
static inline void
|
2012-02-07 00:29:20 -05:00
|
|
|
add_direct(st_table *table, st_data_t key, st_data_t value,
|
|
|
|
st_index_t hash_val, register st_index_t bin_pos)
|
2012-01-15 10:46:30 -05:00
|
|
|
{
|
2012-01-15 10:46:44 -05:00
|
|
|
register st_table_entry *entry;
|
2012-01-15 10:46:30 -05:00
|
|
|
if (table->num_entries > ST_DEFAULT_MAX_DENSITY * table->num_bins) {
|
|
|
|
rehash(table);
|
2014-01-18 00:47:38 -05:00
|
|
|
bin_pos = hash_pos(hash_val, table->num_bins);
|
2012-01-15 10:46:30 -05:00
|
|
|
}
|
|
|
|
|
2012-03-04 22:44:14 -05:00
|
|
|
entry = new_entry(table, key, value, hash_val, bin_pos);
|
2012-01-15 10:46:30 -05:00
|
|
|
|
|
|
|
if (table->head != 0) {
|
|
|
|
entry->fore = 0;
|
|
|
|
(entry->back = table->tail)->fore = entry;
|
|
|
|
table->tail = entry;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
table->head = table->tail = entry;
|
|
|
|
entry->fore = entry->back = 0;
|
|
|
|
}
|
|
|
|
table->num_entries++;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2007-08-28 22:36:54 -04:00
|
|
|
static void
|
|
|
|
unpack_entries(register st_table *table)
|
|
|
|
{
|
2009-10-30 21:17:27 -04:00
|
|
|
st_index_t i;
|
2012-03-10 09:52:06 -05:00
|
|
|
st_packed_entry packed_bins[MAX_PACKED_HASH];
|
2012-03-04 22:44:14 -05:00
|
|
|
register st_table_entry *entry, *preventry = 0, **chain;
|
2009-10-16 11:12:31 -04:00
|
|
|
st_table tmp_table = *table;
|
|
|
|
|
2012-03-10 09:52:06 -05:00
|
|
|
MEMCPY(packed_bins, PACKED_BINS(table), st_packed_entry, MAX_PACKED_HASH);
|
|
|
|
table->as.packed.entries = packed_bins;
|
2009-10-16 11:12:31 -04:00
|
|
|
tmp_table.entries_packed = 0;
|
2012-03-04 22:43:45 -05:00
|
|
|
#if ST_DEFAULT_INIT_TABLE_SIZE == ST_DEFAULT_PACKED_TABLE_SIZE
|
2012-02-07 05:37:40 -05:00
|
|
|
MEMZERO(tmp_table.bins, st_table_entry*, tmp_table.num_bins);
|
2012-03-04 22:43:45 -05:00
|
|
|
#else
|
|
|
|
tmp_table.bins = st_realloc_bins(tmp_table.bins, ST_DEFAULT_INIT_TABLE_SIZE, tmp_table.num_bins);
|
|
|
|
tmp_table.num_bins = ST_DEFAULT_INIT_TABLE_SIZE;
|
|
|
|
#endif
|
2012-03-04 22:44:14 -05:00
|
|
|
i = 0;
|
|
|
|
chain = &tmp_table.head;
|
|
|
|
do {
|
2012-03-10 09:52:06 -05:00
|
|
|
st_data_t key = packed_bins[i].key;
|
|
|
|
st_data_t val = packed_bins[i].val;
|
2012-03-10 09:52:30 -05:00
|
|
|
st_index_t hash = packed_bins[i].hash;
|
2012-03-04 22:44:14 -05:00
|
|
|
entry = new_entry(&tmp_table, key, val, hash,
|
2014-01-18 00:47:38 -05:00
|
|
|
hash_pos(hash, ST_DEFAULT_INIT_TABLE_SIZE));
|
2012-03-04 22:44:14 -05:00
|
|
|
*chain = entry;
|
|
|
|
entry->back = preventry;
|
|
|
|
preventry = entry;
|
|
|
|
chain = &entry->fore;
|
|
|
|
} while (++i < MAX_PACKED_HASH);
|
|
|
|
*chain = NULL;
|
|
|
|
tmp_table.tail = entry;
|
2009-10-16 11:12:31 -04:00
|
|
|
*table = tmp_table;
|
2007-08-28 22:36:54 -04:00
|
|
|
}
|
|
|
|
|
2012-01-15 10:46:41 -05:00
|
|
|
static void
|
2012-03-10 09:52:30 -05:00
|
|
|
add_packed_direct(st_table *table, st_data_t key, st_data_t value, st_index_t hash_val)
|
2012-01-15 10:46:30 -05:00
|
|
|
{
|
2012-03-10 09:52:06 -05:00
|
|
|
if (table->real_entries < MAX_PACKED_HASH) {
|
|
|
|
st_index_t i = table->real_entries++;
|
2012-01-15 10:46:34 -05:00
|
|
|
PKEY_SET(table, i, key);
|
|
|
|
PVAL_SET(table, i, value);
|
2012-03-10 09:52:30 -05:00
|
|
|
PHASH_SET(table, i, hash_val);
|
2012-03-10 09:52:06 -05:00
|
|
|
table->num_entries++;
|
2012-01-15 10:46:30 -05:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
unpack_entries(table);
|
2014-01-18 00:47:38 -05:00
|
|
|
add_direct(table, key, value, hash_val, hash_pos(hash_val, table->num_bins));
|
2012-01-15 10:46:30 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
int
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 06:44:21 -04:00
|
|
|
st_insert(register st_table *table, register st_data_t key, st_data_t value)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2012-01-15 10:46:44 -05:00
|
|
|
st_index_t hash_val;
|
|
|
|
register st_index_t bin_pos;
|
1998-01-16 07:13:05 -05:00
|
|
|
register st_table_entry *ptr;
|
|
|
|
|
2012-03-10 09:52:30 -05:00
|
|
|
hash_val = do_hash(key, table);
|
|
|
|
|
2007-08-28 22:36:54 -04:00
|
|
|
if (table->entries_packed) {
|
2012-03-10 09:52:30 -05:00
|
|
|
st_index_t i = find_packed_index(table, hash_val, key);
|
2012-03-10 09:52:06 -05:00
|
|
|
if (i < table->real_entries) {
|
2012-01-15 10:46:34 -05:00
|
|
|
PVAL_SET(table, i, value);
|
2012-01-15 10:46:30 -05:00
|
|
|
return 1;
|
2007-08-28 22:36:54 -04:00
|
|
|
}
|
2012-03-10 09:52:30 -05:00
|
|
|
add_packed_direct(table, key, value, hash_val);
|
2012-01-15 10:46:41 -05:00
|
|
|
return 0;
|
2007-08-28 22:36:54 -04:00
|
|
|
}
|
|
|
|
|
2012-03-04 22:43:55 -05:00
|
|
|
FIND_ENTRY(table, ptr, hash_val, bin_pos);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
if (ptr == 0) {
|
2012-01-15 10:46:30 -05:00
|
|
|
add_direct(table, key, value, hash_val, bin_pos);
|
1998-01-16 07:13:05 -05:00
|
|
|
return 0;
|
2001-05-02 00:22:21 -04:00
|
|
|
}
|
|
|
|
else {
|
1998-01-16 07:13:05 -05:00
|
|
|
ptr->record = value;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-27 11:56:14 -04:00
|
|
|
int
|
|
|
|
st_insert2(register st_table *table, register st_data_t key, st_data_t value,
|
|
|
|
st_data_t (*func)(st_data_t))
|
|
|
|
{
|
2012-01-15 10:46:44 -05:00
|
|
|
st_index_t hash_val;
|
|
|
|
register st_index_t bin_pos;
|
2009-05-27 11:56:14 -04:00
|
|
|
register st_table_entry *ptr;
|
|
|
|
|
2012-03-10 09:52:30 -05:00
|
|
|
hash_val = do_hash(key, table);
|
|
|
|
|
2009-05-27 11:56:14 -04:00
|
|
|
if (table->entries_packed) {
|
2012-03-10 09:52:30 -05:00
|
|
|
st_index_t i = find_packed_index(table, hash_val, key);
|
2012-03-10 09:52:06 -05:00
|
|
|
if (i < table->real_entries) {
|
2012-01-15 10:46:34 -05:00
|
|
|
PVAL_SET(table, i, value);
|
2012-01-15 10:46:30 -05:00
|
|
|
return 1;
|
2012-03-10 09:52:30 -05:00
|
|
|
}
|
|
|
|
key = (*func)(key);
|
|
|
|
add_packed_direct(table, key, value, hash_val);
|
2012-01-15 10:46:41 -05:00
|
|
|
return 0;
|
2009-05-27 11:56:14 -04:00
|
|
|
}
|
|
|
|
|
2012-03-04 22:43:55 -05:00
|
|
|
FIND_ENTRY(table, ptr, hash_val, bin_pos);
|
2009-05-27 11:56:14 -04:00
|
|
|
|
|
|
|
if (ptr == 0) {
|
|
|
|
key = (*func)(key);
|
2012-01-15 10:46:30 -05:00
|
|
|
add_direct(table, key, value, hash_val, bin_pos);
|
2009-05-27 11:56:14 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ptr->record = value;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
void
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 06:44:21 -04:00
|
|
|
st_add_direct(st_table *table, st_data_t key, st_data_t value)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2012-01-15 10:46:44 -05:00
|
|
|
st_index_t hash_val;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2012-03-10 09:52:30 -05:00
|
|
|
hash_val = do_hash(key, table);
|
2007-08-28 22:36:54 -04:00
|
|
|
if (table->entries_packed) {
|
2012-03-10 09:52:30 -05:00
|
|
|
add_packed_direct(table, key, value, hash_val);
|
2012-01-15 10:46:41 -05:00
|
|
|
return;
|
2007-08-28 22:36:54 -04:00
|
|
|
}
|
|
|
|
|
2014-01-18 00:47:38 -05:00
|
|
|
add_direct(table, key, value, hash_val, hash_pos(hash_val, table->num_bins));
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 06:44:21 -04:00
|
|
|
rehash(register st_table *table)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2007-08-21 00:51:54 -04:00
|
|
|
register st_table_entry *ptr, **new_bins;
|
2012-01-15 10:46:37 -05:00
|
|
|
st_index_t new_num_bins, hash_val;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2007-08-21 00:43:51 -04:00
|
|
|
new_num_bins = new_size(table->num_bins+1);
|
2012-01-15 10:46:37 -05:00
|
|
|
new_bins = st_realloc_bins(table->bins, new_num_bins, table->num_bins);
|
2007-08-21 00:43:51 -04:00
|
|
|
table->num_bins = new_num_bins;
|
|
|
|
table->bins = new_bins;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2007-08-21 00:51:54 -04:00
|
|
|
if ((ptr = table->head) != 0) {
|
2007-08-21 00:43:51 -04:00
|
|
|
do {
|
2014-01-18 00:47:38 -05:00
|
|
|
hash_val = hash_pos(ptr->hash, new_num_bins);
|
1999-01-19 23:59:39 -05:00
|
|
|
ptr->next = new_bins[hash_val];
|
|
|
|
new_bins[hash_val] = ptr;
|
2009-02-08 09:34:13 -05:00
|
|
|
} while ((ptr = ptr->fore) != 0);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
st_table*
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 06:44:21 -04:00
|
|
|
st_copy(st_table *old_table)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
st_table *new_table;
|
2012-03-04 22:44:05 -05:00
|
|
|
st_table_entry *ptr, *entry, *prev, **tailp;
|
2009-09-08 09:18:13 -04:00
|
|
|
st_index_t num_bins = old_table->num_bins;
|
|
|
|
st_index_t hash_val;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2012-01-15 10:46:37 -05:00
|
|
|
new_table = st_alloc_table();
|
1999-01-19 23:59:39 -05:00
|
|
|
if (new_table == 0) {
|
|
|
|
return 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
*new_table = *old_table;
|
2012-01-15 10:46:37 -05:00
|
|
|
new_table->bins = st_alloc_bins(num_bins);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
if (new_table->bins == 0) {
|
2012-01-15 10:46:37 -05:00
|
|
|
st_dealloc_table(new_table);
|
1999-01-19 23:59:39 -05:00
|
|
|
return 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
2007-08-28 22:36:54 -04:00
|
|
|
if (old_table->entries_packed) {
|
2012-02-07 05:37:40 -05:00
|
|
|
MEMCPY(new_table->bins, old_table->bins, st_table_entry*, old_table->num_bins);
|
2007-08-28 22:36:54 -04:00
|
|
|
return new_table;
|
|
|
|
}
|
|
|
|
|
2007-08-21 00:43:51 -04:00
|
|
|
if ((ptr = old_table->head) != 0) {
|
|
|
|
prev = 0;
|
2012-03-04 22:44:05 -05:00
|
|
|
tailp = &new_table->head;
|
2007-08-21 00:43:51 -04:00
|
|
|
do {
|
2012-01-15 10:46:37 -05:00
|
|
|
entry = st_alloc_entry();
|
1999-08-13 01:45:20 -04:00
|
|
|
if (entry == 0) {
|
2007-08-21 00:43:51 -04:00
|
|
|
st_free_table(new_table);
|
1999-01-19 23:59:39 -05:00
|
|
|
return 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-08-13 01:45:20 -04:00
|
|
|
*entry = *ptr;
|
2014-01-18 00:47:38 -05:00
|
|
|
hash_val = hash_pos(entry->hash, num_bins);
|
2007-08-21 00:43:51 -04:00
|
|
|
entry->next = new_table->bins[hash_val];
|
|
|
|
new_table->bins[hash_val] = entry;
|
|
|
|
entry->back = prev;
|
2012-03-04 22:44:05 -05:00
|
|
|
*tailp = prev = entry;
|
|
|
|
tailp = &entry->fore;
|
2009-02-08 09:34:13 -05:00
|
|
|
} while ((ptr = ptr->fore) != 0);
|
|
|
|
new_table->tail = prev;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2007-08-21 00:43:51 -04:00
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
return new_table;
|
|
|
|
}
|
|
|
|
|
2012-01-15 10:46:30 -05:00
|
|
|
static inline void
|
|
|
|
remove_entry(st_table *table, st_table_entry *ptr)
|
|
|
|
{
|
|
|
|
if (ptr->fore == 0 && ptr->back == 0) {
|
|
|
|
table->head = 0;
|
|
|
|
table->tail = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
st_table_entry *fore = ptr->fore, *back = ptr->back;
|
|
|
|
if (fore) fore->back = back;
|
|
|
|
if (back) back->fore = fore;
|
|
|
|
if (ptr == table->head) table->head = fore;
|
|
|
|
if (ptr == table->tail) table->tail = back;
|
|
|
|
}
|
|
|
|
table->num_entries--;
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
int
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 06:44:21 -04:00
|
|
|
st_delete(register st_table *table, register st_data_t *key, st_data_t *value)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2009-09-08 09:18:13 -04:00
|
|
|
st_index_t hash_val;
|
2007-08-21 00:43:51 -04:00
|
|
|
st_table_entry **prev;
|
1998-01-16 07:13:05 -05:00
|
|
|
register st_table_entry *ptr;
|
|
|
|
|
2012-03-10 09:52:30 -05:00
|
|
|
hash_val = do_hash(*key, table);
|
|
|
|
|
2007-08-28 22:36:54 -04:00
|
|
|
if (table->entries_packed) {
|
2012-03-10 09:52:30 -05:00
|
|
|
st_index_t i = find_packed_index(table, hash_val, *key);
|
2012-03-30 21:01:41 -04:00
|
|
|
if (i < table->real_entries) {
|
2012-01-15 10:46:34 -05:00
|
|
|
if (value != 0) *value = PVAL(table, i);
|
2012-03-10 09:52:30 -05:00
|
|
|
*key = PKEY(table, i);
|
2012-01-15 10:46:30 -05:00
|
|
|
remove_packed_entry(table, i);
|
|
|
|
return 1;
|
2007-08-28 22:36:54 -04:00
|
|
|
}
|
|
|
|
if (value != 0) *value = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-01-18 00:47:38 -05:00
|
|
|
prev = &table->bins[hash_pos(hash_val, table->num_bins)];
|
2012-03-10 09:52:30 -05:00
|
|
|
for (;(ptr = *prev) != 0; prev = &ptr->next) {
|
2007-08-21 00:43:51 -04:00
|
|
|
if (EQUAL(table, *key, ptr->key)) {
|
|
|
|
*prev = ptr->next;
|
2012-01-15 10:46:30 -05:00
|
|
|
remove_entry(table, ptr);
|
2007-08-21 00:43:51 -04:00
|
|
|
if (value != 0) *value = ptr->record;
|
|
|
|
*key = ptr->key;
|
2012-01-15 10:46:37 -05:00
|
|
|
st_free_entry(ptr);
|
1998-01-16 07:13:05 -05:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-08-21 00:43:51 -04:00
|
|
|
if (value != 0) *value = 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 06:44:21 -04:00
|
|
|
st_delete_safe(register st_table *table, register st_data_t *key, st_data_t *value, st_data_t never)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2009-09-08 09:18:13 -04:00
|
|
|
st_index_t hash_val;
|
1998-01-16 07:13:05 -05:00
|
|
|
register st_table_entry *ptr;
|
|
|
|
|
2012-03-10 09:52:30 -05:00
|
|
|
hash_val = do_hash(*key, table);
|
|
|
|
|
2009-08-24 03:36:02 -04:00
|
|
|
if (table->entries_packed) {
|
2012-03-10 09:52:30 -05:00
|
|
|
st_index_t i = find_packed_index(table, hash_val, *key);
|
2012-03-10 09:52:06 -05:00
|
|
|
if (i < table->real_entries) {
|
2012-01-15 10:46:34 -05:00
|
|
|
if (value != 0) *value = PVAL(table, i);
|
2012-03-10 09:52:30 -05:00
|
|
|
*key = PKEY(table, i);
|
2012-03-30 18:53:26 -04:00
|
|
|
remove_safe_packed_entry(table, i, never);
|
2012-01-15 10:46:30 -05:00
|
|
|
return 1;
|
2009-08-24 03:36:02 -04:00
|
|
|
}
|
|
|
|
if (value != 0) *value = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-01-18 00:47:38 -05:00
|
|
|
ptr = table->bins[hash_pos(hash_val, table->num_bins)];
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2007-08-21 00:43:51 -04:00
|
|
|
for (; ptr != 0; ptr = ptr->next) {
|
2000-03-23 03:37:35 -05:00
|
|
|
if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) {
|
2012-01-15 10:46:30 -05:00
|
|
|
remove_entry(table, ptr);
|
1998-01-16 07:13:05 -05:00
|
|
|
*key = ptr->key;
|
1999-01-19 23:59:39 -05:00
|
|
|
if (value != 0) *value = ptr->record;
|
1998-01-16 07:13:05 -05:00
|
|
|
ptr->key = ptr->record = never;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-08-21 00:43:51 -04:00
|
|
|
if (value != 0) *value = 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-04-25 01:03:30 -04:00
|
|
|
int
|
|
|
|
st_shift(register st_table *table, register st_data_t *key, st_data_t *value)
|
|
|
|
{
|
|
|
|
st_table_entry **prev;
|
|
|
|
register st_table_entry *ptr;
|
|
|
|
|
|
|
|
if (table->num_entries == 0) {
|
|
|
|
if (value != 0) *value = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (table->entries_packed) {
|
|
|
|
if (value != 0) *value = PVAL(table, 0);
|
|
|
|
*key = PKEY(table, 0);
|
|
|
|
remove_packed_entry(table, 0);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-01-18 00:47:38 -05:00
|
|
|
prev = &table->bins[hash_pos(table->head->hash, table->num_bins)];
|
2013-04-25 01:03:30 -04:00
|
|
|
while ((ptr = *prev) != table->head) prev = &ptr->next;
|
|
|
|
*prev = ptr->next;
|
|
|
|
if (value != 0) *value = ptr->record;
|
|
|
|
*key = ptr->key;
|
|
|
|
remove_entry(table, ptr);
|
|
|
|
st_free_entry(ptr);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1999-08-13 01:45:20 -04:00
|
|
|
void
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 06:44:21 -04:00
|
|
|
st_cleanup_safe(st_table *table, st_data_t never)
|
1999-08-13 01:45:20 -04:00
|
|
|
{
|
2007-08-21 00:43:51 -04:00
|
|
|
st_table_entry *ptr, **last, *tmp;
|
2009-03-12 04:56:31 -04:00
|
|
|
st_index_t i;
|
1999-08-13 01:45:20 -04:00
|
|
|
|
2009-08-24 03:36:02 -04:00
|
|
|
if (table->entries_packed) {
|
|
|
|
st_index_t i = 0, j = 0;
|
2012-01-15 10:46:34 -05:00
|
|
|
while (PKEY(table, i) != never) {
|
2012-03-10 09:52:06 -05:00
|
|
|
if (i++ == table->real_entries) return;
|
2009-08-24 03:36:02 -04:00
|
|
|
}
|
2012-03-10 09:52:06 -05:00
|
|
|
for (j = i; ++i < table->real_entries;) {
|
2012-01-15 10:46:34 -05:00
|
|
|
if (PKEY(table, i) == never) continue;
|
2012-03-04 22:43:55 -05:00
|
|
|
PACKED_ENT(table, j) = PACKED_ENT(table, i);
|
2009-08-24 03:36:02 -04:00
|
|
|
j++;
|
|
|
|
}
|
2012-03-10 09:52:06 -05:00
|
|
|
table->real_entries = j;
|
|
|
|
/* table->num_entries really should be equal j at this moment, but let set it anyway */
|
2009-08-24 03:36:02 -04:00
|
|
|
table->num_entries = j;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-08-21 00:43:51 -04:00
|
|
|
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;
|
2012-01-15 10:46:37 -05:00
|
|
|
st_free_entry(tmp);
|
2007-08-21 00:43:51 -04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
ptr = *(last = &ptr->next);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-08-13 01:45:20 -04:00
|
|
|
}
|
|
|
|
|
2011-12-27 08:04:30 -05:00
|
|
|
int
|
2012-03-29 03:36:12 -04:00
|
|
|
st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data_t arg)
|
2011-12-27 08:04:30 -05:00
|
|
|
{
|
|
|
|
st_index_t hash_val, bin_pos;
|
|
|
|
register st_table_entry *ptr, **last, *tmp;
|
2014-07-06 11:22:19 -04:00
|
|
|
st_data_t value = 0, old_key;
|
2012-03-29 03:36:12 -04:00
|
|
|
int retval, existing = 0;
|
2011-12-27 08:04:30 -05:00
|
|
|
|
2012-03-10 09:52:30 -05:00
|
|
|
hash_val = do_hash(key, table);
|
|
|
|
|
2011-12-27 08:04:30 -05:00
|
|
|
if (table->entries_packed) {
|
2012-03-10 09:52:30 -05:00
|
|
|
st_index_t i = find_packed_index(table, hash_val, key);
|
2012-03-10 09:52:06 -05:00
|
|
|
if (i < table->real_entries) {
|
2012-11-16 21:46:13 -05:00
|
|
|
key = PKEY(table, i);
|
2012-01-15 10:46:34 -05:00
|
|
|
value = PVAL(table, i);
|
2012-03-29 03:36:12 -04:00
|
|
|
existing = 1;
|
|
|
|
}
|
|
|
|
{
|
2014-07-06 11:22:19 -04:00
|
|
|
old_key = key;
|
2012-03-29 10:50:20 -04:00
|
|
|
retval = (*func)(&key, &value, arg, existing);
|
2012-02-07 00:52:15 -05:00
|
|
|
if (!table->entries_packed) {
|
2012-03-04 22:43:55 -05:00
|
|
|
FIND_ENTRY(table, ptr, hash_val, bin_pos);
|
2012-02-07 00:52:15 -05:00
|
|
|
goto unpacked;
|
|
|
|
}
|
|
|
|
switch (retval) {
|
2012-01-15 10:46:30 -05:00
|
|
|
case ST_CONTINUE:
|
2012-03-29 03:36:12 -04:00
|
|
|
if (!existing) {
|
|
|
|
add_packed_direct(table, key, value, hash_val);
|
|
|
|
break;
|
|
|
|
}
|
2014-07-06 10:19:47 -04:00
|
|
|
if (old_key != key) {
|
|
|
|
PKEY(table, i) = key;
|
|
|
|
}
|
2012-01-15 10:46:34 -05:00
|
|
|
PVAL_SET(table, i, value);
|
2012-01-15 10:46:30 -05:00
|
|
|
break;
|
|
|
|
case ST_DELETE:
|
2012-03-29 03:36:12 -04:00
|
|
|
if (!existing) break;
|
2012-01-15 10:46:30 -05:00
|
|
|
remove_packed_entry(table, i);
|
2011-12-27 08:04:30 -05:00
|
|
|
}
|
|
|
|
}
|
2012-03-29 03:36:12 -04:00
|
|
|
return existing;
|
2011-12-27 08:04:30 -05:00
|
|
|
}
|
|
|
|
|
2012-03-04 22:43:55 -05:00
|
|
|
FIND_ENTRY(table, ptr, hash_val, bin_pos);
|
2011-12-27 08:04:30 -05:00
|
|
|
|
2012-03-29 03:36:12 -04:00
|
|
|
if (ptr != 0) {
|
2012-11-16 21:46:13 -05:00
|
|
|
key = ptr->key;
|
2011-12-27 08:04:30 -05:00
|
|
|
value = ptr->record;
|
2012-03-29 03:36:12 -04:00
|
|
|
existing = 1;
|
|
|
|
}
|
|
|
|
{
|
2014-07-06 11:22:19 -04:00
|
|
|
old_key = key;
|
2012-03-29 10:50:20 -04:00
|
|
|
retval = (*func)(&key, &value, arg, existing);
|
2012-02-07 00:52:15 -05:00
|
|
|
unpacked:
|
|
|
|
switch (retval) {
|
2011-12-27 08:04:30 -05:00
|
|
|
case ST_CONTINUE:
|
2012-03-29 03:36:12 -04:00
|
|
|
if (!existing) {
|
2014-01-18 00:47:38 -05:00
|
|
|
add_direct(table, key, value, hash_val, hash_pos(hash_val, table->num_bins));
|
2012-03-29 03:36:12 -04:00
|
|
|
break;
|
|
|
|
}
|
2014-07-06 10:19:47 -04:00
|
|
|
if (old_key != key) {
|
|
|
|
ptr->key = key;
|
|
|
|
}
|
2011-12-27 08:04:30 -05:00
|
|
|
ptr->record = value;
|
|
|
|
break;
|
|
|
|
case ST_DELETE:
|
2012-03-29 03:36:12 -04:00
|
|
|
if (!existing) break;
|
2011-12-27 08:04:30 -05:00
|
|
|
last = &table->bins[bin_pos];
|
|
|
|
for (; (tmp = *last) != 0; last = &tmp->next) {
|
|
|
|
if (ptr == tmp) {
|
|
|
|
*last = ptr->next;
|
2012-01-15 10:46:30 -05:00
|
|
|
remove_entry(table, ptr);
|
2012-01-15 10:46:37 -05:00
|
|
|
st_free_entry(ptr);
|
2011-12-27 08:04:30 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2012-03-29 03:36:12 -04:00
|
|
|
return existing;
|
2011-12-27 08:04:30 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 01:47:45 -05:00
|
|
|
int
|
2012-03-10 09:52:19 -05:00
|
|
|
st_foreach_check(st_table *table, int (*func)(ANYARGS), st_data_t arg, st_data_t never)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2007-08-21 00:43:51 -04:00
|
|
|
st_table_entry *ptr, **last, *tmp;
|
1998-01-16 07:13:05 -05:00
|
|
|
enum st_retval retval;
|
2009-03-12 04:56:31 -04:00
|
|
|
st_index_t i;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2007-08-28 22:36:54 -04:00
|
|
|
if (table->entries_packed) {
|
2012-03-10 09:52:19 -05:00
|
|
|
for (i = 0; i < table->real_entries; i++) {
|
|
|
|
st_data_t key, val;
|
2012-03-10 09:52:30 -05:00
|
|
|
st_index_t hash;
|
2012-03-10 09:52:19 -05:00
|
|
|
key = PKEY(table, i);
|
|
|
|
val = PVAL(table, i);
|
2012-03-10 09:52:30 -05:00
|
|
|
hash = PHASH(table, i);
|
2012-03-10 09:52:19 -05:00
|
|
|
if (key == never) continue;
|
2013-11-13 21:33:50 -05:00
|
|
|
retval = (*func)(key, val, arg, 0);
|
2012-02-07 00:29:20 -05:00
|
|
|
if (!table->entries_packed) {
|
2012-03-10 09:52:30 -05:00
|
|
|
FIND_ENTRY(table, ptr, hash, i);
|
2012-02-07 00:29:20 -05:00
|
|
|
if (retval == ST_CHECK) {
|
|
|
|
if (!ptr) goto deleted;
|
|
|
|
goto unpacked_continue;
|
|
|
|
}
|
|
|
|
goto unpacked;
|
|
|
|
}
|
2012-03-10 09:52:19 -05:00
|
|
|
switch (retval) {
|
2007-08-28 22:36:54 -04:00
|
|
|
case ST_CHECK: /* check if hash is modified during iteration */
|
2012-03-10 09:52:30 -05:00
|
|
|
if (PHASH(table, i) == 0 && PKEY(table, i) == never) {
|
2012-03-10 09:52:19 -05:00
|
|
|
break;
|
|
|
|
}
|
2014-04-19 23:58:22 -04:00
|
|
|
i = find_packed_index_from(table, hash, key, i);
|
|
|
|
if (i >= table->real_entries) {
|
|
|
|
i = find_packed_index(table, hash, key);
|
|
|
|
if (i >= table->real_entries) goto deleted;
|
2012-03-10 09:52:06 -05:00
|
|
|
}
|
2007-08-28 22:36:54 -04:00
|
|
|
/* fall through */
|
|
|
|
case ST_CONTINUE:
|
|
|
|
break;
|
|
|
|
case ST_STOP:
|
|
|
|
return 0;
|
|
|
|
case ST_DELETE:
|
2012-03-30 18:53:26 -04:00
|
|
|
remove_safe_packed_entry(table, i, never);
|
2012-03-10 09:52:19 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
2011-01-27 09:30:00 -05:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
ptr = table->head;
|
2007-08-28 22:36:54 -04:00
|
|
|
}
|
|
|
|
|
2011-01-27 09:30:00 -05:00
|
|
|
if (ptr != 0) {
|
2007-08-21 00:43:51 -04:00
|
|
|
do {
|
2012-03-10 09:52:19 -05:00
|
|
|
if (ptr->key == never)
|
|
|
|
goto unpacked_continue;
|
2014-01-18 00:47:38 -05:00
|
|
|
i = hash_pos(ptr->hash, table->num_bins);
|
2013-11-13 21:33:50 -05:00
|
|
|
retval = (*func)(ptr->key, ptr->record, arg, 0);
|
2012-02-07 00:29:20 -05:00
|
|
|
unpacked:
|
1998-01-16 07:13:05 -05:00
|
|
|
switch (retval) {
|
2007-08-21 00:43:51 -04:00
|
|
|
case ST_CHECK: /* check if hash is modified during iteration */
|
|
|
|
for (tmp = table->bins[i]; tmp != ptr; tmp = tmp->next) {
|
|
|
|
if (!tmp) {
|
2012-02-07 00:29:20 -05:00
|
|
|
deleted:
|
2007-08-21 00:43:51 -04:00
|
|
|
/* call func with error notice */
|
|
|
|
retval = (*func)(0, 0, arg, 1);
|
|
|
|
return 1;
|
2004-09-22 00:48:52 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* fall through */
|
2007-08-21 00:43:51 -04:00
|
|
|
case ST_CONTINUE:
|
2012-02-07 00:29:20 -05:00
|
|
|
unpacked_continue:
|
2007-08-21 00:43:51 -04:00
|
|
|
ptr = ptr->fore;
|
1998-01-16 07:13:05 -05:00
|
|
|
break;
|
2007-08-21 00:43:51 -04:00
|
|
|
case ST_STOP:
|
|
|
|
return 0;
|
|
|
|
case ST_DELETE:
|
2014-01-18 00:47:38 -05:00
|
|
|
last = &table->bins[hash_pos(ptr->hash, table->num_bins)];
|
2007-08-21 00:43:51 -04:00
|
|
|
for (; (tmp = *last) != 0; last = &tmp->next) {
|
|
|
|
if (ptr == tmp) {
|
|
|
|
tmp = ptr->fore;
|
2012-01-15 10:46:30 -05:00
|
|
|
remove_entry(table, ptr);
|
2012-03-30 18:53:26 -04:00
|
|
|
ptr->key = ptr->record = never;
|
|
|
|
ptr->hash = 0;
|
2007-08-21 00:43:51 -04:00
|
|
|
ptr = tmp;
|
|
|
|
break;
|
2012-03-10 09:52:19 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (ptr && table->head);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
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->real_entries; i++) {
|
2014-03-04 06:51:53 -05:00
|
|
|
st_data_t key, val;
|
|
|
|
st_index_t hash;
|
2012-03-10 09:52:19 -05:00
|
|
|
key = PKEY(table, i);
|
|
|
|
val = PVAL(table, i);
|
2012-03-10 09:52:30 -05:00
|
|
|
hash = PHASH(table, i);
|
2013-11-13 21:33:50 -05:00
|
|
|
retval = (*func)(key, val, arg, 0);
|
2012-03-10 09:52:19 -05:00
|
|
|
if (!table->entries_packed) {
|
2012-03-10 09:52:30 -05:00
|
|
|
FIND_ENTRY(table, ptr, hash, i);
|
2012-03-10 09:52:19 -05:00
|
|
|
if (!ptr) return 0;
|
|
|
|
goto unpacked;
|
|
|
|
}
|
|
|
|
switch (retval) {
|
|
|
|
case ST_CONTINUE:
|
|
|
|
break;
|
|
|
|
case ST_CHECK:
|
|
|
|
case ST_STOP:
|
|
|
|
return 0;
|
|
|
|
case ST_DELETE:
|
|
|
|
remove_packed_entry(table, i);
|
|
|
|
i--;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ptr = table->head;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ptr != 0) {
|
|
|
|
do {
|
2014-01-18 00:47:38 -05:00
|
|
|
i = hash_pos(ptr->hash, table->num_bins);
|
2013-11-13 21:33:50 -05:00
|
|
|
retval = (*func)(ptr->key, ptr->record, arg, 0);
|
2012-03-10 09:52:19 -05:00
|
|
|
unpacked:
|
|
|
|
switch (retval) {
|
|
|
|
case ST_CONTINUE:
|
|
|
|
ptr = ptr->fore;
|
|
|
|
break;
|
|
|
|
case ST_CHECK:
|
|
|
|
case ST_STOP:
|
|
|
|
return 0;
|
|
|
|
case ST_DELETE:
|
2014-01-18 00:47:38 -05:00
|
|
|
last = &table->bins[hash_pos(ptr->hash, table->num_bins)];
|
2012-03-10 09:52:19 -05:00
|
|
|
for (; (tmp = *last) != 0; last = &tmp->next) {
|
|
|
|
if (ptr == tmp) {
|
|
|
|
tmp = ptr->fore;
|
|
|
|
*last = ptr->next;
|
|
|
|
remove_entry(table, ptr);
|
|
|
|
st_free_entry(ptr);
|
|
|
|
ptr = tmp;
|
|
|
|
break;
|
2007-08-21 00:43:51 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-02-08 09:34:13 -05:00
|
|
|
} while (ptr && table->head);
|
2007-08-21 00:43:51 -04:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-11-28 03:15:26 -05:00
|
|
|
static st_index_t
|
|
|
|
get_keys(st_table *table, st_data_t *keys, st_index_t size, int check, st_data_t never)
|
2013-11-27 11:07:10 -05:00
|
|
|
{
|
2013-11-28 03:15:26 -05:00
|
|
|
st_data_t key;
|
2013-11-27 11:07:10 -05:00
|
|
|
st_data_t *keys_start = keys;
|
|
|
|
|
|
|
|
if (table->entries_packed) {
|
|
|
|
st_index_t i;
|
|
|
|
|
|
|
|
if (size > table->real_entries) size = table->real_entries;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
|
|
key = PKEY(table, i);
|
2013-11-28 03:15:26 -05:00
|
|
|
if (check && key == never) continue;
|
2013-11-27 11:07:10 -05:00
|
|
|
*keys++ = key;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
st_table_entry *ptr = table->head;
|
|
|
|
st_data_t *keys_end = keys + size;
|
2013-11-28 03:15:26 -05:00
|
|
|
for (; ptr && keys < keys_end; ptr = ptr->fore) {
|
2013-11-27 11:07:10 -05:00
|
|
|
key = ptr->key;
|
2013-11-28 03:15:26 -05:00
|
|
|
if (check && key == never) continue;
|
|
|
|
*keys++ = key;
|
2013-11-27 11:07:10 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return keys - keys_start;
|
|
|
|
}
|
|
|
|
|
2013-11-28 03:15:26 -05:00
|
|
|
st_index_t
|
|
|
|
st_keys(st_table *table, st_data_t *keys, st_index_t size)
|
|
|
|
{
|
|
|
|
return get_keys(table, keys, size, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
st_index_t
|
|
|
|
st_keys_check(st_table *table, st_data_t *keys, st_index_t size, st_data_t never)
|
|
|
|
{
|
|
|
|
return get_keys(table, keys, size, 1, never);
|
|
|
|
}
|
|
|
|
|
2013-11-28 03:39:16 -05:00
|
|
|
static st_index_t
|
|
|
|
get_values(st_table *table, st_data_t *values, st_index_t size, int check, st_data_t never)
|
|
|
|
{
|
|
|
|
st_data_t key;
|
|
|
|
st_data_t *values_start = values;
|
|
|
|
|
|
|
|
if (table->entries_packed) {
|
|
|
|
st_index_t i;
|
|
|
|
|
|
|
|
if (size > table->real_entries) size = table->real_entries;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
|
|
key = PKEY(table, i);
|
|
|
|
if (check && key == never) continue;
|
|
|
|
*values++ = PVAL(table, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
st_table_entry *ptr = table->head;
|
|
|
|
st_data_t *values_end = values + size;
|
|
|
|
for (; ptr && values < values_end; ptr = ptr->fore) {
|
|
|
|
key = ptr->key;
|
|
|
|
if (check && key == never) continue;
|
|
|
|
*values++ = ptr->record;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return values - values_start;
|
|
|
|
}
|
|
|
|
|
|
|
|
st_index_t
|
|
|
|
st_values(st_table *table, st_data_t *values, st_index_t size)
|
|
|
|
{
|
|
|
|
return get_values(table, values, size, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
st_index_t
|
|
|
|
st_values_check(st_table *table, st_data_t *values, st_index_t size, st_data_t never)
|
|
|
|
{
|
|
|
|
return get_values(table, values, size, 1, never);
|
|
|
|
}
|
|
|
|
|
2008-06-05 08:47:48 -04:00
|
|
|
#if 0 /* unused right now */
|
2007-08-21 00:43:51 -04:00
|
|
|
int
|
|
|
|
st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg)
|
|
|
|
{
|
|
|
|
st_table_entry *ptr, **last, *tmp;
|
|
|
|
enum st_retval retval;
|
2009-02-08 09:34:13 -05:00
|
|
|
int i;
|
2007-08-21 00:43:51 -04:00
|
|
|
|
2007-08-28 22:36:54 -04:00
|
|
|
if (table->entries_packed) {
|
|
|
|
for (i = table->num_entries-1; 0 <= i; i--) {
|
|
|
|
int j;
|
|
|
|
st_data_t key, val;
|
2012-01-15 10:46:34 -05:00
|
|
|
key = PKEY(table, i);
|
|
|
|
val = PVAL(table, i);
|
2013-11-13 21:33:50 -05:00
|
|
|
retval = (*func)(key, val, arg, 0);
|
2007-08-28 22:36:54 -04:00
|
|
|
switch (retval) {
|
|
|
|
case ST_CHECK: /* check if hash is modified during iteration */
|
|
|
|
for (j = 0; j < table->num_entries; j++) {
|
2012-01-15 10:46:34 -05:00
|
|
|
if (PKEY(table, j) == key)
|
2007-08-28 22:36:54 -04:00
|
|
|
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:
|
2012-01-15 10:46:30 -05:00
|
|
|
remove_packed_entry(table, i);
|
2007-08-28 22:36:54 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-08-21 00:43:51 -04:00
|
|
|
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 */
|
2014-01-18 00:47:38 -05:00
|
|
|
i = hash_pos(ptr->hash, table->num_bins);
|
2007-08-21 00:43:51 -04:00
|
|
|
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;
|
|
|
|
}
|
2001-05-02 00:22:21 -04:00
|
|
|
}
|
2007-08-21 00:43:51 -04:00
|
|
|
/* fall through */
|
|
|
|
case ST_CONTINUE:
|
|
|
|
ptr = ptr->back;
|
|
|
|
break;
|
|
|
|
case ST_STOP:
|
|
|
|
return 0;
|
|
|
|
case ST_DELETE:
|
2014-01-18 00:47:38 -05:00
|
|
|
last = &table->bins[hash_pos(ptr->hash, table->num_bins)];
|
2007-08-21 00:43:51 -04:00
|
|
|
for (; (tmp = *last) != 0; last = &tmp->next) {
|
|
|
|
if (ptr == tmp) {
|
|
|
|
tmp = ptr->back;
|
|
|
|
*last = ptr->next;
|
2012-01-15 10:46:30 -05:00
|
|
|
remove_entry(table, ptr);
|
2012-01-15 10:46:37 -05:00
|
|
|
st_free_entry(ptr);
|
2007-08-21 00:43:51 -04:00
|
|
|
ptr = tmp;
|
|
|
|
break;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
ptr = ptr->next;
|
2005-12-19 09:10:36 -05:00
|
|
|
free(tmp);
|
1998-01-16 07:13:05 -05:00
|
|
|
table->num_entries--;
|
|
|
|
}
|
2009-02-08 09:34:13 -05:00
|
|
|
} while (ptr && table->head);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 01:47:45 -05:00
|
|
|
return 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2008-06-05 08:47:48 -04:00
|
|
|
#endif
|
1998-01-16 07:13:05 -05:00
|
|
|
|
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-09 17:20:17 -04:00
|
|
|
/*
|
|
|
|
* hash_32 - 32 bit Fowler/Noll/Vo FNV-1a hash code
|
|
|
|
*
|
2007-09-20 14:48:19 -04:00
|
|
|
* @(#) $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 $
|
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-09 17:20:17 -04:00
|
|
|
*
|
|
|
|
***
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
|
2009-09-26 10:29:13 -04:00
|
|
|
#ifdef ST_USE_FNV1
|
2009-09-08 09:10:04 -04:00
|
|
|
static st_index_t
|
2009-09-08 09:18:13 -04:00
|
|
|
strhash(st_data_t arg)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2009-09-08 09:18:13 -04:00
|
|
|
register const char *string = (const char *)arg;
|
2009-09-08 09:10:04 -04:00
|
|
|
register st_index_t hval = FNV1_32A_INIT;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-09 17:20:17 -04:00
|
|
|
/*
|
|
|
|
* FNV-1a hash each octet in the buffer
|
|
|
|
*/
|
|
|
|
while (*string) {
|
|
|
|
/* xor the bottom with the current octet */
|
2006-07-03 16:07:10 -04:00
|
|
|
hval ^= (unsigned int)*string++;
|
2000-02-24 22:51:23 -05:00
|
|
|
|
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-09 17:20:17 -04:00
|
|
|
/* multiply by the 32 bit FNV magic prime mod 2^32 */
|
|
|
|
hval *= FNV_32_PRIME;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-09 17:20:17 -04:00
|
|
|
return hval;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2009-09-26 10:29:13 -04:00
|
|
|
#else
|
|
|
|
|
|
|
|
#ifndef UNALIGNED_WORD_ACCESS
|
2011-07-14 12:51:29 -04:00
|
|
|
# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
|
2013-04-10 17:16:44 -04:00
|
|
|
defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \
|
2014-07-23 10:50:12 -04:00
|
|
|
defined(__powerpc64__) || \
|
2011-07-14 12:51:29 -04:00
|
|
|
defined(__mc68020__)
|
2009-09-26 10:29:13 -04:00
|
|
|
# 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
|
|
|
|
|
2010-10-12 11:18:22 -04:00
|
|
|
#define MurmurMagic_1 (st_index_t)0xc6a4a793
|
|
|
|
#define MurmurMagic_2 (st_index_t)0x5bd1e995
|
2009-09-26 10:29:13 -04:00
|
|
|
#if MURMUR == 1
|
2010-10-12 11:18:22 -04:00
|
|
|
#define MurmurMagic MurmurMagic_1
|
2009-09-26 10:29:13 -04:00
|
|
|
#elif MURMUR == 2
|
|
|
|
#if SIZEOF_ST_INDEX_T > 4
|
2010-10-12 11:18:22 -04:00
|
|
|
#define MurmurMagic ((MurmurMagic_1 << 32) | MurmurMagic_2)
|
2009-09-26 10:29:13 -04:00
|
|
|
#else
|
2010-10-12 11:18:22 -04:00
|
|
|
#define MurmurMagic MurmurMagic_2
|
2009-09-26 10:29:13 -04:00
|
|
|
#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;
|
|
|
|
}
|
|
|
|
|
2010-12-30 20:28:41 -05:00
|
|
|
#define murmur_step(h, k) murmur((h), (k), 16)
|
2009-09-26 10:29:13 -04:00
|
|
|
|
|
|
|
#if MURMUR == 1
|
2010-12-30 20:28:41 -05:00
|
|
|
#define murmur1(h) murmur_step((h), 16)
|
2009-09-26 10:29:13 -04:00
|
|
|
#else
|
2010-12-30 20:28:41 -05:00
|
|
|
#define murmur1(h) murmur_step((h), 24)
|
2009-09-26 10:29:13 -04:00
|
|
|
#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;
|
|
|
|
|
2010-12-30 20:28:41 -05:00
|
|
|
#define data_at(n) (st_index_t)((unsigned char)data[(n)])
|
2009-09-26 10:29:13 -04:00
|
|
|
#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
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2008-01-01 07:24:04 -05:00
|
|
|
int
|
2013-07-16 19:15:41 -04:00
|
|
|
st_locale_insensitive_strcasecmp(const char *s1, const char *s2)
|
2008-01-01 07:24:04 -05:00
|
|
|
{
|
|
|
|
unsigned int c1, c2;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
c1 = (unsigned char)*s1++;
|
|
|
|
c2 = (unsigned char)*s2++;
|
2008-01-01 08:19:21 -05:00
|
|
|
if (c1 == '\0' || c2 == '\0') {
|
|
|
|
if (c1 != '\0') return 1;
|
|
|
|
if (c2 != '\0') return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
2008-01-01 07:24:04 -05:00
|
|
|
if ((unsigned int)(c1 - 'A') <= ('Z' - 'A')) c1 += 'a' - 'A';
|
|
|
|
if ((unsigned int)(c2 - 'A') <= ('Z' - 'A')) c2 += 'a' - 'A';
|
|
|
|
if (c1 != c2) {
|
|
|
|
if (c1 > c2)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2013-07-16 19:15:41 -04:00
|
|
|
st_locale_insensitive_strncasecmp(const char *s1, const char *s2, size_t n)
|
2008-01-01 07:24:04 -05:00
|
|
|
{
|
|
|
|
unsigned int c1, c2;
|
|
|
|
|
|
|
|
while (n--) {
|
|
|
|
c1 = (unsigned char)*s1++;
|
|
|
|
c2 = (unsigned char)*s2++;
|
2008-01-01 08:19:21 -05:00
|
|
|
if (c1 == '\0' || c2 == '\0') {
|
|
|
|
if (c1 != '\0') return 1;
|
|
|
|
if (c2 != '\0') return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
2008-01-01 07:24:04 -05:00
|
|
|
if ((unsigned int)(c1 - 'A') <= ('Z' - 'A')) c1 += 'a' - 'A';
|
|
|
|
if ((unsigned int)(c2 - 'A') <= ('Z' - 'A')) c2 += 'a' - 'A';
|
|
|
|
if (c1 != c2) {
|
|
|
|
if (c1 > c2)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-09-08 09:10:04 -04:00
|
|
|
static st_index_t
|
2009-09-08 09:18:13 -04:00
|
|
|
strcasehash(st_data_t arg)
|
2007-09-28 15:27:10 -04:00
|
|
|
{
|
2009-09-08 09:18:13 -04:00
|
|
|
register const char *string = (const char *)arg;
|
2009-09-08 09:10:04 -04:00
|
|
|
register st_index_t hval = FNV1_32A_INIT;
|
2007-09-28 15:27:10 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* FNV-1a hash each octet in the buffer
|
|
|
|
*/
|
|
|
|
while (*string) {
|
|
|
|
unsigned int c = (unsigned char)*string++;
|
2007-10-16 17:18:09 -04:00
|
|
|
if ((unsigned int)(c - 'A') <= ('Z' - 'A')) c += 'a' - 'A';
|
2007-09-28 15:27:10 -04:00
|
|
|
hval ^= c;
|
|
|
|
|
|
|
|
/* multiply by the 32 bit FNV magic prime mod 2^32 */
|
|
|
|
hval *= FNV_32_PRIME;
|
|
|
|
}
|
|
|
|
return hval;
|
|
|
|
}
|
|
|
|
|
2006-09-11 04:09:19 -04:00
|
|
|
int
|
2007-08-31 22:14:40 -04:00
|
|
|
st_numcmp(st_data_t x, st_data_t y)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
return x != y;
|
|
|
|
}
|
|
|
|
|
2009-09-08 09:10:04 -04:00
|
|
|
st_index_t
|
2007-08-31 22:14:40 -04:00
|
|
|
st_numhash(st_data_t n)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2014-03-22 19:34:21 -04:00
|
|
|
/*
|
|
|
|
* This hash function is lightly-tuned for Ruby. Further tuning
|
|
|
|
* should be possible. Notes:
|
|
|
|
*
|
|
|
|
* - (n >> 3) alone is great for heap objects and OK for fixnum,
|
|
|
|
* however symbols perform poorly.
|
|
|
|
* - (n >> (RUBY_SPECIAL_SHIFT+3)) was added to make symbols hash well,
|
|
|
|
* n.b.: +3 to remove ID scope, +1 worked well initially, too
|
|
|
|
* - (n << 3) was finally added to avoid losing bits for fixnums
|
|
|
|
* - avoid expensive modulo instructions, it is currently only
|
|
|
|
* shifts and bitmask operations.
|
|
|
|
*/
|
|
|
|
return (st_index_t)((n>>(RUBY_SPECIAL_SHIFT+3)|(n<<3)) ^ (n>>3));
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|