Skip to content

Commit

Permalink
initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
fbzhong committed Apr 13, 2011
0 parents commit 26bd464
Show file tree
Hide file tree
Showing 9 changed files with 222 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
@@ -0,0 +1,4 @@
.DS_Store
.lock-wscript
build

3 changes: 3 additions & 0 deletions .gitmodules
@@ -0,0 +1,3 @@
[submodule "cityhash"]
path = cityhash
url = https://github.com/hsaito/CityHash.git
10 changes: 10 additions & 0 deletions Makefile
@@ -0,0 +1,10 @@
all: clean build test

build:
node-waf configure build

clean:
@rm -rf ./build

test:
node test.js
133 changes: 133 additions & 0 deletions binding.cc
@@ -0,0 +1,133 @@
#include <v8.h>
#include <string.h>
#include <sstream>
#include "cityhash/src/city.h"

#define MAX_64_HASH_LEN 21
#define MAX_128_HASH_LEN MAX_64_HASH_LEN*2

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

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

return String::New(buf);
}

uint64
to_uint64(const char* data, size_t len) {
std::stringstream str;
str.write(data, len);

uint64 v;
str >> v;
return v;
}

void
to_uint128(uint128* v, const char* data, size_t len) {
std::stringstream str;
uint64 i;

char* sep = strchr(data, (int)',');
if(sep == NULL) {
str.write(data, len);
str >> i;
v->first = i;
v->second = 0;

} else {
int pos = (int)(sep - data);
str.write(data, pos);
str >> i;
v->first = i;

str.clear();
str.write(sep+1, len - pos - 1);
str >> i;
v->second = i;
}
}

Handle<Value>
node_CityHash64(const Arguments& args) {
HandleScope scope;

int args_len = args.Length();
if(args_len == 0 || args_len > 3) {
return ThrowException(String::New("Invalid arguments."));
}

String::Utf8Value data(args[0]->ToString());
const char* str = *data;
size_t len = data.length();

uint64 hash;

if(args_len == 1) {
hash = CityHash64(str, len);
} else if(args_len == 2) {
String::AsciiValue seedString(args[1]->ToString());
uint64 seed = to_uint64(*seedString, seedString.length());

hash = CityHash64WithSeed(str, len, seed);
} else if(args_len == 3) {
String::AsciiValue seed0String(args[1]->ToString());
String::AsciiValue seed1String(args[2]->ToString());
uint64 seed0 = to_uint64(*seed0String, seed0String.length());
uint64 seed1 = to_uint64(*seed1String, seed1String.length());

hash = CityHash64WithSeeds(str, len, seed0, seed1);
}

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

Handle<Value>
node_CityHash128(const Arguments& args) {
HandleScope scope;

int args_len = args.Length();
if(args_len == 0 || args_len > 2) {
return ThrowException(String::New("Invalid arguments."));
}

String::Utf8Value data(args[0]->ToString());
const char* str = *data;
size_t len = data.length();

uint128 hash;

if(args.Length() == 2) {
uint128 seed;
String::AsciiValue seedString(args[1]->ToString());
to_uint128(&seed, *seedString, seedString.length());

hash = CityHash128WithSeed(str, len, seed);
} else {
hash = CityHash128(str, len);
}

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

extern "C" void
init (Handle<Object> target) {
HandleScope scope;
target->Set(String::New("hash64"), FunctionTemplate::New(node_CityHash64)->GetFunction());
target->Set(String::New("hash128"), FunctionTemplate::New(node_CityHash128)->GetFunction());
}
1 change: 1 addition & 0 deletions cityhash
Submodule cityhash added at 2e507b
5 changes: 5 additions & 0 deletions install.sh
@@ -0,0 +1,5 @@
#!/bin/sh

node-waf configure
node-waf build

19 changes: 19 additions & 0 deletions package.json
@@ -0,0 +1,19 @@
{
"name": "node-cityhash"
,"version": "0.0.1"
,"main": "./build/default/cityhash"
,"description": "NodeJS binding for Google CityHash."
,"scripts" : { "install" : "./install.sh" }
,"dependencies": []
,"repositories": [{ "type": "git"
,"path": "git://github.com/fbzhong/node-cityhash.git"
}]
,"homepage": "http://github.com/fbzhong/node-cityhash"
,"bugs": "http://github.com/fbzhong/node-cityhash/issues"
,"maintainers": [{ "name": "Robin"
,"email": "fbzhong@gmail.com"
,"web": "http://github.com/fbzhong/"
}]
,"licenses": [{ "type": "MIT" }]
,"engine": "node"
}
22 changes: 22 additions & 0 deletions test.js
@@ -0,0 +1,22 @@
var cityhash = require('./build/default/cityhash.node');

function assertEqual(expected, actual, message) {
if(expected != actual) {
if(message) {
message += '. ';
} else {
message = '';
}

console.log('[Error]' + message + 'Expected ' + expected + ' , but actual is ' + actual);
}
}

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('11793567364161249803,13788582196852422552', cityhash.hash128('Hello'), 'Hash128 for "Hello"');
assertEqual('14316895837725277120,16588029950142229031', cityhash.hash128('hello'), 'Hash128 for "hello"');
assertEqual('9958601979657309277,6783721701693091028', cityhash.hash128('Hello', '12343,30293'), 'Hash128 for "Hello" with seed 12343,30293');
25 changes: 25 additions & 0 deletions wscript
@@ -0,0 +1,25 @@
srcdir = "."
blddir = "build"
VERSION = "0.0.1"

def set_options(opt):
opt.tool_options("compiler_cxx")
opt.tool_options("compiler_cc")

def configure(conf):
conf.check_tool("compiler_cxx")
conf.check_tool("compiler_cc")
conf.check_tool("node_addon")
conf.env.append_value('CCFLAGS', ['-O3'])

def build(bld):
libcity = bld.new_task_gen("cxx", "shlib")
libcity.source = "cityhash/src/city.cc"
libcity.name = "libcity"
libcity.target = "libcity"

obj = bld.new_task_gen("cxx", "shlib", "node_addon")
obj.target = "cityhash"
obj.source = "binding.cc"
obj.includes = "libcity"
obj.add_objects = "libcity"

0 comments on commit 26bd464

Please sign in to comment.