Skip to content
This repository was archived by the owner on Jun 5, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
"targets": [
{
"target_name": "memcpy",
"sources": [ "src/memcpy.cc" ]
"sources": [ "src/memcpy.cc" ],
"include_dirs" : [
"<!(node -e \"require('nan')\")"
]
}
]
}
66 changes: 36 additions & 30 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,31 +1,37 @@
{
"name": "memcpy",
"version": "0.4.0",
"author": "Daniel Wirtz <dcode@dcode.io>",
"description": "Copies data between node Buffers and/or ArrayBuffers up to ~75 times faster than in pure JS.",
"main": "src/memcpy.js",
"repository": {
"type": "git",
"url": "https://github.com/dcodeIO/node-memcpy.git"
},
"bugs": {
"url": "https://github.com/dcodeIO/node-memcpy/issues"
},
"keywords": ["array", "buffer", "arraybuffer", "typed array"],
"dependencies": {
"bindings": "~1.1"
},
"devDependencies": {
"testjs": "latest"
},
"license": "Apache-2.0",
"engines": {
"node": ">=0.8"
},
"scripts": {
"prepublish": "npm test",
"test": "node node_modules/testjs/bin/testjs tests/suite.js",
"make": "node-gyp configure build && npm test",
"install": "node-gyp configure build"
}
}
"name": "memcpy",
"version": "0.4.0",
"author": "Daniel Wirtz <dcode@dcode.io>",
"description": "Copies data between node Buffers and/or ArrayBuffers up to ~75 times faster than in pure JS.",
"main": "src/memcpy.js",
"repository": {
"type": "git",
"url": "https://github.com/dcodeIO/node-memcpy.git"
},
"bugs": {
"url": "https://github.com/dcodeIO/node-memcpy/issues"
},
"keywords": [
"array",
"buffer",
"arraybuffer",
"typed array"
],
"dependencies": {
"bindings": "~1.1",
"nan": "~1.2.0"
},
"devDependencies": {
"testjs": "latest"
},
"license": "Apache-2.0",
"engines": {
"node": ">=0.8"
},
"scripts": {
"prepublish": "npm test",
"test": "node node_modules/testjs/bin/testjs tests/suite.js",
"make": "node-gyp configure build && npm test",
"install": "node-gyp configure build"
}
}
68 changes: 35 additions & 33 deletions src/memcpy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,94 +13,96 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <string.h>
#include <node.h>
#include <nan.h>

using namespace v8;

// Copies data between kExternalUnsignedByteArrays like node Buffers and ArrayBuffers.
// memcpy(target[, targetStart], source[, sourceStart[, sourceEnd]]):bytesCopied
Handle<Value> memcpy(const Arguments& args) {
HandleScope scope;
NAN_METHOD(memcpy){
NanScope();

// Parse arguments
if (args.Length() < 2) {
ThrowException(Exception::TypeError(String::New("Illegal number of arguments")));
return scope.Close(Undefined());
NanThrowTypeError("Illegal number of arguments");
NanReturnUndefined();
}
int i = 0;
if (!args[i]->IsObject()) {
ThrowException(Exception::TypeError(String::New("Illegal target: Not an object")));
return scope.Close(Undefined());
NanThrowTypeError("Illegal target: Not an object");
NanReturnUndefined();
}
Local<Object> target = args[i++]->ToObject();
if (target->GetIndexedPropertiesExternalArrayDataType() != kExternalUnsignedByteArray) {
ThrowException(Exception::TypeError(String::New("Illegal target: Not a valid kExternalUnsignedByteArray")));
return scope.Close(Undefined());
NanThrowTypeError("Illegal target: Not a valid kExternalUnsignedByteArray");
NanReturnUndefined();
}
int targetStart = 0;
int targetLength = target->GetIndexedPropertiesExternalArrayDataLength();
if (args[i]->IsUint32()) {
targetStart = args[i++]->ToUint32()->Value();
if (targetStart < 0 || targetStart > targetLength) {
ThrowException(Exception::TypeError(String::New("Illegal targetStart: Less than 0 or bigger than length")));
return scope.Close(Undefined());
NanThrowTypeError("Illegal targetStart: Less than 0 or bigger than length");
NanReturnUndefined();
}
}
if (i >= args.Length()) {
ThrowException(Exception::TypeError(String::New("Illegal number of arguments")));
return scope.Close(Undefined());
NanThrowTypeError("Illegal number of arguments");
NanReturnUndefined();
}
if (!args[i]->IsObject()) {
ThrowException(Exception::TypeError(String::New("Illegal source: Not an object")));
return scope.Close(Undefined());
NanThrowTypeError("Illegal source: Not an object");
NanReturnUndefined();
}
Local<Object> source = args[i++]->ToObject();
if (source->GetIndexedPropertiesExternalArrayDataType() != kExternalUnsignedByteArray) {
ThrowException(Exception::TypeError(String::New("Illegal source: Not a valid kExternalUnsignedByteArray")));
return scope.Close(Undefined());
NanThrowTypeError("Illegal source: Not a valid kExternalUnsignedByteArray");
NanReturnUndefined();
}
int sourceStart = 0;
int sourceLength = source->GetIndexedPropertiesExternalArrayDataLength();
int sourceEnd = sourceLength;
if (i < args.Length()) {
if (!args[i]->IsUint32()) {
ThrowException(Exception::TypeError(String::New("Illegal sourceStart: Not an uint32")));
return scope.Close(Undefined());
NanThrowTypeError("Illegal sourceStart: Not an uint32");
NanReturnUndefined();
}
sourceStart = args[i++]->ToUint32()->Value();
if (sourceStart < 0 || sourceStart > sourceLength) {
ThrowException(Exception::TypeError(String::New("Illegal sourceStart: Less than 0 or bigger than length")));
return scope.Close(Undefined());
NanThrowTypeError("Illegal sourceStart: Less than 0 or bigger than length");
NanReturnUndefined();
}
}
if (i < args.Length()) {
if (!args[i]->IsUint32()) {
ThrowException(Exception::TypeError(String::New("Illegal sourceEnd: Not an uint32")));
return scope.Close(Undefined());
NanThrowTypeError("Illegal sourceEnd: Not an uint32");
NanReturnUndefined();
}
sourceEnd = args[i++]->ToUint32()->Value();
if (sourceEnd < sourceStart || sourceEnd > sourceLength) {
ThrowException(Exception::TypeError(String::New("Illegal sourceEnd: Less than sourceStart or bigger than length")));
return scope.Close(Undefined());
NanThrowTypeError("Illegal sourceEnd: Less than sourceStart or bigger than length");
NanReturnUndefined();
}
}
if (i /* still */ < args.Length()) {
ThrowException(Exception::TypeError(String::New("Illegal number of arguments")));
return scope.Close(Undefined());
NanThrowTypeError("Illegal number of arguments");
NanReturnUndefined();
}

// Perform sanity checks
int len = sourceEnd - sourceStart;
if (len == 0) {
return scope.Close(Undefined()); // Nothing to copy
NanReturnUndefined();
}
if (targetStart + len > targetLength) {
ThrowException(Exception::TypeError(String::New("Illegal source range: Target capacity overrun")));
return scope.Close(Undefined());
NanThrowTypeError("Illegal source range: Target capacity overrun");
NanReturnUndefined();
}
if (sizeof(unsigned char) != 1) {
ThrowException(Exception::TypeError(String::New("sizeof(unsigned char) != 1")));
return scope.Close(Undefined());
NanThrowTypeError("sizeof(unsigned char) != 1");
NanReturnUndefined();
}

// Do the thing (memmove to be compatible with native Buffer#copy)
Expand All @@ -110,11 +112,11 @@ Handle<Value> memcpy(const Arguments& args) {
len
);

return scope.Close(Number::New(len));
NanReturnValue(NanNew<Number>(len));
}

void init(Handle<Object> exports) {
exports->Set(String::NewSymbol("memcpy"), FunctionTemplate::New(memcpy)->GetFunction());
exports->Set(NanNew<String>("memcpy"), NanNew<FunctionTemplate>(memcpy)->GetFunction());
}

NODE_MODULE(memcpy, init);