[Pkg-javascript-commits] [node-leveldown] 107/492: allow JS Strings through to native layer

Andrew Kelley andrewrk-guest at moszumanska.debian.org
Sun Jul 6 17:13:49 UTC 2014


This is an automated email from the git hooks/post-receive script.

andrewrk-guest pushed a commit to annotated tag rocksdb-0.10.1
in repository node-leveldown.

commit bedf32e8093637335e983c0093aac22d962b13da
Author: Rod Vagg <rod at vagg.org>
Date:   Sat Dec 15 17:02:15 2012 +1100

    allow JS Strings through to native layer
    
    major speed boost here for all utf8 databases
---
 .jshintrc            |   3 +-
 lib/levelup.js       |  13 +++---
 lib/util.js          |   4 +-
 src/batch.h          |  12 +++---
 src/database.cc      | 110 +++++++++++++--------------------------------------
 src/database_async.h |  14 +++----
 src/iterator.cc      |  16 +++++---
 src/levelup.h        |  32 +++++++++++++++
 8 files changed, 92 insertions(+), 112 deletions(-)

diff --git a/.jshintrc b/.jshintrc
index 6fac775..2685324 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -25,5 +25,6 @@
   , "proto": true
   , "expr": true
   , "es5": true
+  , "esnext": true
   , "strict": false
-}
+}
\ No newline at end of file
diff --git a/lib/levelup.js b/lib/levelup.js
index 7ddabfb..9f794dc 100644
--- a/lib/levelup.js
+++ b/lib/levelup.js
@@ -26,15 +26,13 @@ var bridge       = require('bindings')('levelup.node')
     }('hex utf8 utf-8 ascii binary base64 ucs2 ucs-2 utf16le utf-16le'.split(' ')))
 
   , getOptions = function (options, globalOptions) {
-      if (typeof options == 'string') // just an encoding
-        options = extend({}, encodingOpts[options] || encodingOpts[defaultOptions.encoding])
-      return extend(extend({}, globalOptions), options)
+      return typeof options == 'string' // just an encoding
+        ? options = extend({}, encodingOpts[options] || encodingOpts[defaultOptions.encoding])
+        : extend(extend({}, globalOptions), options)
     }
 
   , getCallback = function (options_, callback_) {
-      if (typeof options_ == 'function')
-        return options_
-      return callback_
+      return typeof options_ == 'function' ? options_ : callback_
     }
 
 // Possible this._status values:
@@ -172,8 +170,7 @@ LevelUP.prototype = {
             this.emit('error', err)
           } else {
             this.emit('put', key_, value_)
-            // Node 0.9 bug, do this in current tick and a copy() operation will core dump
-            callback && process.nextTick(callback.bind(null, null, key, value))
+            callback && callback(null, key, value)
           }
         }.bind(this))
       } else {
diff --git a/lib/util.js b/lib/util.js
index 6c8550b..c34a084 100644
--- a/lib/util.js
+++ b/lib/util.js
@@ -5,7 +5,9 @@ var toBuffer = function (data, encoding) {
         data = JSON.stringify(data)
         encoding = 'utf8'
       }
-      return data === undefined || data === null || Buffer.isBuffer(data) ? data : new Buffer(String(data), encoding)
+      if (data === undefined || data === null || Buffer.isBuffer(data)) return data
+      data = String(data)
+      return encoding == 'utf8' ? data : new Buffer(data, encoding)
     }
 
   , toEncoding = function (buffer, encoding) {
diff --git a/src/batch.h b/src/batch.h
index ac95d38..a1a6380 100644
--- a/src/batch.h
+++ b/src/batch.h
@@ -19,7 +19,7 @@ class BatchDelete : public BatchOp {
 public:
   BatchDelete (
       Slice key
-    , Persistent<Object> keyPtr
+    , Persistent<Value> keyPtr
   ) : key(key)
     , keyPtr(keyPtr)
   {};
@@ -28,7 +28,7 @@ public:
 
 private:
   Slice key;
-  Persistent<Object> keyPtr;
+  Persistent<Value> keyPtr;
 };
 
 class BatchWrite : public BatchOp {
@@ -36,8 +36,8 @@ public:
   BatchWrite (
       Slice key
     , Slice value
-    , Persistent<Object> keyPtr
-    , Persistent<Object> valuePtr
+    , Persistent<Value> keyPtr
+    , Persistent<Value> valuePtr
   ) : key(key)
     , keyPtr(keyPtr)
     , value(value)
@@ -48,9 +48,9 @@ public:
 
 private:
   Slice key;
-  Persistent<Object> keyPtr;
+  Persistent<Value> keyPtr;
   Slice value;
-  Persistent<Object> valuePtr;
+  Persistent<Value> valuePtr;
 };
 
 #endif
diff --git a/src/database.cc b/src/database.cc
index 5df7d1c..ae69ce6 100644
--- a/src/database.cc
+++ b/src/database.cc
@@ -153,42 +153,15 @@ Handle<Value> Database::Put (const Arguments& args) {
   Database* database = ObjectWrap::Unwrap<Database>(args.This());
   Persistent<Function> callback = Persistent<Function>::New(Local<Function>::Cast(args[3]));
 
-  if (args[0]->IsNull() || args[0]->IsUndefined()) {
-    Local<Value> argv[] = {
-      Local<Value>::New(Exception::Error(String::New("Key cannot be `null` or `undefined`")))
-    };
-    RunCallback(callback, argv, 1);
-    return Undefined();
-  }
-
-  if (!Buffer::HasInstance(args[0])) {
-    Local<Value> argv[] = {
-      Local<Value>::New(Exception::Error(String::New("Key must be an instance of Buffer")))
-    };
-    RunCallback(callback, argv, 1);
-    return Undefined();
-  }
-
-  if (args[1]->IsNull() || args[1]->IsUndefined()) {
-    Local<Value> argv[] = {
-      Local<Value>::New(Exception::Error(String::New("Value cannot be `null` or `undefined`")))
-    };
-    RunCallback(callback, argv, 1);
-    return Undefined();
-  }
-
-  if (!Buffer::HasInstance(args[1])) {
-    Local<Value> argv[] = {
-      Local<Value>::New(Exception::Error(String::New("Value must be an instance of Buffer")))
-    };
-    RunCallback(callback, argv, 1);
-    return Undefined();
-  }
-
-  Persistent<Object> keyBuffer = Persistent<Object>::New(args[0]->ToObject());
-  Slice key(Buffer::Data(keyBuffer), Buffer::Length(keyBuffer));
-  Persistent<Object> valueBuffer = Persistent<Object>::New(args[1]->ToObject());
-  Slice value(Buffer::Data(valueBuffer), Buffer::Length(valueBuffer));
+  CB_ERR_IF_NULL_OR_UNDEFINED(0, "Key")
+  CB_ERR_IF_NOT_BUFFER_OR_STRING(0, "Key")
+  CB_ERR_IF_NULL_OR_UNDEFINED(1, "Value")
+  CB_ERR_IF_NOT_BUFFER_OR_STRING(1, "Value")
+
+  Persistent<Value> keyBuffer = Persistent<Value>::New(args[0]);
+  STRING_OR_BUFFER_TO_SLICE(key, keyBuffer)
+  Persistent<Value> valueBuffer = Persistent<Value>::New(args[1]);
+  STRING_OR_BUFFER_TO_SLICE(value, valueBuffer)
   Local<Object> optionsObj = Local<Object>::Cast(args[2]);
   bool sync = optionsObj->Has(option_sync) && optionsObj->Get(option_sync)->BooleanValue();
 
@@ -212,25 +185,11 @@ Handle<Value> Database::Get (const Arguments& args) {
   Database* database = ObjectWrap::Unwrap<Database>(args.This());
   Persistent<Function> callback = Persistent<Function>::New(Local<Function>::Cast(args[2]));
 
-  if (args[0]->IsNull() || args[0]->IsUndefined()) {
-    Local<Value> argv[] = {
-      Local<Value>::New(Exception::Error(String::New("Key cannot be `null` or `undefined`")))
-    };
-    RunCallback(callback, argv, 1);
-    return Undefined();
-  }
-
-  if (!Buffer::HasInstance(args[0])) {
-    Local<Value> argv[] = {
-      Local<Value>::New(Exception::Error(String::New("Key must be an instance of Buffer")))
-    };
-    RunCallback(callback, argv, 1);
-    return Undefined();
-  }
+  CB_ERR_IF_NULL_OR_UNDEFINED(0, "Key")
+  CB_ERR_IF_NOT_BUFFER_OR_STRING(0, "Key")
 
-  Persistent<Object> keyBuffer = Persistent<Object>::New(args[0]->ToObject());
-  Slice key(Buffer::Data(keyBuffer), Buffer::Length(keyBuffer));
-  //Local<Object> optionsObj = Local<Object>::Cast(args[1]);
+  Persistent<Value> keyBuffer = Persistent<Value>::New(args[0]);
+  STRING_OR_BUFFER_TO_SLICE(key, keyBuffer)
 
   ReadWorker* worker = new ReadWorker(
       database
@@ -249,24 +208,11 @@ Handle<Value> Database::Delete (const Arguments& args) {
   Database* database = ObjectWrap::Unwrap<Database>(args.This());
   Persistent<Function> callback = Persistent<Function>::New(Local<Function>::Cast(args[2]));
 
-  if (args[0]->IsNull() || args[0]->IsUndefined()) {
-    Local<Value> argv[] = {
-      Local<Value>::New(Exception::Error(String::New("Key cannot be `null` or `undefined`")))
-    };
-    RunCallback(callback, argv, 1);
-    return Undefined();
-  }
+  CB_ERR_IF_NULL_OR_UNDEFINED(0, "Key")
+  CB_ERR_IF_NOT_BUFFER_OR_STRING(0, "Key")
 
-  if (!Buffer::HasInstance(args[0])) {
-    Local<Value> argv[] = {
-      Local<Value>::New(Exception::Error(String::New("Key must be an instance of Buffer")))
-    };
-    RunCallback(callback, argv, 1);
-    return Undefined();
-  }
-
-  Persistent<Object> keyBuffer = Persistent<Object>::New(args[0]->ToObject());
-  Slice key(Buffer::Data(keyBuffer), Buffer::Length(keyBuffer));
+  Persistent<Value> keyBuffer = Persistent<Value>::New(args[0]);
+  STRING_OR_BUFFER_TO_SLICE(key, keyBuffer)
   Local<Object> optionsObj = Local<Object>::Cast(args[1]);
   bool sync = optionsObj->Has(option_sync) && optionsObj->Get(option_sync)->BooleanValue();
 
@@ -297,26 +243,24 @@ Handle<Value> Database::Batch (const Arguments& args) {
       continue;
 
     Local<Object> obj = Local<Object>::Cast(array->Get(i));
-    if (!obj->Has(str_type) || !obj->Has(str_key))
+    if (!obj->Has(str_type) && !obj->Has(str_key))
       continue;
 
-    if (!obj->Get(str_key)->IsObject())
-      continue;
-    Local<Object> keyBuffer = obj->Get(str_key)->ToObject();
-    if (!Buffer::HasInstance(keyBuffer))
+    Local<Value> keyBuffer = obj->Get(str_key);
+    if (!keyBuffer->IsString() && !Buffer::HasInstance(keyBuffer))
       continue;
-    Slice key(Buffer::Data(keyBuffer), Buffer::Length(keyBuffer));
+    STRING_OR_BUFFER_TO_SLICE(key, keyBuffer)
 
     if (obj->Get(str_type)->StrictEquals(str_del)) {
-      operations->push_back(new BatchDelete(key, Persistent<Object>::New(keyBuffer)));
+      operations->push_back(new BatchDelete(key, Persistent<Value>::New(keyBuffer)));
     } else if (obj->Get(str_type)->StrictEquals(str_put) && obj->Has(str_value)) {
-      if (!obj->Get(str_value)->IsObject())
+      if (!obj->Has(str_value))
         continue;
-      Local<Object> valueBuffer = obj->Get(str_value)->ToObject();
-      if (!Buffer::HasInstance(valueBuffer))
+      Local<Value> valueBuffer = obj->Get(str_value);
+      if (!valueBuffer->IsString() && !Buffer::HasInstance(valueBuffer))
         continue;
-      Slice value(Buffer::Data(valueBuffer), Buffer::Length(valueBuffer));
-      operations->push_back(new BatchWrite(key, value, Persistent<Object>::New(keyBuffer), Persistent<Object>::New(valueBuffer)));
+      STRING_OR_BUFFER_TO_SLICE(value, valueBuffer)
+      operations->push_back(new BatchWrite(key, value, Persistent<Value>::New(keyBuffer), Persistent<Value>::New(valueBuffer)));
     }
   }
 
diff --git a/src/database_async.h b/src/database_async.h
index 62508df..5f22116 100644
--- a/src/database_async.h
+++ b/src/database_async.h
@@ -58,7 +58,7 @@ public:
       Database* database
     , Persistent<Function> callback
     , Slice key
-    , Persistent<Object> keyPtr
+    , Persistent<Value> keyPtr
   ) : AsyncWorker(database, callback)
     , key(key)
     , keyPtr(keyPtr)
@@ -69,7 +69,7 @@ public:
 
 protected:
   Slice key;
-  Persistent<Object> keyPtr;
+  Persistent<Value> keyPtr;
 };
 
 class ReadWorker : public IOWorker {
@@ -78,7 +78,7 @@ public:
       Database* database
     , Persistent<Function> callback
     , Slice key
-    , Persistent<Object> keyPtr
+    , Persistent<Value> keyPtr
   ) : IOWorker(database, callback, key, keyPtr)
   {
     options = new ReadOptions();
@@ -100,7 +100,7 @@ public:
     , Persistent<Function> callback
     , Slice key
     , bool sync
-    , Persistent<Object> keyPtr
+    , Persistent<Value> keyPtr
   ) : IOWorker(database, callback, key, keyPtr)
   {
     options = new WriteOptions();
@@ -122,8 +122,8 @@ public:
     , Slice key
     , Slice value
     , bool sync
-    , Persistent<Object> keyPtr
-    , Persistent<Object> valuePtr
+    , Persistent<Value> keyPtr
+    , Persistent<Value> valuePtr
   ) : DeleteWorker(database, callback, key, sync, keyPtr)
     , value(value)
     , valuePtr(valuePtr)
@@ -134,7 +134,7 @@ public:
 
 private:
   Slice value;
-  Persistent<Object> valuePtr;
+  Persistent<Value> valuePtr;
 };
 
 class BatchWorker : public AsyncWorker {
diff --git a/src/iterator.cc b/src/iterator.cc
index f1cf20b..5dcd002 100644
--- a/src/iterator.cc
+++ b/src/iterator.cc
@@ -120,14 +120,18 @@ Handle<Value> levelup::Iterator::New (const Arguments& args) {
 
   Database* database = ObjectWrap::Unwrap<Database>(args[0]->ToObject());
   Slice* start = NULL;
-  if (args[1]->ToObject()->Has(option_start) && Buffer::HasInstance(args[1]->ToObject()->Get(option_start))) {
-    Local<Object> startBuffer = Local<Object>::New(args[1]->ToObject()->Get(option_start)->ToObject());
-    start = new Slice(Buffer::Data(startBuffer), Buffer::Length(startBuffer));
+  if (args[1]->ToObject()->Has(option_start)
+      && (Buffer::HasInstance(args[1]->ToObject()->Get(option_start)) || args[1]->ToObject()->Get(option_start)->IsString())) {
+    Local<Value> startBuffer = Local<Value>::New(args[1]->ToObject()->Get(option_start));
+    STRING_OR_BUFFER_TO_SLICE(_start, startBuffer)
+    start = new Slice(_start.data(), _start.size());
   }
   string* end = NULL;
-  if (args[1]->ToObject()->Has(option_end) && Buffer::HasInstance(args[1]->ToObject()->Get(option_end))) {
-    Local<Object> endBuffer = Local<Object>::New(args[1]->ToObject()->Get(option_end)->ToObject());
-    end = new string(Buffer::Data(endBuffer), Buffer::Length(endBuffer));
+  if (args[1]->ToObject()->Has(option_end)
+      && (Buffer::HasInstance(args[1]->ToObject()->Get(option_end)) || args[1]->ToObject()->Get(option_end)->IsString())) {
+    Local<Value> endBuffer = Local<Value>::New(args[1]->ToObject()->Get(option_end));
+    STRING_OR_BUFFER_TO_SLICE(_end, endBuffer)
+    end = new string(_end.data(), _end.size());
   }
   bool reverse = false;
   if (args[1]->ToObject()->Has(option_reverse)) {
diff --git a/src/levelup.h b/src/levelup.h
index cdb64de..feabc4b 100644
--- a/src/levelup.h
+++ b/src/levelup.h
@@ -12,6 +12,38 @@
 #define LU_V8_METHOD(name) \
   static v8::Handle<v8::Value> name (const v8::Arguments& args);
 
+#define CB_ERR_IF_NULL_OR_UNDEFINED(index, name) \
+  if (args[index]->IsNull() || args[index]->IsUndefined()) { \
+    Local<Value> argv[] = { \
+      Local<Value>::New(Exception::Error(String::New("#name cannot be `null` or `undefined`"))) \
+    }; \
+    RunCallback(callback, argv, 1); \
+    return Undefined(); \
+  }
+
+#define CB_ERR_IF_NOT_BUFFER_OR_STRING(index, name) \
+  if (!args[index]->IsString() && !Buffer::HasInstance(args[index])) { \
+    Local<Value> argv[] = { \
+      Local<Value>::New(Exception::Error(String::New("name must be a Buffer or a String"))) \
+    }; \
+    RunCallback(callback, argv, 1); \
+    return Undefined(); \
+  }
+
+#define STRING_OR_BUFFER_TO_SLICE(to, from) \
+  size_t to ## Sz_; \
+  char* to ## Ch_; \
+  if (from->IsString()) { \
+    to ## Sz_ = from->ToString()->Utf8Length(); \
+    to ## Ch_ = new char[to ## Sz_]; \
+    from->ToString()->WriteUtf8(to ## Ch_, -1, NULL, String::NO_NULL_TERMINATION); \
+  } else { \
+    assert(Buffer::HasInstance(from->ToObject())); \
+    to ## Sz_ = Buffer::Length(from->ToObject()); \
+    to ## Ch_ = Buffer::Data(from->ToObject()); \
+  } \
+  Slice to(to ## Ch_, to ## Sz_);
+
 const char* ToCString(const v8::String::Utf8Value& value);
 const char* ToCString(const v8::String::AsciiValue& value);
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-leveldown.git



More information about the Pkg-javascript-commits mailing list