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); }