Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding a feature to create an external ArrayBuffer from given address… #67

Open
wants to merge 1 commit into
base: latest
Choose a base branch
from
Open
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
40 changes: 40 additions & 0 deletions src/binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,45 @@ Value ReadPointer(const CallbackInfo& args) {
return WrapPointer(env, val, size);
}

/**
* Creates an ArrayBuffer from the given address without allocating new memory,
* using napi_create_external_arraybuffer.
*
* args[0] - Number/String - the memory address
* args[1] - Number - the length in bytes of the returned ArrayBuffer instance
*/

Value ReadExternalArrayBuffer(const CallbackInfo& args) {
Env env = args.Env();
Value in = args[0];
int64_t address;
if (in.IsNumber()) {
address = in.As<Number>();
} else if (in.IsString()) {
char* endptr;
char* str;
int base = 0;
std::string _str = in.As<String>();
str = &_str[0];

errno = 0; /* To distinguish success/failure after call */
address = strtoll(str, &endptr, base);

if (endptr == str) {
throw TypeError::New(env, "readExternalArrayBuffer: no digits we found in input String");
} else if (errno == ERANGE && (address == INT64_MAX || address == INT64_MIN)) {
throw TypeError::New(env, "readExternalArrayBuffer: input String numerical value out of range");
} else if (errno != 0 && address == 0) {
char errmsg[200];
snprintf(errmsg, sizeof(errmsg), "readExternalArrayBuffer: %s", strerror(errno));
throw TypeError::New(env, errmsg);
}
}
int64_t length = args[1].ToNumber();

return ArrayBuffer::New(env, (void*) address, (size_t) length);
}

/**
* Writes the memory address of the "input" buffer (and optional offset) to the
* specified "buf" buffer and offset. Essentially making "buf" hold a reference
Expand Down Expand Up @@ -699,6 +738,7 @@ Object Init(Env env, Object exports) {
exports["readCString"] = Function::New(env, ReadCString);
exports["_reinterpret"] = Function::New(env, ReinterpretBuffer);
exports["_reinterpretUntilZeros"] = Function::New(env, ReinterpretBufferUntilZeros);
exports["readExternalArrayBuffer"] = Function::New(env, ReadExternalArrayBuffer);
return exports;
}

Expand Down
35 changes: 35 additions & 0 deletions test/external_arraybuffer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use strict';
const assert = require('assert');
const ref = require('../');
const inspect = require('util').inspect;

describe('external_arraybuffer', function() {

it('should get an array buffer with number address', function() {
const buf = Buffer.from('hello' + '\0');
const address = ref.address(buf);
const ab = ref.readExternalArrayBuffer(address, 6);
assert.strictEqual(typeof ab, 'object');
const buffer = Buffer.from(ab);
const address2 = ref.address(buffer);
assert.strictEqual(address, address2);
assert.strictEqual('hello', buffer.readCString());
// when buffer gets changed, the original buf should be changed too
buffer.writeCString('olleh');
assert.strictEqual('olleh', buf.readCString());
});

it('should get an array buffer with string address', function() {
const buf = Buffer.from('hello' + '\0');
const hexAddress = ref.hexAddress(buf);
const ab = ref.readExternalArrayBuffer('0x' + hexAddress, 6);
assert.strictEqual(typeof ab, 'object');
const buffer = Buffer.from(ab);
const address2 = ref.hexAddress(buffer);
assert.strictEqual(hexAddress, address2);
assert.strictEqual('hello', buffer.readCString());
// when buffer gets changed, the original buf should be changed too
buffer.writeCString('olleh');
assert.strictEqual('olleh', buf.readCString());
});
});