#ifndef _ADDON_TOOLS_HPP_ #define _ADDON_TOOLS_HPP_ #include #define NAN_HS Nan::HandleScope scope; #define RET_VALUE(VAL) info.GetReturnValue().Set(VAL); #define RET_UNDEFINED RET_VALUE(Nan::Undefined()); typedef v8::Local V8_VAR_VAL; typedef v8::Local V8_VAR_OBJ; typedef v8::Local V8_VAR_ARR; typedef v8::Local V8_VAR_STR; typedef v8::Local V8_VAR_FUNC; typedef v8::Local V8_VAR_FT; typedef v8::Local V8_VAR_OT; typedef Nan::Persistent V8_STORE_FT; typedef Nan::Persistent V8_STORE_FUNC; typedef Nan::Persistent V8_STORE_OBJ; typedef Nan::Persistent V8_STORE_VAL; #define JS_STR(...) Nan::New(__VA_ARGS__).ToLocalChecked() #define JS_UTF8(...) Nan::New(__VA_ARGS__).ToLocalChecked() #define JS_INT(val) Nan::New(val) #define JS_INT32(val) Nan::New(val) #define JS_UINT32(val) Nan::New(val) #define JS_NUM(val) Nan::New(val) #define JS_OFFS(val) Nan::New(static_cast(val)) #define JS_FLOAT(val) Nan::New(val) #define JS_DOUBLE(val) Nan::New(val) #define JS_EXT(val) Nan::New(reinterpret_cast(val)) #define JS_BOOL(val) (val) ? Nan::True() : Nan::False() #define JS_FUN(val) Nan::New(val) #define JS_OBJ(val) Nan::New(val) #define REQ_ARGS(N) \ if (info.Length() < (N)) \ return Nan::ThrowTypeError("Expected at least " #N " arguments"); #define IS_ARG_EMPTY(I) (info[I]->IsNull() || info[I]->IsUndefined()) #define CHECK_REQ_ARG(I, C, T) \ if (info.Length() <= (I) || ! info[I]->C) \ return Nan::ThrowTypeError("Argument " #I " must be " T); #define CHECK_LET_ARG(I, C, T) \ if ( ! (IS_ARG_EMPTY(I) || info[I]->C) ) \ return Nan::ThrowTypeError("Argument " #I " must be " T " or null"); #define REQ_UTF8_ARG(I, VAR) \ CHECK_REQ_ARG(I, IsString(), "string"); \ Nan::Utf8String VAR(info[I]); #define LET_UTF8_ARG(I, VAR) \ CHECK_LET_ARG(I, IsString(), "string"); \ Nan::Utf8String VAR(JS_STR("")); #define REQ_STR_ARG(I, VAR) REQ_UTF8_ARG(I, VAR) #define LET_STR_ARG(I, VAR) LET_UTF8_ARG(I, VAR) #define REQ_INT32_ARG(I, VAR) \ CHECK_REQ_ARG(I, IsInt32(), "int32"); \ int VAR = info[I]->Int32Value(); #define LET_INT32_ARG(I, VAR) \ CHECK_LET_ARG(I, IsInt32(), "int32"); \ int VAR = IS_ARG_EMPTY(I) ? 0 : info[I]->Int32Value(); #define REQ_UINT32_ARG(I, VAR) \ CHECK_REQ_ARG(I, IsUint32(), "uint32"); \ unsigned int VAR = info[I]->Uint32Value(); #define LET_UINT32_ARG(I, VAR) \ CHECK_LET_ARG(I, IsUint32(), "uint32"); \ unsigned int VAR = IS_ARG_EMPTY(I) ? 0 : info[I]->Uint32Value(); #define REQ_INT_ARG(I, VAR) LET_INT32_ARG(I, VAR) #define LET_INT_ARG(I, VAR) REQ_UINT32_ARG(I, VAR) #define REQ_BOOL_ARG(I, VAR) \ CHECK_REQ_ARG(I, IsBoolean(), "bool"); \ bool VAR = info[I]->BooleanValue(); #define LET_BOOL_ARG(I, VAR) \ CHECK_LET_ARG(I, IsBoolean(), "bool"); \ bool VAR = IS_ARG_EMPTY(I) ? false : info[I]->BooleanValue(); #define REQ_OFFS_ARG(I, VAR) \ CHECK_REQ_ARG(I, IsNumber(), "number"); \ size_t VAR = static_cast(info[I]->IntegerValue()); #define LET_OFFS_ARG(I, VAR) \ CHECK_LET_ARG(I, IsNumber(), "number"); \ size_t VAR = IS_ARG_EMPTY(I) ? 0 : static_cast(info[I]->IntegerValue()); #define REQ_DOUBLE_ARG(I, VAR) \ CHECK_REQ_ARG(I, IsNumber(), "number"); \ double VAR = info[I]->NumberValue(); #define LET_DOUBLE_ARG(I, VAR) \ CHECK_LET_ARG(I, IsNumber(), "number"); \ double VAR = IS_ARG_EMPTY(I) ? 0.0 : info[I]->NumberValue(); #define REQ_FLOAT_ARG(I, VAR) \ CHECK_REQ_ARG(I, IsNumber(), "number"); \ float VAR = static_cast(info[I]->NumberValue()); #define LET_FLOAT_ARG(I, VAR) \ CHECK_LET_ARG(I, IsNumber(), "number"); \ float VAR = IS_ARG_EMPTY(I) ? 0.f : static_cast(info[I]->NumberValue()); #define REQ_EXT_ARG(I, VAR) \ CHECK_REQ_ARG(I, IsExternal(), "void*"); \ v8::Local VAR = v8::Local::Cast(info[I]); #define LET_EXT_ARG(I, VAR) \ CHECK_LET_ARG(I, IsExternal(), "number"); \ v8::Local VAR = IS_ARG_EMPTY(I) ? JS_EXT(NULL) : \ v8::Local::Cast(info[I]); #define REQ_FUN_ARG(I, VAR) \ CHECK_REQ_ARG(I, IsFunction(), "function"); \ v8::Local VAR = v8::Local::Cast(info[I]); #define REQ_OBJ_ARG(I, VAR) \ CHECK_REQ_ARG(I, IsObject(), "object"); \ v8::Local VAR = v8::Local::Cast(info[I]); #define REQ_ARRV_ARG(I, VAR) \ REQ_OBJ_ARG(I, _obj_##VAR); \ if( ! _obj_##VAR->IsArrayBufferView() ) \ return Nan::ThrowTypeError("Argument " #I " must be an array buffer");\ v8::Local VAR = v8::Local::Cast(_obj_##VAR); #define SET_PROP(OBJ, KEY, VAL) OBJ->Set(JS_STR(KEY), VAL); #define SET_I(ARR, I, VAL) ARR->Set(I, VAL); #define CTOR_CHECK(T) \ if ( ! info.IsConstructCall() ) \ return Nan::ThrowTypeError(T " must be called with the 'new' keyword."); #define DES_CHECK \ if (_isDestroyed) return; #define SETTER_CHECK(C, T) \ if ( ! value->C ) \ return Nan::ThrowTypeError("Value must be " T); #define ACCESSOR_RW(OBJ, NAME) \ Nan::SetAccessor(OBJ, JS_STR(#NAME), NAME ## Getter, NAME ## Setter); #define ACCESSOR_R(OBJ, NAME) \ Nan::SetAccessor(OBJ, JS_STR(#NAME), NAME ## Getter); #define SETTER_UTF8_ARG \ SETTER_CHECK(IsString(), "string"); \ Nan::Utf8String v(value); #define SETTER_STR_ARG SETTER_UTF8_ARG #define SETTER_INT32_ARG \ SETTER_CHECK(IsInt32(), "int32"); \ int v = value->Int32Value(); #define SETTER_INT_ARG SETTER_INT32_ARG #define SETTER_BOOL_ARG \ SETTER_CHECK(IsBoolean(), "bool"); \ bool v = value->BooleanValue(); #define SETTER_UINT32_ARG \ SETTER_CHECK(IsUint32(), "uint32"); \ unsigned int v = value->Uint32Value(); #define SETTER_OFFS_ARG \ SETTER_CHECK(IsNumber(), "number"); \ size_t v = static_cast(value->IntegerValue()); #define SETTER_DOUBLE_ARG \ SETTER_CHECK(IsNumber(), "number"); \ double v = value->NumberValue(); #define SETTER_FLOAT_ARG \ SETTER_CHECK(IsNumber(), "number"); \ float v = static_cast(value->NumberValue()); #define SETTER_EXT_ARG \ SETTER_CHECK(IsExternal(), "void*"); \ v8::Local v = v8::Local::Cast(value); #define SETTER_FUN_ARG \ SETTER_CHECK(IsFunction(), "function"); \ v8::Local v = v8::Local::Cast(value); #define SETTER_OBJ_ARG \ SETTER_CHECK(IsObject(), "object"); \ v8::Local v = v8::Local::Cast(value); #define SETTER_ARRV_ARG \ SETTER_CHECK(IsObject(), "object"); \ v8::Local _obj_v = v8::Local::Cast(value); \ if( ! _obj_v->IsArrayBufferView() ) \ return Nan::ThrowTypeError("The value must be an array buffer"); \ v8::Local v = v8::Local::Cast(_obj_v); template inline Type* getArrayData(v8::Local arg, int *num = NULL) { Type *data = NULL; if (num) { *num = 0; } if (arg->IsNull() || arg->IsUndefined()) { return data; } if (arg->IsArray()) { Nan::ThrowError("JS Array is not supported here."); return data; } if ( ! arg->IsArrayBufferView() ) { Nan::ThrowError("Argument must be a TypedArray."); return data; } v8::Local arr = v8::Local::Cast(arg); if (num) { *num = arr->ByteLength() / sizeof(Type); } data = reinterpret_cast(arr->Buffer()->GetContents().Data()); return data; } inline void *getImageData(v8::Local arg) { void *pixels = NULL; if (arg->IsNull() || arg->IsUndefined()) { return pixels; } v8::Local obj = v8::Local::Cast(arg); if ( ! obj->IsObject() ) { Nan::ThrowError("Bad Image argument"); return pixels; } if (obj->IsArrayBufferView()) { pixels = getArrayData(obj, NULL); } else if (obj->Has(JS_STR("data"))) { pixels = node::Buffer::Data(Nan::Get(obj, JS_STR("data")).ToLocalChecked()); } else { Nan::ThrowError("Bad Image argument"); } return pixels; } #endif // _ADDON_TOOLS_HPP_