1414
1515class SignalTokenizerModule {
1616 public:
17- static void Destroy (void * p_ctx) {}
17+ static void Destroy (void * p_ctx) {
18+ delete static_cast <SignalTokenizerModule*>(p_ctx);
19+ }
1820
19- inline fts5_tokenizer* GetAPIObject () { return & api_object; }
21+ static fts5_tokenizer api_object;
2022
2123 private:
2224 static int Create (void * p_ctx, char const **, int , Fts5Tokenizer** pp_out) {
@@ -26,7 +28,6 @@ class SignalTokenizerModule {
2628 }
2729
2830 static void Delete (Fts5Tokenizer* tokenizer) {}
29- static fts5_tokenizer api_object;
3031};
3132
3233fts5_tokenizer SignalTokenizerModule::api_object = {
@@ -72,6 +73,27 @@ static Napi::Value SignalTokenize(const Napi::CallbackInfo& info) {
7273 return result;
7374}
7475
76+ // Utils
77+
78+ Napi::Error FormatError (Napi::Env env, const char * format, ...) {
79+ va_list args;
80+
81+ va_start (args, format);
82+
83+ // Get buffer size
84+ auto size = vsnprintf (nullptr , 0 , format, args);
85+
86+ // Allocate and fill the string
87+ auto buf = new char [size + 1 ];
88+ vsnprintf (buf, size + 1 , format, args);
89+
90+ va_end (args);
91+
92+ auto err = Napi::Error::New (env, buf);
93+ delete[] buf;
94+ return err;
95+ }
96+
7597// Database
7698
7799Napi::Object Database::Init (Napi::Env env, Napi::Object exports) {
@@ -126,10 +148,8 @@ Napi::Value Database::Open(const Napi::CallbackInfo& info) {
126148 sqlite3* handle = nullptr ;
127149 int r = sqlite3_open_v2 (path_utf8.c_str (), &handle, flags, nullptr );
128150 if (r != SQLITE_OK) {
129- char buf[1024 ];
130-
131- snprintf (buf, sizeof (buf), " sqlite open error: %s" , sqlite3_errstr (r));
132- NAPI_THROW (Napi::Error::New (env, buf), Napi::Value ());
151+ NAPI_THROW (FormatError (env, " sqlite open error: %s" , sqlite3_errstr (r)),
152+ Napi::Value ());
133153 }
134154
135155 auto db = new Database (env, handle);
@@ -145,8 +165,12 @@ Napi::Value Database::Open(const Napi::CallbackInfo& info) {
145165 return Napi::Value ();
146166 }
147167 SignalTokenizerModule* icu = new SignalTokenizerModule ();
148- fts5->xCreateTokenizer (fts5, " signal_tokenizer" , icu, icu->GetAPIObject (),
149- &SignalTokenizerModule::Destroy);
168+ r = fts5->xCreateTokenizer (fts5, " signal_tokenizer" , icu, &icu->api_object ,
169+ &SignalTokenizerModule::Destroy);
170+ if (r != SQLITE_OK) {
171+ delete icu;
172+ return db->ThrowSqliteError (env, r);
173+ }
150174
151175 return db->self_ref_ .Value ();
152176}
@@ -204,20 +228,18 @@ Napi::Value Database::Exec(const Napi::CallbackInfo& info) {
204228}
205229
206230Napi::Value Database::ThrowSqliteError (Napi::Env env, int error) {
207- char buf[1024 ];
208-
209231 assert (handle_ != nullptr );
210232 const char * msg = sqlite3_errmsg (handle_);
211233 int offset = sqlite3_error_offset (handle_);
212234 int extended = sqlite3_extended_errcode (handle_);
213235 if (offset == -1 ) {
214- snprintf (buf, sizeof (buf), " sqlite error(%d): %s" , extended, msg);
236+ NAPI_THROW (FormatError (env, " sqlite error(%d): %s" , extended, msg),
237+ Napi::Value ());
215238 } else {
216- snprintf (buf, sizeof (buf), " sqlite error(%d): %s, offset: %d" , extended,
217- msg, offset);
239+ NAPI_THROW (FormatError (env, " sqlite error(%d): %s, offset: %d" , extended,
240+ msg, offset),
241+ Napi::Value ());
218242 }
219-
220- NAPI_THROW (Napi::Error::New (env, buf), Napi::Value ());
221243}
222244
223245fts5_api* Database::GetFTS5API (Napi::Env env) {
@@ -249,7 +271,9 @@ std::list<Statement*>::const_iterator Database::TrackStatement(
249271 self_ref_.Ref ();
250272
251273 statements_.emplace_back (stmt);
252- return --statements_.end ();
274+ auto end = statements_.end ();
275+ end--;
276+ return end;
253277}
254278
255279void Database::UntrackStatement (std::list<Statement*>::const_iterator iter) {
@@ -492,8 +516,6 @@ Napi::Value Statement::Step(const Napi::CallbackInfo& info) {
492516}
493517
494518bool Statement::BindParams (Napi::Env env, Napi::Value params) {
495- char buf[1024 ];
496-
497519 int key_count = sqlite3_bind_parameter_count (handle_);
498520
499521 if (params.IsNull ()) {
@@ -505,29 +527,29 @@ bool Statement::BindParams(Napi::Env env, Napi::Value params) {
505527 return true ;
506528 }
507529
508- snprintf (buf, sizeof (buf) , " Expected %d parameters, got 0" , key_count);
509- NAPI_THROW ( Napi::Error::New (env, buf), false );
530+ NAPI_THROW ( FormatError (env , " Expected %d parameters, got 0" , key_count),
531+ false );
510532 } else if (params.IsArray ()) {
511533 auto list = params.As <Napi::Array>();
512534 auto list_len = static_cast <int >(list.Length ());
513535 if (list_len != key_count) {
514- snprintf (buf, sizeof (buf) , " Expected %d parameters, got %d" , key_count,
515- list_len);
516- NAPI_THROW ( Napi::Error::New (env, buf), false );
536+ NAPI_THROW ( FormatError (env , " Expected %d parameters, got %d" , key_count,
537+ list_len),
538+ false );
517539 }
518540
519541 for (int i = 1 ; i <= list_len; i++) {
520542 auto name = sqlite3_bind_parameter_name (handle_, i);
521543 if (name != nullptr ) {
522- snprintf (buf, sizeof (buf) , " Unexpected named param %s at %d" , name, i);
523- NAPI_THROW ( Napi::Error::New (env, buf), false );
544+ NAPI_THROW ( FormatError (env , " Unexpected named param %s at %d" , name, i),
545+ false );
524546 }
525547
526548 auto error = BindParam (env, i, list[i - 1 ]);
527549 if (error != nullptr ) {
528- snprintf (buf, sizeof (buf), " Failed to bind param %d, error %s " , i,
529- error);
530- NAPI_THROW ( Napi::Error::New (env, buf), false );
550+ NAPI_THROW (
551+ FormatError (env, " Failed to bind param %d, error %s " , i, error),
552+ false );
531553 }
532554 }
533555 } else {
@@ -536,18 +558,18 @@ bool Statement::BindParams(Napi::Env env, Napi::Value params) {
536558 for (int i = 1 ; i <= key_count; i++) {
537559 auto name = sqlite3_bind_parameter_name (handle_, i);
538560 if (name == nullptr ) {
539- snprintf (buf, sizeof (buf) , " Unexpected anonymous param at %d" , i);
540- NAPI_THROW ( Napi::Error::New (env, buf), false );
561+ NAPI_THROW ( FormatError (env , " Unexpected anonymous param at %d" , i),
562+ false );
541563 }
542564
543565 // Skip "$"
544566 name = name + 1 ;
545567 auto value = obj[name];
546568 auto error = BindParam (env, i, value);
547569 if (error != nullptr ) {
548- snprintf (buf, sizeof (buf), " Failed to bind param %s, error %s " , name,
549- error);
550- NAPI_THROW ( Napi::Error::New (env, buf), false );
570+ NAPI_THROW (
571+ FormatError (env, " Failed to bind param %s, error %s " , name, error),
572+ false );
551573 }
552574 }
553575 }
0 commit comments