Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

add stringify and objectify function.

  • Loading branch information...
commit 5f90ec71ceb1b4e1fbe54e9d38da45bddc003a72 1 parent 706245d
Robin authored May 08, 2011

Showing 2 changed files with 281 additions and 29 deletions. Show diff stats Hide diff stats

  1. 142  binding.cc
  2. 168  test.js
142  binding.cc
@@ -29,26 +29,19 @@
29 29
 
30 30
 using namespace v8;
31 31
 
32  
-Local<String>
33  
-stringify_hash(uint64 hash) {
34  
-    // hash to char
35  
-    char buf[MAX_64_HASH_LEN];
36  
-    memset(buf, 0, MAX_64_HASH_LEN);
37  
-    snprintf(buf, MAX_64_HASH_LEN, "%llu", hash);
38  
-
39  
-    return String::New(buf);
  32
+inline uint32 Uint64High32(const uint64 &x) {
  33
+    return (uint32)((x >> 32) & 0xFFFFFFFF);
40 34
 }
41 35
 
42  
-Local<String>
43  
-stringify_hash(uint128* hash) {
44  
-    // hash to char
45  
-    char buf[MAX_128_HASH_LEN];
46  
-    memset(buf, 0, MAX_128_HASH_LEN);
47  
-    snprintf(buf, MAX_128_HASH_LEN, "%llu,%llu", Uint128Low64(*hash), Uint128High64(*hash));
  36
+inline uint32 Uint64Low32(const uint64 &x) {
  37
+    return (uint32)x;
  38
+}
48 39
 
49  
-    return String::New(buf);
  40
+inline uint64 HighLow32ToUint64(const uint32 &low, const uint32 &high) {
  41
+    return ((uint64_t)low) + ((((uint64_t)high) << 32) & 0xFFFFFFFF00000000);
50 42
 }
51 43
 
  44
+
52 45
 uint64
53 46
 to_uint64(const char* data, size_t len) {
54 47
     std::stringstream str;
@@ -59,6 +52,13 @@ to_uint64(const char* data, size_t len) {
59 52
     return v;
60 53
 }
61 54
 
  55
+inline uint64
  56
+to_uint64(const Local<Object> &obj) {
  57
+    Local<Uint32> low = obj->Get(String::New("low"))->ToUint32();
  58
+    Local<Uint32> high = obj->Get(String::New("high"))->ToUint32();
  59
+    return HighLow32ToUint64(low->Value(), high->Value());
  60
+}
  61
+
62 62
 void
63 63
 to_uint128(uint128* v, const char* data, size_t len) {
64 64
     std::stringstream str;
@@ -84,6 +84,110 @@ to_uint128(uint128* v, const char* data, size_t len) {
84 84
     }
85 85
 }
86 86
 
  87
+inline void
  88
+to_uint128(uint128 *v, const Local<Object> &obj) {
  89
+    v->first = to_uint64(obj->Get(String::New("low"))->ToObject());
  90
+    v->second = to_uint64(obj->Get(String::New("high"))->ToObject());
  91
+}
  92
+
  93
+Local<String>
  94
+stringify_hash(const uint64 &hash) {
  95
+    // hash to char
  96
+    char buf[MAX_64_HASH_LEN];
  97
+    memset(buf, 0, MAX_64_HASH_LEN);
  98
+    snprintf(buf, MAX_64_HASH_LEN, "%llu", hash);
  99
+
  100
+    return String::New(buf);
  101
+}
  102
+
  103
+Local<String>
  104
+stringify_hash(const uint128 &hash) {
  105
+    // hash to char
  106
+    char buf[MAX_128_HASH_LEN];
  107
+    memset(buf, 0, MAX_128_HASH_LEN);
  108
+    snprintf(buf, MAX_128_HASH_LEN, "%llu,%llu", Uint128Low64(hash), Uint128High64(hash));
  109
+
  110
+    return String::New(buf);
  111
+}
  112
+
  113
+Local<String>
  114
+stringify_hash(Local<Object> obj) {
  115
+    Local<Value> lowObject = obj->Get(String::New("low"));
  116
+    if(lowObject->IsObject()) {
  117
+        uint128 hash128;
  118
+        to_uint128(&hash128, obj);
  119
+        return stringify_hash(hash128);
  120
+    } else {
  121
+        return stringify_hash(to_uint64(obj));
  122
+    }
  123
+}
  124
+
  125
+Local<Object>
  126
+objectify_hash(const uint64 &hash) {
  127
+    uint32 low = Uint64Low32(hash);
  128
+    uint32 high = Uint64High32(hash);
  129
+
  130
+    Local<Object> ret = Object::New();
  131
+    ret->Set(String::New("low"), Integer::NewFromUnsigned(low));
  132
+    ret->Set(String::New("high"), Integer::NewFromUnsigned(high));
  133
+    ret->Set(String::New("value"), stringify_hash(hash));
  134
+    ret->Set(String::New("uint64"), Boolean::New(true));
  135
+
  136
+    return ret;
  137
+}
  138
+
  139
+Local<Object>
  140
+objectify_hash(const uint128 &hash) {
  141
+    Local<Object> ret = Object::New();
  142
+    ret->Set(String::New("low"), objectify_hash(Uint128Low64(hash)));
  143
+    ret->Set(String::New("high"), objectify_hash(Uint128High64(hash)));
  144
+    ret->Set(String::New("value"), stringify_hash(hash));
  145
+    ret->Set(String::New("uint128"), Boolean::New(true));
  146
+
  147
+    return ret;
  148
+}
  149
+
  150
+Local<Object>
  151
+objectify_hash(const String::AsciiValue &hash) {
  152
+    const char *data = *hash;
  153
+    size_t len = hash.length();
  154
+
  155
+    char *ch = strchr(data, ',');
  156
+    if(ch == NULL) {
  157
+        return objectify_hash(to_uint64(data, len));
  158
+    } else {
  159
+        uint128 hash128;
  160
+        to_uint128(&hash128, data, len);
  161
+        return objectify_hash(hash128);
  162
+    }
  163
+}
  164
+
  165
+Handle<Value>
  166
+node_Stringify(const Arguments& args) {
  167
+    HandleScope scope;
  168
+
  169
+    int args_len = args.Length();
  170
+    if(args_len != 1 || !args[0]->IsObject()) {
  171
+        return ThrowException(String::New("Invalid arguments."));
  172
+    }
  173
+
  174
+    Local<Object> obj = args[0]->ToObject();
  175
+    return scope.Close(stringify_hash(obj));
  176
+}
  177
+
  178
+Handle<Value>
  179
+node_Objectify(const Arguments& args) {
  180
+    HandleScope scope;
  181
+
  182
+    int args_len = args.Length();
  183
+    if(args_len != 1) {
  184
+        return ThrowException(String::New("Invalid arguments."));
  185
+    }
  186
+
  187
+    String::AsciiValue obj(args[0]->ToString());
  188
+    return scope.Close(objectify_hash(obj));
  189
+}
  190
+
87 191
 Handle<Value>
88 192
 node_CityHash64(const Arguments& args) {
89 193
     HandleScope scope;
@@ -115,7 +219,7 @@ node_CityHash64(const Arguments& args) {
115 219
         hash = CityHash64WithSeeds(str, len, seed0, seed1);
116 220
     }
117 221
 
118  
-    return scope.Close(stringify_hash(hash));
  222
+    return scope.Close(objectify_hash(hash));
119 223
 }
120 224
 
121 225
 Handle<Value>
@@ -143,7 +247,7 @@ node_CityHash128(const Arguments& args) {
143 247
         hash = CityHash128(str, len);
144 248
     }
145 249
 
146  
-    return scope.Close(stringify_hash(&hash));
  250
+    return scope.Close(objectify_hash(hash));
147 251
 }
148 252
 
149 253
 Handle<Value>
@@ -171,12 +275,14 @@ node_CityHashCrc128(const Arguments& args) {
171 275
         hash = CityHashCrc128(str, len);
172 276
     }
173 277
 
174  
-    return scope.Close(stringify_hash(&hash));
  278
+    return scope.Close(objectify_hash(hash));
175 279
 }
176 280
 
177 281
 extern "C" void
178 282
 init (Handle<Object> target) {
179 283
     HandleScope scope;
  284
+    target->Set(String::New("stringify"), FunctionTemplate::New(node_Stringify)->GetFunction());
  285
+    target->Set(String::New("objectify"), FunctionTemplate::New(node_Objectify)->GetFunction());
180 286
     target->Set(String::New("hash64"), FunctionTemplate::New(node_CityHash64)->GetFunction());
181 287
     target->Set(String::New("hash128"), FunctionTemplate::New(node_CityHash128)->GetFunction());
182 288
     target->Set(String::New("crc128"), FunctionTemplate::New(node_CityHashCrc128)->GetFunction());
168  test.js
@@ -2,15 +2,37 @@ var cityhash = require('./build/default/cityhash.node');
2 2
 
3 3
 var passed = true;
4 4
 
  5
+function equal(expected, actual) {
  6
+    var type_expected = typeof expected;
  7
+    var type_actual = typeof actual;
  8
+
  9
+    if(type_expected != type_actual) {
  10
+        return false;
  11
+    } else if(type_expected === 'object') {
  12
+        for(var key in expected) {
  13
+            var expected_value = expected[key];
  14
+            var actual_value = actual[key];
  15
+            if(!equal(expected_value, actual_value)) {
  16
+                return false;
  17
+            }
  18
+        }
  19
+    } else if(expected != actual) {
  20
+        return false;
  21
+    }
  22
+    return true;
  23
+}
  24
+
5 25
 function assertEqual(expected, actual, message) {
6  
-    if(expected != actual) {
  26
+    var failed = !equal(expected, actual);
  27
+
  28
+    if(failed) {
7 29
         if(message) {
8 30
             message += '. ';
9 31
         } else {
10 32
             message = '';
11 33
         }
12 34
         passed = false;
13  
-        console.log('[Error]' + message + 'Expected ' + expected + ' , but actual is ' + actual);
  35
+        console.log('[Error]' + message + 'Expected ' + JSON.stringify(expected) + ' , but actual is ' + JSON.stringify(actual));
14 36
     }
15 37
 }
16 38
 
@@ -20,16 +42,140 @@ function end() {
20 42
     }
21 43
 }
22 44
 
23  
-assertEqual('6596376470467341850', cityhash.hash64('Hello'), 'Hash64 for "Hello"');
24  
-assertEqual('2578220239953316063', cityhash.hash64('hello'), 'Hash64 for "hello"');
25  
-assertEqual('15738392108067291633', cityhash.hash64('Hello', 87392039), 'Hash64 for "hello" with seed 87392039');
26  
-assertEqual('16267654833214665223', cityhash.hash64('Hello', 87392039, 1230234), 'Hash64 for "hello" with seed 87392039 and 1230234');
  45
+assertEqual('6596376470467341850', cityhash.stringify({low:1727229466, high:1535838579}), 'Stringify for uint64 object');
  46
+assertEqual({low:1727229466, high:1535838579}, cityhash.objectify('6596376470467341850'), 'Objectify for uint64 hash string');
  47
+
  48
+assertEqual('9138004313465017137,12242971252332641544', cityhash.stringify({
  49
+            "low": {
  50
+                "low": 68277041,
  51
+                "high": 2127607426
  52
+            },
  53
+            "high": {
  54
+                "low": 3936042248,
  55
+                "high": 2850538876
  56
+            }}), 'Stringify for uint128 object');
  57
+
  58
+assertEqual({
  59
+            "low": {
  60
+                "low": 68277041,
  61
+                "high": 2127607426
  62
+            },
  63
+            "high": {
  64
+                "low": 3936042248,
  65
+                "high": 2850538876
  66
+            }}, cityhash.objectify('9138004313465017137,12242971252332641544'), 'Stringify for uint128 object');
  67
+
  68
+assertEqual({
  69
+    low: 1727229466,
  70
+    high: 1535838579,
  71
+    uint64: true,
  72
+    value:'6596376470467341850'
  73
+    }, cityhash.hash64('Hello'), 'Hash64 for "Hello"');
  74
+
  75
+assertEqual({
  76
+        low: 4079208671,
  77
+        high: 600288677,
  78
+        uint64: true,
  79
+        value: '2578220239953316063'
  80
+    }, cityhash.hash64('hello'), 'Hash64 for "hello"');
  81
+
  82
+assertEqual({
  83
+        low: 2569634289,
  84
+        high: 3664379964,
  85
+        uint64: true,
  86
+        value: '15738392108067291633'
  87
+    }, cityhash.hash64('Hello', 87392039), 'Hash64 for "hello" with seed 87392039');
  88
+
  89
+assertEqual({
  90
+        low: 2389520903,
  91
+        high: 3787608545,
  92
+        value: '16267654833214665223',
  93
+        uint64: true,
  94
+    }, cityhash.hash64('Hello', 87392039, 1230234), 'Hash64 for "hello" with seed 87392039 and 1230234');
  95
+
  96
+assertEqual({
  97
+        "low": {
  98
+            "low": 68277041,
  99
+            "high": 2127607426,
  100
+            "value": "9138004313465017137",
  101
+            "uint64": true
  102
+        },
  103
+        "high": {
  104
+            "low": 3936042248,
  105
+            "high": 2850538876,
  106
+            "value": "12242971252332641544",
  107
+            "uint64": true
  108
+        },
  109
+        "value": "9138004313465017137,12242971252332641544",
  110
+        "uint128": true
  111
+    }, cityhash.hash128('Hello'), 'Hash128 for "Hello"');
  112
+
  113
+assertEqual({
  114
+        "low": {
  115
+            "low": 3440602095,
  116
+            "high": 3148776037,
  117
+            "value": "13523890104784088047",
  118
+            "uint64": true
  119
+        },
  120
+        "high": {
  121
+            "low": 2750723564,
  122
+            "high": 4052229467,
  123
+            "value": "17404193039403234796",
  124
+            "uint64": true
  125
+        },
  126
+        "value": "13523890104784088047,17404193039403234796",
  127
+        "uint128": true
  128
+    }, cityhash.hash128('hello'), 'Hash128 for "hello"');
  129
+
  130
+assertEqual({
  131
+        "low": {
  132
+            "low": 3184066266,
  133
+            "high": 3674042232,
  134
+            "value": "15779891233746910938",
  135
+            "uint64": true
  136
+        },
  137
+        "high": {
  138
+            "low": 4196783977,
  139
+            "high": 3519958761,
  140
+            "value": "15118107765960464233",
  141
+            "uint64": true
  142
+        },
  143
+        "value": "15779891233746910938,15118107765960464233",
  144
+        "uint128": true
  145
+    }, cityhash.hash128('Hello', '12343,30293'), 'Hash128 for "Hello" with seed 12343,30293');
27 146
 
28  
-assertEqual('9138004313465017137,12242971252332641544', cityhash.hash128('Hello'), 'Hash128 for "Hello"');
29  
-assertEqual('13523890104784088047,17404193039403234796', cityhash.hash128('hello'), 'Hash128 for "hello"');
30  
-assertEqual('15779891233746910938,15118107765960464233', cityhash.hash128('Hello', '12343,30293'), 'Hash128 for "Hello" with seed 12343,30293');
  147
+assertEqual({
  148
+        "low": {
  149
+            "low": 68277041,
  150
+            "high": 2127607426,
  151
+            "value": "9138004313465017137",
  152
+            "uint64": true
  153
+        },
  154
+        "high": {
  155
+            "low": 3936042248,
  156
+            "high": 2850538876,
  157
+            "value": "12242971252332641544",
  158
+            "uint64": true
  159
+        },
  160
+        "value": "9138004313465017137,12242971252332641544",
  161
+        "uint128": true
  162
+    }, cityhash.crc128('Hello'), 'Crc128 for "Hello"');
31 163
 
32  
-assertEqual('9138004313465017137,12242971252332641544', cityhash.crc128('Hello'), 'Crc128 for "Hello"');
33  
-assertEqual('15779891233746910938,15118107765960464233', cityhash.crc128('Hello', '12343,30293'), 'Crc128 for "Hello" with seed 12343,30293');
  164
+assertEqual({
  165
+        "low": {
  166
+            "low": 3184066266,
  167
+            "high": 3674042232,
  168
+            "value": "15779891233746910938",
  169
+            "uint64": true
  170
+        },
  171
+        "high": {
  172
+            "low": 4196783977,
  173
+            "high": 3519958761,
  174
+            "value": "15118107765960464233",
  175
+            "uint64": true
  176
+        },
  177
+        "value": "15779891233746910938,15118107765960464233",
  178
+        "uint128": true
  179
+    }, cityhash.crc128('Hello', '12343,30293'), 'Crc128 for "Hello" with seed 12343,30293');
34 180
 
35 181
 end();

0 notes on commit 5f90ec7

Please sign in to comment.
Something went wrong with that request. Please try again.