#include #include #include #include using namespace node; using namespace v8; namespace { Handle except(const char* msg) { return ThrowException(Exception::Error(String::New(msg))); } enum ByteOrder { kNative, kFlip }; template t SwapBytes(const t& in) { t out; const char* in_p = reinterpret_cast(&in); char* out_p = reinterpret_cast(&out) + sizeof(t) - 1; for(; out_p >= reinterpret_cast(&out); --out_p, ++in_p) { *out_p = *in_p; } return out; } bool IsPlatformLittleEndian() { int32_t one = 1; char* one_p = reinterpret_cast(&one); if(*one_p == 1) return true; return false; } ByteOrder GetByteOrder(const Arguments& args) { // default to native. if(!(args.Length() > 1)) return kNative; Local arg = args[1]; if(arg->IsString()) { char utf8[12]; arg->ToString()->WriteUtf8(utf8, 10); if(!std::strncmp(utf8, "big", 10)) return IsPlatformLittleEndian() ? kFlip : kNative; if(!std::strncmp(utf8, "little", 10)) return IsPlatformLittleEndian() ? kNative : kFlip; } return kNative; } template Handle unpackBuffer(const Arguments& args) { HandleScope scope; if(args.Length() < 1) return except("You must provide at least one argument."); if(!Buffer::HasInstance(args[0]->ToObject())) return except("The first argument must be a buffer."); if(Buffer::Length(args[0]->ToObject()) != sizeof(t)) return except("Buffer is the incorrect length."); ByteOrder order = GetByteOrder(args); t nativeType = *reinterpret_cast(Buffer::Data(args[0]->ToObject())); if(order == kFlip) nativeType = SwapBytes(nativeType); Local num = Number::New(nativeType); return scope.Close(num); } template Handle packBuffer(const Arguments& args) { HandleScope scope; if(args.Length() < 1) return except("You must provide at least one argument."); if(!args[0]->IsNumber ()) return except("The first argument must be a number."); ByteOrder order = GetByteOrder(args); Local num = args[0]->ToNumber(); t nativeType = num->Value(); if(order == kFlip) nativeType = SwapBytes(nativeType); Buffer* buff = Buffer::New(reinterpret_cast(&nativeType), sizeof(nativeType)); return scope.Close(buff->handle_); } }// private namespace extern "C" { static void init(Handle target) { NODE_SET_METHOD(target, "unpackFloat32", unpackBuffer); NODE_SET_METHOD(target, "unpackFloat64", unpackBuffer); NODE_SET_METHOD(target, "unpackInt8", unpackBuffer); NODE_SET_METHOD(target, "unpackInt16", unpackBuffer); NODE_SET_METHOD(target, "unpackInt32", unpackBuffer); NODE_SET_METHOD(target, "unpackInt64", unpackBuffer); NODE_SET_METHOD(target, "unpackUInt8", unpackBuffer); NODE_SET_METHOD(target, "unpackUInt16", unpackBuffer); NODE_SET_METHOD(target, "unpackUInt32", unpackBuffer); NODE_SET_METHOD(target, "unpackUInt64", unpackBuffer); NODE_SET_METHOD(target, "packFloat32", packBuffer); NODE_SET_METHOD(target, "packFloat64", packBuffer); NODE_SET_METHOD(target, "packInt8", packBuffer); NODE_SET_METHOD(target, "packInt16", packBuffer); NODE_SET_METHOD(target, "packInt32", packBuffer); NODE_SET_METHOD(target, "packInt64", packBuffer); NODE_SET_METHOD(target, "packUInt8", packBuffer); NODE_SET_METHOD(target, "packUInt16", packBuffer); NODE_SET_METHOD(target, "packUInt32", packBuffer); NODE_SET_METHOD(target, "packUInt64", packBuffer); } NODE_MODULE(binpack, init); }