ext/digest/murmurhash/murmurhash.c in digest-murmurhash-0.0.1 vs ext/digest/murmurhash/murmurhash.c in digest-murmurhash-0.1.0
- old
+ new
@@ -10,11 +10,13 @@
ID id_concat;
typedef struct {
- VALUE data;
+ char* data;
+ char* p;
+ size_t memsize;
} murmur_t;
#define MURMURHASH(self, name) \
murmur_t* name; \
Data_Get_Struct(self, murmur_t, name); \
@@ -23,23 +25,24 @@
}
static void
murmur_init(murmur_t* ptr)
{
- ptr->data = rb_str_new("", 0);
+ ptr->data = (char*) malloc(sizeof(char) * 64);
+ ptr->p = ptr->data;
+ ptr->memsize = 64;
}
static void
murmur_mark(murmur_t* ptr)
{
- rb_gc_mark(ptr->data);
}
static void
murmur_free(murmur_t* ptr)
{
- xfree(ptr);
+ free(ptr->data);
}
static VALUE
murmur_alloc(VALUE self)
{
@@ -47,54 +50,76 @@
murmur_init(ptr);
return Data_Wrap_Struct(self, murmur_mark, murmur_free, ptr);
}
static VALUE
-murmur_initialize_copy(VALUE self, VALUE obj)
+murmur_initialize_copy(VALUE copy, VALUE origin)
{
- if (self == obj) return self;
+ murmur_t *ptr_copy, *ptr_origin;
+ size_t data_len;
- MURMURHASH(self, pctx1);
- MURMURHASH(obj, pctx2);
+ if (copy == origin) return copy;
- rb_check_frozen(self);
+ rb_check_frozen(copy);
- memcpy(pctx1, pctx2, sizeof(murmur_t));
+ Data_Get_Struct(copy, murmur_t, ptr_copy);
+ Data_Get_Struct(origin, murmur_t, ptr_origin);
- return self;
+ data_len = ptr_origin->p - ptr_origin->data;
+ ptr_copy->data = (char*) malloc(sizeof(char) * ptr_origin->memsize);
+ memcpy(ptr_copy->data, ptr_origin->data, data_len);
+ ptr_copy->p = ptr_copy->data + data_len;
+ ptr_copy->memsize = ptr_origin->memsize;
+
+ return copy;
}
static VALUE
murmur_reset(VALUE self)
{
MURMURHASH(self, ptr);
- murmur_init(ptr);
+ ptr->p = ptr->data;
return self;
}
static VALUE
murmur_update(VALUE self, VALUE str)
{
+ size_t data_len, str_len, require, newsize;
+ const char* str_p;
MURMURHASH(self, ptr);
+
StringValue(str);
- rb_funcall(ptr->data, id_concat, 1, str);
+ str_p = RSTRING_PTR(str);
+ str_len = RSTRING_LEN(str);
+ data_len = (ptr->p - ptr->data);
+ require = data_len + str_len;
+ if (ptr->memsize < require) {
+ newsize = ptr->memsize;
+ while (newsize < require) {
+ newsize *= 2;
+ }
+ ptr->data = realloc(ptr->data, sizeof(char) * newsize);
+ ptr->p = ptr->data + data_len;
+ ptr->memsize = newsize;
+ }
+ memcpy(ptr->p, str_p, str_len);
+ ptr->p += str_len;
+
return self;
}
-static VALUE
-murmur_finish(VALUE self)
+static uint32_t
+murmur_hash_process(murmur_t* ptr)
{
const uint32_t m = 0x5bd1e995;
const uint8_t r = 16;
uint32_t length, h;
const char* p;
- uint8_t digest[MURMURHASH_DIGEST_LENGTH];
- MURMURHASH(self, ptr);
-
- p = RSTRING_PTR(ptr->data);
- length = RSTRING_LEN(ptr->data);
+ p = ptr->data;
+ length = ptr->p - ptr->data;
h = length * m;
while (4 <= length) {
h += *(uint32_t*)p;
h *= m;
@@ -117,10 +142,22 @@
h *= m;
h ^= h >> 10;
h *= m;
h ^= h >> 17;
+ return h;
+}
+
+static VALUE
+murmur_finish(VALUE self)
+{
+ uint32_t h;
+ uint8_t digest[MURMURHASH_DIGEST_LENGTH];
+ MURMURHASH(self, ptr);
+
+ h = murmur_hash_process(ptr);
+
digest[0] = (h >> 24);
digest[1] = (h >> 16);
digest[2] = (h >> 8);
digest[3] = (h);
@@ -137,10 +174,17 @@
murmur_block_length(VALUE self)
{
return INT2NUM(MURMURHASH_BLOCK_LENGTH);
}
+static VALUE
+murmur_to_i(VALUE self)
+{
+ MURMURHASH(self, ptr);
+ return UINT2NUM(murmur_hash_process(ptr));
+}
+
void
Init_murmurhash()
{
VALUE mDigest, cDigest_Base, cDigest_MurmurHash;
@@ -158,6 +202,8 @@
rb_define_method(cDigest_MurmurHash, "reset", murmur_reset, 0);
rb_define_method(cDigest_MurmurHash, "update", murmur_update, 1);
rb_define_private_method(cDigest_MurmurHash, "finish", murmur_finish, 0);
rb_define_method(cDigest_MurmurHash, "digest_length", murmur_digest_length, 0);
rb_define_method(cDigest_MurmurHash, "block_length", murmur_block_length, 0);
+
+ rb_define_method(cDigest_MurmurHash, "to_i", murmur_to_i, 0);
}