1 Support node 0.12, fixes #4, use require(buffer), fixes #2 · dcodeIO/node-memcpy@5bd6b5f · GitHub
Skip to content
This repository was archived by the owner on Jun 5, 2020. It is now read-only.

Commit 5bd6b5f

Browse files
committed
Support node 0.12, fixes #4, use require(buffer), fixes #2
1 parent f809cc4 commit 5bd6b5f

8 files changed

Lines changed: 182 additions & 177 deletions

File tree

README.md

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,17 @@ types can be ridiculously slow. This is where a node module like memcpy comes in
1313
1414
i memcpy.100k > cc Buffer -> Buffer: 22.756ms
1515
i memcpy.100k > cc Buffer -> ArrayBuffer: 23.861ms
16-
i memcpy.100k > cc Buffer -> Uint8Array: 22.953ms
1716
1817
i memcpy.100k > cc ArrayBuffer -> Buffer: 22.955ms
1918
i memcpy.100k > cc ArrayBuffer -> ArrayBuffer: 23.273ms
20-
i memcpy.100k > cc ArrayBuffer -> Uint8Array: 22.685ms
21-
22-
i memcpy.100k > cc Uint8Array -> Buffer: 23.472ms
23-
i memcpy.100k > cc Uint8Array -> ArrayBuffer: 22.975ms
24-
i memcpy.100k > cc Uint8Array -> Uint8Array: 22.953ms
2519
2620
// Native JS
2721
2822
i memcpy.100k > js Buffer -> Buffer: 21.617ms
2923
i memcpy.100k > js Buffer -> ArrayBuffer: 993.361ms
30-
i memcpy.100k > js Buffer -> Uint8Array: 410.010ms
3124
3225
i memcpy.100k > js ArrayBuffer -> Buffer: 940.273ms
3326
i memcpy.100k > js ArrayBuffer -> ArrayBuffer: 1626.182ms
34-
i memcpy.100k > js ArrayBuffer -> Uint8Array: 1084.790ms
35-
36-
i memcpy.100k > js Uint8Array -> Buffer: 386.218ms
37-
i memcpy.100k > js Uint8Array -> ArrayBuffer: 1107.530ms
38-
i memcpy.100k > js Uint8Array -> Uint8Array: 502.653ms
3927
```
4028

4129
API
@@ -44,9 +32,9 @@ API
4432

4533
| Argument | Type | Optional | Description
4634
|--------------|---------------------------|-----------|------------------------------------------------------------------
47-
| target | Buffer | ArrayBuffer | Uint8Array | | Target buffer to copy to
35+
| target | Buffer | ArrayBuffer | | Target buffer to copy to
4836
| targetStart | number | omittable | Target offset to begin copying to, defaults to `0`
49-
| source | Buffer | ArrayBuffer | Uint8Array | | Source buffer to copy from
37+
| source | Buffer | ArrayBuffer | | Source buffer to copy from
5038
| sourceStart | number | optional | Source offset to begin copying from, defaults to `0`
5139
| sourceEnd | number | optional | Source offset to end copying from, defaults ot `source.length`
5240
| **@returns** | number | | Number of bytes copied

binding.gyp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"target_name": "memcpy",
55
"sources": [ "src/memcpy.cc" ],
66
"include_dirs" : [
7-
"<!(node -e \"require('nan')\")"
7+
"<!(node -e \"require('nan')\")",
8+
"<!(node -e \"require('node-arraybuffer')\")"
89
]
910
}
1011
]

index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require("./src/memcpy.js");

package.json

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,41 @@
11
{
2-
"name": "memcpy",
3-
"version": "0.5.0",
4-
"author": "Daniel Wirtz <dcode@dcode.io>",
5-
"contributors": [
6-
"Denys Khanzhiyev <xdenser@gmail.com>"
7-
],
8-
"description": "Copies data between node Buffers and/or ArrayBuffers up to ~75 times faster than in pure JS.",
9-
"main": "src/memcpy.js",
10-
"repository": {
11-
"type": "git",
12-
"url": "https://github.com/dcodeIO/node-memcpy.git"
13-
},
14-
"bugs": {
15-
"url": "https://github.com/dcodeIO/node-memcpy/issues"
16-
},
17-
"keywords": [
18-
"array",
19-
"buffer",
20-
"arraybuffer",
21-
"typed array"
22-
],
23-
"dependencies": {
24-
"bindings": "~1.1",
25-
"nan": "~1.2.0"
26-
},
27-
"devDependencies": {
28-
"testjs": "latest"
29-
},
30-
"license": "Apache-2.0",
31-
"engines": {
32-
"node": ">=0.8"
33-
},
34-
"scripts": {
35-
"prepublish": "npm test",
36-
"test": "node node_modules/testjs/bin/testjs tests/suite.js",
37-
"make": "node-gyp configure build && npm test",
38-
"install": "node-gyp configure build"
39-
}
2+
"name": "memcpy",
3+
"version": "0.6.0",
4+
"author": "Daniel Wirtz <dcode@dcode.io>",
5+
"contributors": [
6+
"Denys Khanzhiyev <xdenser@gmail.com>"
7+
],
8+
"description": "Copies data between node Buffers and/or ArrayBuffers up to ~75 times faster than in pure JS.",
9+
"main": "src/memcpy.js",
10+
"repository": {
11+
"type": "git",
12+
"url": "https://github.com/dcodeIO/node-memcpy.git"
13+
},
14+
"bugs": {
15+
"url": "https://github.com/dcodeIO/node-memcpy/issues"
16+
},
17+
"keywords": [
18+
"array",
19+
"buffer",
20+
"arraybuffer",
21+
"typed array"
22+
],
23+
"dependencies": {
24+
"bindings": "~1.1",
25+
"nan": "~1.2.0",
26+
"node-arraybuffer": "^1.0.11"
27+
},
28+
"devDependencies": {
29+
"testjs": "latest"
30+
},
31+
"license": "Apache-2.0",
32+
"engines": {
33+
"node": ">=0.8 <=0.12"
34+
},
35+
"scripts": {
36+
"prepublish": "npm test",
37+
"test": "node node_modules/testjs/bin/testjs tests/suite.js",
38+
"make": "node-gyp configure build && npm test",
39+
"install": "node-gyp configure build"
40+
}
4041
}

src/memcpy.cc

Lines changed: 84 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,103 +16,145 @@
1616
#include <string.h>
1717
#include <node.h>
1818
#include <nan.h>
19+
#include <ArrayBuffer.h>
20+
#include "memcpy.h"
1921

2022
using namespace v8;
2123

2224
// Copies data between kExternalUnsignedByteArrays like node Buffers and ArrayBuffers.
2325
// memcpy(target[, targetStart], source[, sourceStart[, sourceEnd]]):bytesCopied
2426
NAN_METHOD(memcpy){
2527
NanScope();
28+
if (sizeof(unsigned char) != 1) {
29+
NanThrowError("sizeof(unsigned char) != 1");
30+
NanReturnUndefined();
31+
}
2632

27-
// Parse arguments
33+
unsigned char* targetData;
34+
size_t targetStart = 0,
35+
targetLength;
36+
37+
unsigned char* sourceData;
38+
size_t sourceStart = 0,
39+
sourceLength,
40+
sourceEnd;
41+
42+
// Requires at least two arguments: target and source
2843
if (args.Length() < 2) {
29-
NanThrowTypeError("Illegal number of arguments");
44+
NanThrowTypeError("illegal number of arguments");
3045
NanReturnUndefined();
3146
}
3247
int i = 0;
48+
49+
// Target must be an object
3350
if (!args[i]->IsObject()) {
34-
NanThrowTypeError("Illegal target: Not an object");
51+
NanThrowTypeError("illegal target: not an object");
3552
NanReturnUndefined();
3653
}
37-
Local<Object> target = args[i++]->ToObject();
38-
if (target->GetIndexedPropertiesExternalArrayDataType() != kExternalUnsignedByteArray) {
39-
NanThrowTypeError("Illegal target: Not a valid kExternalUnsignedByteArray");
54+
Local<Object> target = args[i]->ToObject();
55+
56+
// Target must reference an unsigned byte array (or be an ArrayBuffer)
57+
if (target->GetIndexedPropertiesExternalArrayDataType() == kExternalUnsignedByteArray) {
58+
targetData = static_cast<unsigned char*>(target->GetIndexedPropertiesExternalArrayData());
59+
targetLength = target->GetIndexedPropertiesExternalArrayDataLength();
60+
} else {
61+
#if NODE_MAJOR_VERSION > 0 || NODE_MINOR_VERSION >= 12
62+
if (!args[i]->IsArrayBuffer()) {
63+
NanThrowTypeError("illegal target: not an ArrayBuffer");
64+
NanReturnUndefined();
65+
}
66+
node::ArrayBuffer* ab = node::ArrayBuffer::New(args[i]);
67+
targetData = static_cast<unsigned char*>(ab->Data());
68+
targetLength = ab->ByteLength();
69+
#else
70+
NanThrowTypeError("illegal target: not a kExternalUnsignedByteArray");
4071
NanReturnUndefined();
72+
#endif
4173
}
42-
int targetStart = 0;
43-
int targetLength = target->GetIndexedPropertiesExternalArrayDataLength();
44-
if (args[i]->IsUint32()) {
74+
// If specified, targetStart must be an unsigned integer in [0,targetLength]
75+
if (args[++i]->IsUint32()) {
4576
targetStart = args[i++]->ToUint32()->Value();
4677
if (targetStart < 0 || targetStart > targetLength) {
47-
NanThrowTypeError("Illegal targetStart: Less than 0 or bigger than length");
78+
NanThrowRangeError("illegal targetStart: out of bounds");
4879
NanReturnUndefined();
4980
}
5081
}
82+
// Requires at least one additional argument: source
5183
if (i >= args.Length()) {
52-
NanThrowTypeError("Illegal number of arguments");
84+
NanThrowTypeError("illegal number of arguments");
5385
NanReturnUndefined();
5486
}
87+
// Source must be an object
5588
if (!args[i]->IsObject()) {
56-
NanThrowTypeError("Illegal source: Not an object");
89+
NanThrowTypeError("illegal source: not an object");
5790
NanReturnUndefined();
5891
}
59-
Local<Object> source = args[i++]->ToObject();
60-
if (source->GetIndexedPropertiesExternalArrayDataType() != kExternalUnsignedByteArray) {
61-
NanThrowTypeError("Illegal source: Not a valid kExternalUnsignedByteArray");
92+
Local<Object> source = args[i]->ToObject();
93+
94+
// Source must reference an unsigned byte array (or be an ArrayBuffer)
95+
if (source->GetIndexedPropertiesExternalArrayDataType() == kExternalUnsignedByteArray) {
96+
sourceData = static_cast<unsigned char*>(source->GetIndexedPropertiesExternalArrayData());
97+
sourceEnd = sourceLength = source->GetIndexedPropertiesExternalArrayDataLength();
98+
} else {
99+
#if NODE_MAJOR_VERSION > 0 || NODE_MINOR_VERSION >= 12
100+
if (!args[i]->IsArrayBuffer()) {
101+
NanThrowTypeError("illegal source: not an ArrayBuffer");
102+
NanReturnUndefined();
103+
}
104+
node::ArrayBuffer* ab = node::ArrayBuffer::New(args[i]);
105+
sourceData = static_cast<unsigned char*>(ab->Data());
106+
sourceEnd = sourceLength = ab->ByteLength();
107+
#else
108+
NanThrowTypeError("illegal target: not a kExternalUnsignedByteArray");
62109
NanReturnUndefined();
110+
#endif
63111
}
64-
int sourceStart = 0;
65-
int sourceLength = source->GetIndexedPropertiesExternalArrayDataLength();
66-
int sourceEnd = sourceLength;
67-
if (i < args.Length()) {
112+
// If specified, sourceStart must be an unsigned integer in [0,sourceLength]
113+
if (++i < args.Length()) {
68114
if (!args[i]->IsUint32()) {
69-
NanThrowTypeError("Illegal sourceStart: Not an uint32");
115+
NanThrowTypeError("illegal sourceStart: not an uint32");
70116
NanReturnUndefined();
71117
}
72118
sourceStart = args[i++]->ToUint32()->Value();
73119
if (sourceStart < 0 || sourceStart > sourceLength) {
74-
NanThrowTypeError("Illegal sourceStart: Less than 0 or bigger than length");
120+
NanThrowTypeError("illegal sourceStart: out of bounds");
75121
NanReturnUndefined();
76122
}
77123
}
124+
// If specified, sourceEnd must be an unsigned integer in [sourceStart,sourceLength]
78125
if (i < args.Length()) {
79126
if (!args[i]->IsUint32()) {
80-
NanThrowTypeError("Illegal sourceEnd: Not an uint32");
127+
NanThrowTypeError("illegal sourceEnd: not an uint32");
81128
NanReturnUndefined();
82129
}
83130
sourceEnd = args[i++]->ToUint32()->Value();
84131
if (sourceEnd < sourceStart || sourceEnd > sourceLength) {
85-
NanThrowTypeError("Illegal sourceEnd: Less than sourceStart or bigger than length");
132+
NanThrowTypeError("illegal sourceEnd: out of bounds");
86133
NanReturnUndefined();
87134
}
88135
}
89-
if (i /* still */ < args.Length()) {
90-
NanThrowTypeError("Illegal number of arguments");
136+
// Additional arguments are invalid
137+
if (i < args.Length()) {
138+
NanThrowTypeError("illegal number of arguments");
91139
NanReturnUndefined();
92140
}
93-
94-
// Perform sanity checks
95-
int len = sourceEnd - sourceStart;
96-
if (len == 0) {
97-
NanReturnUndefined();
141+
// Determine number of bytes to copy
142+
int length = sourceEnd - sourceStart;
143+
if (length == 0) {
144+
NanReturnValue(NanNew<Number>(length));
98145
}
99-
if (targetStart + len > targetLength) {
100-
NanThrowTypeError("Illegal source range: Target capacity overrun");
101-
NanReturnUndefined();
102-
}
103-
if (sizeof(unsigned char) != 1) {
104-
NanThrowTypeError("sizeof(unsigned char) != 1");
146+
// Perform sanity checks
147+
if (targetStart + length > targetLength) {
148+
NanThrowTypeError("illegal source range: target capacity overrun");
105149
NanReturnUndefined();
106150
}
107-
108151
// Do the thing (memmove to be compatible with native Buffer#copy)
109152
memmove(
110-
static_cast<unsigned char*>(target->GetIndexedPropertiesExternalArrayData()) + targetStart,
111-
static_cast<unsigned char*>(source->GetIndexedPropertiesExternalArrayData()) + sourceStart,
112-
len
153+
targetData + targetStart,
154+
sourceData + sourceStart,
155+
length
113156
);
114-
115-
NanReturnValue(NanNew<Number>(len));
157+
NanReturnValue(NanNew<Number>(length));
116158
}
117159

118160
void init(Handle<Object> exports) {

src/memcpy.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#ifndef NODE_MEMCPY_H_
2+
#define NODE_MEMCPY_H_
3+
4+
#endif

0 commit comments

Comments
 (0)