44#include < stdlib.h> // malloc, free
55#include < v8.h>
66
7+ #include < arpa/inet.h> // htons, htonl
8+
79#include < node.h>
810
911namespace node {
@@ -261,6 +263,70 @@ Handle<Value> Buffer::AsciiWrite(const Arguments &args) {
261263}
262264
263265
266+ // buffer.unpack(format, index);
267+ // Starting at 'index', unpacks binary from the buffer into an array.
268+ // 'format' is a string
269+ //
270+ // FORMAT RETURNS
271+ // N uint32_t a 32bit unsigned integer in network byte order
272+ // n uint16_t a 16bit unsigned integer in network byte order
273+ // o uint8_t a 8bit unsigned integer
274+ Handle<Value> Buffer::Unpack (const Arguments &args) {
275+ HandleScope scope;
276+ Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args.This ());
277+
278+ if (!args[0 ]->IsString ()) {
279+ return ThrowException (Exception::TypeError (String::New (
280+ " Argument must be a string" )));
281+ }
282+
283+ String::AsciiValue format (args[0 ]->ToString ());
284+ int index = args[1 ]->IntegerValue ();
285+
286+ #define OUT_OF_BOUNDS ThrowException (Exception::Error(String::New(" Out of bounds" )))
287+
288+ Local<Array> array = Array::New(format.length());
289+
290+ uint8_t uint8;
291+ uint16_t uint16;
292+ uint32_t uint32;
293+
294+ for (int i = 0 ; i < format.length (); i++) {
295+ switch ((*format)[i]) {
296+ // 32bit unsigned integer in network byte order
297+ case ' N' :
298+ if (index + 3 >= buffer->length_ ) return OUT_OF_BOUNDS;
299+ uint32 = htonl (*(uint32_t *)(buffer->data_ + index));
300+ array->Set (Integer::New (i), Integer::NewFromUnsigned (uint32));
301+ index += 4 ;
302+ break ;
303+
304+ // 16bit unsigned integer in network byte order
305+ case ' n' :
306+ if (index + 1 >= buffer->length_ ) return OUT_OF_BOUNDS;
307+ uint16 = htons (*(uint16_t *)(buffer->data_ + index));
308+ array->Set (Integer::New (i), Integer::NewFromUnsigned (uint16));
309+ index += 2 ;
310+ break ;
311+
312+ // a single octet, unsigned.
313+ case ' o' :
314+ if (index >= buffer->length_ ) return OUT_OF_BOUNDS;
315+ uint8 = (uint8_t )buffer->data_ [index];
316+ array->Set (Integer::New (i), Integer::NewFromUnsigned (uint8));
317+ index += 1 ;
318+ break ;
319+
320+ default :
321+ return ThrowException (Exception::Error (
322+ String::New (" Unknown format character" )));
323+ }
324+ }
325+
326+ return scope.Close (array);
327+ }
328+
329+
264330// var nbytes = Buffer.utf8Length("string")
265331Handle<Value> Buffer::Utf8Length (const Arguments &args) {
266332 HandleScope scope;
@@ -280,6 +346,7 @@ bool Buffer::HasInstance(Handle<Value> val) {
280346}
281347
282348
349+
283350void Buffer::Initialize (Handle<Object> target) {
284351 HandleScope scope;
285352
@@ -299,6 +366,7 @@ void Buffer::Initialize(Handle<Object> target) {
299366
300367 NODE_SET_PROTOTYPE_METHOD (constructor_template, " utf8Write" , Buffer::Utf8Write);
301368 NODE_SET_PROTOTYPE_METHOD (constructor_template, " asciiWrite" , Buffer::AsciiWrite);
369+ NODE_SET_PROTOTYPE_METHOD (constructor_template, " unpack" , Buffer::Unpack);
302370
303371 NODE_SET_METHOD (constructor_template->GetFunction (), " utf8Length" , Buffer::Utf8Length);
304372
0 commit comments