Add buffer.unpack
This commit is contained in:
parent
49451c1dab
commit
785531691b
@ -4,6 +4,8 @@
|
||||
#include <stdlib.h> // malloc, free
|
||||
#include <v8.h>
|
||||
|
||||
#include <arpa/inet.h> // htons, htonl
|
||||
|
||||
#include <node.h>
|
||||
|
||||
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")
|
||||
Handle<Value> Buffer::Utf8Length(const Arguments &args) {
|
||||
HandleScope scope;
|
||||
@ -280,6 +346,7 @@ bool Buffer::HasInstance(Handle<Value> val) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Buffer::Initialize(Handle<Object> target) {
|
||||
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, "asciiWrite", Buffer::AsciiWrite);
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "unpack", Buffer::Unpack);
|
||||
|
||||
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> Utf8Write(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 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