SQLite Forum

_vconfig variants taking ap_list
Login

sqlite_config variant taking ap_list

(1.2) By sbooth on 2020-06-23 19:10:35 edited from 1.1 [source]

Swift generally supports calling C functions but does not support C variadic functions. Swift does, however, support a type called CVarArg which is basically a va_list.

The current implementation of sqlite3_config in main.c looks like:

int sqlite3_config(int op, ...){
  va_list ap;
  int rc = SQLITE_OK;

  /* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while
  ** the SQLite library is in use. */
  if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE_BKPT;

  va_start(ap, op);
  /* implementation is here */
  va_end(ap);
  return rc;
}

It would be beneficial for using SQLite from Swift (and possibly other languages that don't support calling C variadic functions) if there were versions of the _config functions (sqlite3_config and sqlite3_db_config) that took a va_list, much like vprintf. A possible implementation could look like:

int sqlite3_config(int op, ...){
  va_list ap;
  va_start(ap, op);
  int rc = sqlite3_vconfig(op, ap);
  va_end(ap);
  return rc;
}

int sqlite3_vconfig(int op, va_list ap){
  /* existing implementation of sqlite3_config minus the va_start()/va_end() portion*/
}

I'm happy to submit a patch if this is something that would be considered.

(2) By sbooth on 2020-07-02 11:32:57 in reply to 1.2 [link] [source]

In case there is any interest here is a proof-of-concept change implementing the above:

Index: src/main.c
==================================================================
--- src/main.c
+++ src/main.c
@@ -427,19 +427,17 @@
 ** This routine should only be called when there are no outstanding
 ** database connections or memory allocations.  This routine is not
 ** threadsafe.  Failure to heed these warnings can lead to unpredictable
 ** behavior.
 */
-int sqlite3_config(int op, ...){
-  va_list ap;
+int sqlite3_vconfig(int op, va_list ap){
   int rc = SQLITE_OK;
 
   /* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while
   ** the SQLite library is in use. */
   if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE_BKPT;
 
-  va_start(ap, op);
   switch( op ){
 
     /* Mutex configuration options are only available in a threadsafe
     ** compile.
     */
@@ -730,10 +728,18 @@
     default: {
       rc = SQLITE_ERROR;
       break;
     }
   }
+  return rc;
+}
+
+int sqlite3_config(int op, ...){
+  va_list ap;
+  int rc;
+  va_start(ap, op);
+  rc = sqlite3_vconfig(op, ap);
   va_end(ap);
   return rc;
 }
 
 /*
@@ -912,14 +918,12 @@
 }
 
 /*
 ** Configuration settings for an individual database connection
 */
-int sqlite3_db_config(sqlite3 *db, int op, ...){
-  va_list ap;
+int sqlite3_db_vconfig(sqlite3 *db, int op, va_list ap){
   int rc;
-  va_start(ap, op);
   switch( op ){
     case SQLITE_DBCONFIG_MAINDBNAME: {
       /* IMP: R-06824-28531 */
       /* IMP: R-36257-52125 */
       db->aDb[0].zDbSName = va_arg(ap,char*);
@@ -979,10 +983,18 @@
         }
       }
       break;
     }
   }
+  return rc;
+}
+
+int sqlite3_db_config(sqlite3 *db, int op, ...){
+  va_list ap;
+  int rc;
+  va_start(ap, op);
+  rc = sqlite3_db_vconfig(db, op, ap);
   va_end(ap);
   return rc;
 }
 
 /*