Permalink
Browse files

add stringify and objectify function.

  • Loading branch information...
1 parent 706245d commit 5f90ec71ceb1b4e1fbe54e9d38da45bddc003a72 @fbzhong committed May 8, 2011
Showing with 281 additions and 29 deletions.
  1. +124 −18 binding.cc
  2. +157 −11 test.js
View
@@ -29,26 +29,19 @@
using namespace v8;
-Local<String>
-stringify_hash(uint64 hash) {
- // hash to char
- char buf[MAX_64_HASH_LEN];
- memset(buf, 0, MAX_64_HASH_LEN);
- snprintf(buf, MAX_64_HASH_LEN, "%llu", hash);
-
- return String::New(buf);
+inline uint32 Uint64High32(const uint64 &x) {
+ return (uint32)((x >> 32) & 0xFFFFFFFF);
}
-Local<String>
-stringify_hash(uint128* hash) {
- // hash to char
- char buf[MAX_128_HASH_LEN];
- memset(buf, 0, MAX_128_HASH_LEN);
- snprintf(buf, MAX_128_HASH_LEN, "%llu,%llu", Uint128Low64(*hash), Uint128High64(*hash));
+inline uint32 Uint64Low32(const uint64 &x) {
+ return (uint32)x;
+}
- return String::New(buf);
+inline uint64 HighLow32ToUint64(const uint32 &low, const uint32 &high) {
+ return ((uint64_t)low) + ((((uint64_t)high) << 32) & 0xFFFFFFFF00000000);
}
+
uint64
to_uint64(const char* data, size_t len) {
std::stringstream str;
@@ -59,6 +52,13 @@ to_uint64(const char* data, size_t len) {
return v;
}
+inline uint64
+to_uint64(const Local<Object> &obj) {
+ Local<Uint32> low = obj->Get(String::New("low"))->ToUint32();
+ Local<Uint32> high = obj->Get(String::New("high"))->ToUint32();
+ return HighLow32ToUint64(low->Value(), high->Value());
+}
+
void
to_uint128(uint128* v, const char* data, size_t len) {
std::stringstream str;
@@ -84,6 +84,110 @@ to_uint128(uint128* v, const char* data, size_t len) {
}
}
+inline void
+to_uint128(uint128 *v, const Local<Object> &obj) {
+ v->first = to_uint64(obj->Get(String::New("low"))->ToObject());
+ v->second = to_uint64(obj->Get(String::New("high"))->ToObject());
+}
+
+Local<String>
+stringify_hash(const uint64 &hash) {
+ // hash to char
+ char buf[MAX_64_HASH_LEN];
+ memset(buf, 0, MAX_64_HASH_LEN);
+ snprintf(buf, MAX_64_HASH_LEN, "%llu", hash);
+
+ return String::New(buf);
+}
+
+Local<String>
+stringify_hash(const uint128 &hash) {
+ // hash to char
+ char buf[MAX_128_HASH_LEN];
+ memset(buf, 0, MAX_128_HASH_LEN);
+ snprintf(buf, MAX_128_HASH_LEN, "%llu,%llu", Uint128Low64(hash), Uint128High64(hash));
+
+ return String::New(buf);
+}
+
+Local<String>
+stringify_hash(Local<Object> obj) {
+ Local<Value> lowObject = obj->Get(String::New("low"));
+ if(lowObject->IsObject()) {
+ uint128 hash128;
+ to_uint128(&hash128, obj);
+ return stringify_hash(hash128);
+ } else {
+ return stringify_hash(to_uint64(obj));
+ }
+}
+
+Local<Object>
+objectify_hash(const uint64 &hash) {
+ uint32 low = Uint64Low32(hash);
+ uint32 high = Uint64High32(hash);
+
+ Local<Object> ret = Object::New();
+ ret->Set(String::New("low"), Integer::NewFromUnsigned(low));
+ ret->Set(String::New("high"), Integer::NewFromUnsigned(high));
+ ret->Set(String::New("value"), stringify_hash(hash));
+ ret->Set(String::New("uint64"), Boolean::New(true));
+
+ return ret;
+}
+
+Local<Object>
+objectify_hash(const uint128 &hash) {
+ Local<Object> ret = Object::New();
+ ret->Set(String::New("low"), objectify_hash(Uint128Low64(hash)));
+ ret->Set(String::New("high"), objectify_hash(Uint128High64(hash)));
+ ret->Set(String::New("value"), stringify_hash(hash));
+ ret->Set(String::New("uint128"), Boolean::New(true));
+
+ return ret;
+}
+
+Local<Object>
+objectify_hash(const String::AsciiValue &hash) {
+ const char *data = *hash;
+ size_t len = hash.length();
+
+ char *ch = strchr(data, ',');
+ if(ch == NULL) {
+ return objectify_hash(to_uint64(data, len));
+ } else {
+ uint128 hash128;
+ to_uint128(&hash128, data, len);
+ return objectify_hash(hash128);
+ }
+}
+
+Handle<Value>
+node_Stringify(const Arguments& args) {
+ HandleScope scope;
+
+ int args_len = args.Length();
+ if(args_len != 1 || !args[0]->IsObject()) {
+ return ThrowException(String::New("Invalid arguments."));
+ }
+
+ Local<Object> obj = args[0]->ToObject();
+ return scope.Close(stringify_hash(obj));
+}
+
+Handle<Value>
+node_Objectify(const Arguments& args) {
+ HandleScope scope;
+
+ int args_len = args.Length();
+ if(args_len != 1) {
+ return ThrowException(String::New("Invalid arguments."));
+ }
+
+ String::AsciiValue obj(args[0]->ToString());
+ return scope.Close(objectify_hash(obj));
+}
+
Handle<Value>
node_CityHash64(const Arguments& args) {
HandleScope scope;
@@ -115,7 +219,7 @@ node_CityHash64(const Arguments& args) {
hash = CityHash64WithSeeds(str, len, seed0, seed1);
}
- return scope.Close(stringify_hash(hash));
+ return scope.Close(objectify_hash(hash));
}
Handle<Value>
@@ -143,7 +247,7 @@ node_CityHash128(const Arguments& args) {
hash = CityHash128(str, len);
}
- return scope.Close(stringify_hash(&hash));
+ return scope.Close(objectify_hash(hash));
}
Handle<Value>
@@ -171,12 +275,14 @@ node_CityHashCrc128(const Arguments& args) {
hash = CityHashCrc128(str, len);
}
- return scope.Close(stringify_hash(&hash));
+ return scope.Close(objectify_hash(hash));
}
extern "C" void
init (Handle<Object> target) {
HandleScope scope;
+ target->Set(String::New("stringify"), FunctionTemplate::New(node_Stringify)->GetFunction());
+ target->Set(String::New("objectify"), FunctionTemplate::New(node_Objectify)->GetFunction());
target->Set(String::New("hash64"), FunctionTemplate::New(node_CityHash64)->GetFunction());
target->Set(String::New("hash128"), FunctionTemplate::New(node_CityHash128)->GetFunction());
target->Set(String::New("crc128"), FunctionTemplate::New(node_CityHashCrc128)->GetFunction());
View
@@ -2,15 +2,37 @@ var cityhash = require('./build/default/cityhash.node');
var passed = true;
+function equal(expected, actual) {
+ var type_expected = typeof expected;
+ var type_actual = typeof actual;
+
+ if(type_expected != type_actual) {
+ return false;
+ } else if(type_expected === 'object') {
+ for(var key in expected) {
+ var expected_value = expected[key];
+ var actual_value = actual[key];
+ if(!equal(expected_value, actual_value)) {
+ return false;
+ }
+ }
+ } else if(expected != actual) {
+ return false;
+ }
+ return true;
+}
+
function assertEqual(expected, actual, message) {
- if(expected != actual) {
+ var failed = !equal(expected, actual);
+
+ if(failed) {
if(message) {
message += '. ';
} else {
message = '';
}
passed = false;
- console.log('[Error]' + message + 'Expected ' + expected + ' , but actual is ' + actual);
+ console.log('[Error]' + message + 'Expected ' + JSON.stringify(expected) + ' , but actual is ' + JSON.stringify(actual));
}
}
@@ -20,16 +42,140 @@ function end() {
}
}
-assertEqual('6596376470467341850', cityhash.hash64('Hello'), 'Hash64 for "Hello"');
-assertEqual('2578220239953316063', cityhash.hash64('hello'), 'Hash64 for "hello"');
-assertEqual('15738392108067291633', cityhash.hash64('Hello', 87392039), 'Hash64 for "hello" with seed 87392039');
-assertEqual('16267654833214665223', cityhash.hash64('Hello', 87392039, 1230234), 'Hash64 for "hello" with seed 87392039 and 1230234');
+assertEqual('6596376470467341850', cityhash.stringify({low:1727229466, high:1535838579}), 'Stringify for uint64 object');
+assertEqual({low:1727229466, high:1535838579}, cityhash.objectify('6596376470467341850'), 'Objectify for uint64 hash string');
+
+assertEqual('9138004313465017137,12242971252332641544', cityhash.stringify({
+ "low": {
+ "low": 68277041,
+ "high": 2127607426
+ },
+ "high": {
+ "low": 3936042248,
+ "high": 2850538876
+ }}), 'Stringify for uint128 object');
+
+assertEqual({
+ "low": {
+ "low": 68277041,
+ "high": 2127607426
+ },
+ "high": {
+ "low": 3936042248,
+ "high": 2850538876
+ }}, cityhash.objectify('9138004313465017137,12242971252332641544'), 'Stringify for uint128 object');
+
+assertEqual({
+ low: 1727229466,
+ high: 1535838579,
+ uint64: true,
+ value:'6596376470467341850'
+ }, cityhash.hash64('Hello'), 'Hash64 for "Hello"');
+
+assertEqual({
+ low: 4079208671,
+ high: 600288677,
+ uint64: true,
+ value: '2578220239953316063'
+ }, cityhash.hash64('hello'), 'Hash64 for "hello"');
+
+assertEqual({
+ low: 2569634289,
+ high: 3664379964,
+ uint64: true,
+ value: '15738392108067291633'
+ }, cityhash.hash64('Hello', 87392039), 'Hash64 for "hello" with seed 87392039');
+
+assertEqual({
+ low: 2389520903,
+ high: 3787608545,
+ value: '16267654833214665223',
+ uint64: true,
+ }, cityhash.hash64('Hello', 87392039, 1230234), 'Hash64 for "hello" with seed 87392039 and 1230234');
+
+assertEqual({
+ "low": {
+ "low": 68277041,
+ "high": 2127607426,
+ "value": "9138004313465017137",
+ "uint64": true
+ },
+ "high": {
+ "low": 3936042248,
+ "high": 2850538876,
+ "value": "12242971252332641544",
+ "uint64": true
+ },
+ "value": "9138004313465017137,12242971252332641544",
+ "uint128": true
+ }, cityhash.hash128('Hello'), 'Hash128 for "Hello"');
+
+assertEqual({
+ "low": {
+ "low": 3440602095,
+ "high": 3148776037,
+ "value": "13523890104784088047",
+ "uint64": true
+ },
+ "high": {
+ "low": 2750723564,
+ "high": 4052229467,
+ "value": "17404193039403234796",
+ "uint64": true
+ },
+ "value": "13523890104784088047,17404193039403234796",
+ "uint128": true
+ }, cityhash.hash128('hello'), 'Hash128 for "hello"');
+
+assertEqual({
+ "low": {
+ "low": 3184066266,
+ "high": 3674042232,
+ "value": "15779891233746910938",
+ "uint64": true
+ },
+ "high": {
+ "low": 4196783977,
+ "high": 3519958761,
+ "value": "15118107765960464233",
+ "uint64": true
+ },
+ "value": "15779891233746910938,15118107765960464233",
+ "uint128": true
+ }, cityhash.hash128('Hello', '12343,30293'), 'Hash128 for "Hello" with seed 12343,30293');
-assertEqual('9138004313465017137,12242971252332641544', cityhash.hash128('Hello'), 'Hash128 for "Hello"');
-assertEqual('13523890104784088047,17404193039403234796', cityhash.hash128('hello'), 'Hash128 for "hello"');
-assertEqual('15779891233746910938,15118107765960464233', cityhash.hash128('Hello', '12343,30293'), 'Hash128 for "Hello" with seed 12343,30293');
+assertEqual({
+ "low": {
+ "low": 68277041,
+ "high": 2127607426,
+ "value": "9138004313465017137",
+ "uint64": true
+ },
+ "high": {
+ "low": 3936042248,
+ "high": 2850538876,
+ "value": "12242971252332641544",
+ "uint64": true
+ },
+ "value": "9138004313465017137,12242971252332641544",
+ "uint128": true
+ }, cityhash.crc128('Hello'), 'Crc128 for "Hello"');
-assertEqual('9138004313465017137,12242971252332641544', cityhash.crc128('Hello'), 'Crc128 for "Hello"');
-assertEqual('15779891233746910938,15118107765960464233', cityhash.crc128('Hello', '12343,30293'), 'Crc128 for "Hello" with seed 12343,30293');
+assertEqual({
+ "low": {
+ "low": 3184066266,
+ "high": 3674042232,
+ "value": "15779891233746910938",
+ "uint64": true
+ },
+ "high": {
+ "low": 4196783977,
+ "high": 3519958761,
+ "value": "15118107765960464233",
+ "uint64": true
+ },
+ "value": "15779891233746910938,15118107765960464233",
+ "uint128": true
+ }, cityhash.crc128('Hello', '12343,30293'), 'Crc128 for "Hello" with seed 12343,30293');
end();

0 comments on commit 5f90ec7

Please sign in to comment.