Add buffer.unpack
This commit is contained in:
parent
49451c1dab
commit
785531691b
@ -4,6 +4,8 @@
|
|||||||
#include <stdlib.h> // malloc, free
|
#include <stdlib.h> // malloc, free
|
||||||
#include <v8.h>
|
#include <v8.h>
|
||||||
|
|
||||||
|
#include <arpa/inet.h> // htons, htonl
|
||||||
|
|
||||||
#include <node.h>
|
#include <node.h>
|
||||||
|
|
||||||
namespace node {
|
namespace node {
|
||||||
@ -261,6 +263,70 @@ Handle<Value> Buffer::AsciiWrite(const Arguments &args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// buffer.unpack(format, index);
|
||||||
|
// Starting at 'index', unpacks binary from the buffer into an array.
|
||||||
|
// 'format' is a string
|
||||||
|
//
|
||||||
|
// FORMAT RETURNS
|
||||||
|
// N uint32_t a 32bit unsigned integer in network byte order
|
||||||
|
// n uint16_t a 16bit unsigned integer in network byte order
|
||||||
|
// o uint8_t a 8bit unsigned integer
|
||||||
|
Handle<Value> Buffer::Unpack(const Arguments &args) {
|
||||||
|
HandleScope scope;
|
||||||
|
Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args.This());
|
||||||
|
|
||||||
|
if (!args[0]->IsString()) {
|
||||||
|
return ThrowException(Exception::TypeError(String::New(
|
||||||
|
"Argument must be a string")));
|
||||||
|
}
|
||||||
|
|
||||||
|
String::AsciiValue format(args[0]->ToString());
|
||||||
|
int index = args[1]->IntegerValue();
|
||||||
|
|
||||||
|
#define OUT_OF_BOUNDS ThrowException(Exception::Error(String::New("Out of bounds")))
|
||||||
|
|
||||||
|
Local<Array> array = Array::New(format.length());
|
||||||
|
|
||||||
|
uint8_t uint8;
|
||||||
|
uint16_t uint16;
|
||||||
|
uint32_t uint32;
|
||||||
|
|
||||||
|
for (int i = 0; i < format.length(); i++) {
|
||||||
|
switch ((*format)[i]) {
|
||||||
|
// 32bit unsigned integer in network byte order
|
||||||
|
case 'N':
|
||||||
|
if (index + 3 >= buffer->length_) return OUT_OF_BOUNDS;
|
||||||
|
uint32 = htonl(*(uint32_t*)(buffer->data_ + index));
|
||||||
|
array->Set(Integer::New(i), Integer::NewFromUnsigned(uint32));
|
||||||
|
index += 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 16bit unsigned integer in network byte order
|
||||||
|
case 'n':
|
||||||
|
if (index + 1 >= buffer->length_) return OUT_OF_BOUNDS;
|
||||||
|
uint16 = htons(*(uint16_t*)(buffer->data_ + index));
|
||||||
|
array->Set(Integer::New(i), Integer::NewFromUnsigned(uint16));
|
||||||
|
index += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// a single octet, unsigned.
|
||||||
|
case 'o':
|
||||||
|
if (index >= buffer->length_) return OUT_OF_BOUNDS;
|
||||||
|
uint8 = (uint8_t)buffer->data_[index];
|
||||||
|
array->Set(Integer::New(i), Integer::NewFromUnsigned(uint8));
|
||||||
|
index += 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return ThrowException(Exception::Error(
|
||||||
|
String::New("Unknown format character")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return scope.Close(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// var nbytes = Buffer.utf8Length("string")
|
// var nbytes = Buffer.utf8Length("string")
|
||||||
Handle<Value> Buffer::Utf8Length(const Arguments &args) {
|
Handle<Value> Buffer::Utf8Length(const Arguments &args) {
|
||||||
HandleScope scope;
|
HandleScope scope;
|
||||||
@ -280,6 +346,7 @@ bool Buffer::HasInstance(Handle<Value> val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Buffer::Initialize(Handle<Object> target) {
|
void Buffer::Initialize(Handle<Object> target) {
|
||||||
HandleScope scope;
|
HandleScope scope;
|
||||||
|
|
||||||
@ -299,6 +366,7 @@ void Buffer::Initialize(Handle<Object> target) {
|
|||||||
|
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "utf8Write", Buffer::Utf8Write);
|
NODE_SET_PROTOTYPE_METHOD(constructor_template, "utf8Write", Buffer::Utf8Write);
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "asciiWrite", Buffer::AsciiWrite);
|
NODE_SET_PROTOTYPE_METHOD(constructor_template, "asciiWrite", Buffer::AsciiWrite);
|
||||||
|
NODE_SET_PROTOTYPE_METHOD(constructor_template, "unpack", Buffer::Unpack);
|
||||||
|
|
||||||
NODE_SET_METHOD(constructor_template->GetFunction(), "utf8Length", Buffer::Utf8Length);
|
NODE_SET_METHOD(constructor_template->GetFunction(), "utf8Length", Buffer::Utf8Length);
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ class Buffer : public ObjectWrap {
|
|||||||
static v8::Handle<v8::Value> AsciiWrite(const v8::Arguments &args);
|
static v8::Handle<v8::Value> AsciiWrite(const v8::Arguments &args);
|
||||||
static v8::Handle<v8::Value> Utf8Write(const v8::Arguments &args);
|
static v8::Handle<v8::Value> Utf8Write(const v8::Arguments &args);
|
||||||
static v8::Handle<v8::Value> Utf8Length(const v8::Arguments &args);
|
static v8::Handle<v8::Value> Utf8Length(const v8::Arguments &args);
|
||||||
|
static v8::Handle<v8::Value> Unpack(const v8::Arguments &args);
|
||||||
|
|
||||||
int AsciiWrite(char *string, int offset, int length);
|
int AsciiWrite(char *string, int offset, int length);
|
||||||
int Utf8Write(char *string, int offset, int length);
|
int Utf8Write(char *string, int offset, int length);
|
||||||
|
@ -50,4 +50,26 @@ for (var j = 0; j < 10000; j++) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// unpack
|
||||||
|
|
||||||
|
var b = new process.Buffer(10);
|
||||||
|
b[0] = 0x00;
|
||||||
|
b[1] = 0x01;
|
||||||
|
b[2] = 0x03;
|
||||||
|
b[3] = 0x00;
|
||||||
|
|
||||||
|
assert.deepEqual([0x0001], b.unpack('n', 0));
|
||||||
|
assert.deepEqual([0x0001, 0x0300], b.unpack('nn', 0));
|
||||||
|
assert.deepEqual([0x0103], b.unpack('n', 1));
|
||||||
|
assert.deepEqual([0x0300], b.unpack('n', 2));
|
||||||
|
assert.deepEqual([0x00010300], b.unpack('N', 0));
|
||||||
|
assert.throws(function () {
|
||||||
|
b.unpack('N', 8);
|
||||||
|
});
|
||||||
|
|
||||||
|
b[4] = 0xDE;
|
||||||
|
b[5] = 0xAD;
|
||||||
|
b[6] = 0xBE;
|
||||||
|
b[7] = 0xEF;
|
||||||
|
|
||||||
|
assert.deepEqual([0xDEADBEEF], b.unpack('N', 4));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user