#ifndef NODE_SQLITE3_SRC_MACROS_H #define NODE_SQLITE3_SRC_MACROS_H const char* sqlite_code_string(int code); const char* sqlite_authorizer_string(int type); #define REQUIRE_ARGUMENTS(n) \ if (info.Length() < (n)) { \ return Nan::ThrowTypeError("Expected " #n "arguments"); \ } #define REQUIRE_ARGUMENT_EXTERNAL(i, var) \ if (info.Length() <= (i) || !info[i]->IsExternal()) { \ return Nan::ThrowTypeError("Argument " #i " invalid"); \ } \ Local var = Local::Cast(info[i]); #define REQUIRE_ARGUMENT_FUNCTION(i, var) \ if (info.Length() <= (i) || !info[i]->IsFunction()) { \ return Nan::ThrowTypeError("Argument " #i " must be a function"); \ } \ Local var = Local::Cast(info[i]); #define REQUIRE_ARGUMENT_STRING(i, var) \ if (info.Length() <= (i) || !info[i]->IsString()) { \ return Nan::ThrowTypeError("Argument " #i " must be a string"); \ } \ Nan::Utf8String var(info[i]); #define REQUIRE_ARGUMENT_INTEGER(i, var) \ if (info.Length() <= (i) || !info[i]->IsInt32()) { \ return Nan::ThrowTypeError("Argument " #i " must be an integer"); \ } \ int var(Nan::To(info[i]).FromJust()); #define OPTIONAL_ARGUMENT_FUNCTION(i, var) \ Local var; \ if (info.Length() > i && !info[i]->IsUndefined()) { \ if (!info[i]->IsFunction()) { \ return Nan::ThrowTypeError("Argument " #i " must be a function"); \ } \ var = Local::Cast(info[i]); \ } #define OPTIONAL_ARGUMENT_INTEGER(i, var, default) \ int var; \ if (info.Length() <= (i)) { \ var = (default); \ } \ else if (info[i]->IsInt32()) { \ var = Nan::To(info[i]).FromJust(); \ } \ else { \ return Nan::ThrowTypeError("Argument " #i " must be an integer"); \ } #define DEFINE_CONSTANT_INTEGER(target, constant, name) \ Nan::ForceSet(target, \ Nan::New(#name).ToLocalChecked(), \ Nan::New(constant), \ static_cast(ReadOnly | DontDelete) \ ); #define DEFINE_CONSTANT_STRING(target, constant, name) \ Nan::ForceSet(target, \ Nan::New(#name).ToLocalChecked(), \ Nan::New(constant).ToLocalChecked(), \ static_cast(ReadOnly | DontDelete) \ ); #define NODE_SET_GETTER(target, name, function) \ Nan::SetAccessor((target)->InstanceTemplate(), \ Nan::New(name).ToLocalChecked(), (function)); #define NODE_SET_SETTER(target, name, getter, setter) \ Nan::SetAccessor((target)->InstanceTemplate(), \ Nan::New(name).ToLocalChecked(), getter, setter); #define GET_STRING(source, name, property) \ Nan::Utf8String name(Nan::Get(source, \ Nan::New(prop).ToLocalChecked()).ToLocalChecked()); #define GET_INTEGER(source, name, prop) \ int name = Nan::To(Nan::Get(source, \ Nan::New(property).ToLocalChecked()).ToLocalChecked()).FromJust(); #define EXCEPTION(msg, errno, name) \ Local name = Exception::Error(Nan::New( \ std::string(sqlite_code_string(errno)) + \ std::string(": ") + std::string(msg) \ ).ToLocalChecked()); \ Local name ##_obj = name.As(); \ Nan::Set(name ##_obj, Nan::New("errno").ToLocalChecked(), Nan::New(errno));\ Nan::Set(name ##_obj, Nan::New("code").ToLocalChecked(), \ Nan::New(sqlite_code_string(errno)).ToLocalChecked()); #define EMIT_EVENT(obj, argc, argv) \ TRY_CATCH_CALL((obj), \ Nan::Get(obj, \ Nan::New("emit").ToLocalChecked()).ToLocalChecked().As(),\ argc, argv \ ); #define TRY_CATCH_CALL(context, callback, argc, argv) \ Nan::MakeCallback((context), (callback), (argc), (argv)) #define WORK_DEFINITION(name) \ static NAN_METHOD(name); \ static void Work_Begin##name(Baton* baton); \ static void Work_##name(uv_work_t* req); \ static void Work_After##name(uv_work_t* req); #define STATEMENT_BEGIN(type) \ assert(baton); \ assert(baton->stmt); \ assert(!baton->stmt->locked); \ assert(!baton->stmt->finalized); \ assert(baton->stmt->prepared); \ baton->stmt->locked = true; \ baton->stmt->db->pending++; \ int status = uv_queue_work(uv_default_loop(), \ &baton->request, \ Work_##type, reinterpret_cast(Work_After##type)); \ assert(status == 0); #define STATEMENT_INIT(type) \ type* baton = static_cast(req->data); \ Statement* stmt = baton->stmt; #define STATEMENT_END() \ assert(stmt->locked); \ assert(stmt->db->pending); \ stmt->locked = false; \ stmt->db->pending--; \ stmt->Process(); \ stmt->db->Process(); \ delete baton; #define BACKUP_BEGIN(type) \ assert(baton); \ assert(baton->backup); \ assert(!baton->backup->locked); \ assert(!baton->backup->finished); \ assert(baton->backup->inited); \ baton->backup->locked = true; \ baton->backup->db->pending++; \ int status = uv_queue_work(uv_default_loop(), \ &baton->request, \ Work_##type, reinterpret_cast(Work_After##type)); \ assert(status == 0); #define BACKUP_INIT(type) \ type* baton = static_cast(req->data); \ Backup* backup = baton->backup; #define BACKUP_END() \ assert(backup->locked); \ assert(backup->db->pending); \ backup->locked = false; \ backup->db->pending--; \ backup->Process(); \ backup->db->Process(); \ delete baton; #define DELETE_FIELD(field) \ if (field != NULL) { \ switch ((field)->type) { \ case SQLITE_INTEGER: delete (Values::Integer*)(field); break; \ case SQLITE_FLOAT: delete (Values::Float*)(field); break; \ case SQLITE_TEXT: delete (Values::Text*)(field); break; \ case SQLITE_BLOB: delete (Values::Blob*)(field); break; \ case SQLITE_NULL: delete (Values::Null*)(field); break; \ } \ } #endif