summaryrefslogtreecommitdiffhomepage
path: root/src/hash.c
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2014-03-15 15:53:12 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2014-03-15 15:53:12 +0900
commit62505d51cc9c0600677acdae734475cda7095103 (patch)
treee7762e39a13f03cb8900a6005f8fb4f7d0dfcb41 /src/hash.c
parent048bca43c9438b1245fec92d8f05ca0cc0b929d2 (diff)
downloadmruby-62505d51cc9c0600677acdae734475cda7095103.tar.gz
mruby-62505d51cc9c0600677acdae734475cda7095103.zip
calc hash value directly for strings, symbols and numbers
Diffstat (limited to 'src/hash.c')
-rw-r--r--src/hash.c37
1 files changed, 33 insertions, 4 deletions
diff --git a/src/hash.c b/src/hash.c
index 86ad4c63d..ed71d6ee2 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -12,14 +12,43 @@
#include "mruby/string.h"
#include "mruby/variable.h"
+/* a function to get hash value of a float number */
+mrb_int mrb_float_id(mrb_float f);
+
static inline khint_t
mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key)
{
- khint_t h = (khint_t)mrb_type(key) << 24;
- mrb_value h2;
+ enum mrb_vtype t = mrb_type(key);
+ mrb_value hv;
+ const char *p;
+ mrb_int i, len;
+ khint_t h;
+
+ switch (t) {
+ case MRB_TT_STRING:
+ p = RSTRING_PTR(key);
+ len = RSTRING_LEN(key);
+ break;
+
+ case MRB_TT_SYMBOL:
+ p = mrb_sym2name_len(mrb, mrb_symbol(key), &len);
+ break;
+
+ case MRB_TT_FIXNUM:
+ return (khint_t)mrb_float_id((mrb_float)mrb_fixnum(key));
+
+ case MRB_TT_FLOAT:
+ return (khint_t)mrb_float_id(mrb_float(key));
+
+ default:
+ hv = mrb_funcall(mrb, key, "hash", 0);
+ return (khint_t)t ^ mrb_fixnum(hv);
+ }
- h2 = mrb_funcall(mrb, key, "hash", 0);
- h ^= h2.value.i;
+ h = 0;
+ for (i=0; i<len; i++) {
+ h = (h << 5) - h + *p++;
+ }
return h;
}