Skip to content

Commit

Permalink
add stringify and objectify function.
Browse files Browse the repository at this point in the history
  • Loading branch information
fbzhong committed May 8, 2011
1 parent 706245d commit 5f90ec7
Show file tree
Hide file tree
Showing 2 changed files with 281 additions and 29 deletions.
142 changes: 124 additions & 18 deletions binding.cc
Expand Up @@ -29,26 +29,19 @@


using namespace v8; using namespace v8;


Local<String> inline uint32 Uint64High32(const uint64 &x) {
stringify_hash(uint64 hash) { return (uint32)((x >> 32) & 0xFFFFFFFF);
// 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> inline uint32 Uint64Low32(const uint64 &x) {
stringify_hash(uint128* hash) { return (uint32)x;
// 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); inline uint64 HighLow32ToUint64(const uint32 &low, const uint32 &high) {
return ((uint64_t)low) + ((((uint64_t)high) << 32) & 0xFFFFFFFF00000000);
} }



uint64 uint64
to_uint64(const char* data, size_t len) { to_uint64(const char* data, size_t len) {
std::stringstream str; std::stringstream str;
Expand All @@ -59,6 +52,13 @@ to_uint64(const char* data, size_t len) {
return v; 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 void
to_uint128(uint128* v, const char* data, size_t len) { to_uint128(uint128* v, const char* data, size_t len) {
std::stringstream str; std::stringstream str;
Expand All @@ -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> Handle<Value>
node_CityHash64(const Arguments& args) { node_CityHash64(const Arguments& args) {
HandleScope scope; HandleScope scope;
Expand Down Expand Up @@ -115,7 +219,7 @@ node_CityHash64(const Arguments& args) {
hash = CityHash64WithSeeds(str, len, seed0, seed1); hash = CityHash64WithSeeds(str, len, seed0, seed1);
} }


return scope.Close(stringify_hash(hash)); return scope.Close(objectify_hash(hash));
} }


Handle<Value> Handle<Value>
Expand Down Expand Up @@ -143,7 +247,7 @@ node_CityHash128(const Arguments& args) {
hash = CityHash128(str, len); hash = CityHash128(str, len);
} }


return scope.Close(stringify_hash(&hash)); return scope.Close(objectify_hash(hash));
} }


Handle<Value> Handle<Value>
Expand Down Expand Up @@ -171,12 +275,14 @@ node_CityHashCrc128(const Arguments& args) {
hash = CityHashCrc128(str, len); hash = CityHashCrc128(str, len);
} }


return scope.Close(stringify_hash(&hash)); return scope.Close(objectify_hash(hash));
} }


extern "C" void extern "C" void
init (Handle<Object> target) { init (Handle<Object> target) {
HandleScope scope; 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("hash64"), FunctionTemplate::New(node_CityHash64)->GetFunction());
target->Set(String::New("hash128"), FunctionTemplate::New(node_CityHash128)->GetFunction()); target->Set(String::New("hash128"), FunctionTemplate::New(node_CityHash128)->GetFunction());
target->Set(String::New("crc128"), FunctionTemplate::New(node_CityHashCrc128)->GetFunction()); target->Set(String::New("crc128"), FunctionTemplate::New(node_CityHashCrc128)->GetFunction());
Expand Down
168 changes: 157 additions & 11 deletions test.js
Expand Up @@ -2,15 +2,37 @@ var cityhash = require('./build/default/cityhash.node');


var passed = true; 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) { function assertEqual(expected, actual, message) {
if(expected != actual) { var failed = !equal(expected, actual);

if(failed) {
if(message) { if(message) {
message += '. '; message += '. ';
} else { } else {
message = ''; message = '';
} }
passed = false; 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));
} }
} }


Expand All @@ -20,16 +42,140 @@ function end() {
} }
} }


assertEqual('6596376470467341850', cityhash.hash64('Hello'), 'Hash64 for "Hello"'); assertEqual('6596376470467341850', cityhash.stringify({low:1727229466, high:1535838579}), 'Stringify for uint64 object');
assertEqual('2578220239953316063', cityhash.hash64('hello'), 'Hash64 for "hello"'); assertEqual({low:1727229466, high:1535838579}, cityhash.objectify('6596376470467341850'), 'Objectify for uint64 hash string');
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('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({
assertEqual('13523890104784088047,17404193039403234796', cityhash.hash128('hello'), 'Hash128 for "hello"'); "low": {
assertEqual('15779891233746910938,15118107765960464233', cityhash.hash128('Hello', '12343,30293'), 'Hash128 for "Hello" with seed 12343,30293'); "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({
assertEqual('15779891233746910938,15118107765960464233', cityhash.crc128('Hello', '12343,30293'), 'Crc128 for "Hello" with seed 12343,30293'); "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(); end();

0 comments on commit 5f90ec7

Please sign in to comment.