]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Improvements to the sqlite3AtoF() interface. Add a test-control for
authordrh <>
Thu, 26 Mar 2026 14:19:34 +0000 (14:19 +0000)
committerdrh <>
Thu, 26 Mar 2026 14:19:34 +0000 (14:19 +0000)
direct testing of sqlite3AtoF().

FossilOrigin-Name: 97ee48b6ef65fb55633196282c9e75b3b0a3b81ba9755f63493a38e3f1a5610c

manifest
manifest.uuid
src/main.c
src/sqlite.h.in
src/util.c
src/vdbe.c
src/vdbemem.c

index aaf49617c34e3912ac2b18a1d897ff118637cf81..4848e32c6dff4a7d4bab902dfe9e0a3d3e9ca2d7 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Back\sout\sthe\ssqlite3_atof()\sAPI,\sfor\snow.
-D 2026-03-26T12:09:37.920
+C Improvements\sto\sthe\ssqlite3AtoF()\sinterface.\s\sAdd\sa\stest-control\sfor\ndirect\stesting\sof\ssqlite3AtoF().
+D 2026-03-26T14:19:34.547
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -697,7 +697,7 @@ F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
 F src/json.c 5027b856cd9b621dc9ba66b211e21a440ccdc63cefdefb44c51e7d3ac550d1a4
 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
 F src/loadext.c 56a542244fbefc739a2ef57fac007c16b2aefdb4377f584e9547db2ce3e071f9
-F src/main.c 31a13302193fbd51279c7e69cdfa0320d0de7629f9151e0964c1d320e8bdd7a4
+F src/main.c 387bb9d0216d6d35b221481ba8e661d94ad043060cd89581b6422c269ce680a0
 F src/malloc.c 422f7e0498e1c9ef967f06283b6f2c0b16db6b905d8e06f6dbc8baaa3e4e6c5a
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
@@ -735,7 +735,7 @@ F src/resolve.c 928ff887f2a7c64275182060d94d06fdddbe32226c569781cf7e7edc6f58d7fd
 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
 F src/select.c ffe199f025a0dd74670d2a77232bdea364a4d7b36f32c64a6572d39ba6a11576
 F src/shell.c.in 91ee40ec3f75192362cbaa0ad85316140b8dde00a184113d73a837fb6173dbcc
-F src/sqlite.h.in fce4dd4979a6120934a9bc2c0fd2b426b5943d8892b7a82a20307a895b07d7d2
+F src/sqlite.h.in 757b3dbcc4560c02bf9713a395f28a33c66202c1750c740f336df4a118424f6b
 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca
 F src/sqliteInt.h 9716721fb57e32938a1d30a84560ce7633c63860a2209e188c87afad15d4b464
@@ -798,15 +798,15 @@ F src/trigger.c 4bf3bfb3851d165e4404a9f9e69357345f3f7103378c07e07139fdd8aeb7bd20
 F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
 F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
 F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
-F src/util.c 49fc214a09893c98b43d2b085ad8eca74781f0631eecba004bd5471746d069a7
+F src/util.c 70a0a775c6eb824f271862b0acc11557370d2c4e5e2c21188bae60123393748e
 F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
-F src/vdbe.c dbafc6f5762f9ae90d9dc9ed065a31743a8ceafbdbfb1a0a3a228921fb3cc36a
+F src/vdbe.c edff242cffa6d8fbd887415e93c36eadd021c6c66fbdd4f674d77d2baf7721d8
 F src/vdbe.h 70e862ac8a11b590f8c1eaac17a0078429d42bc4ea3f757a9af0f451dd966a71
 F src/vdbeInt.h c31ba4dc8d280c2b1dc89c6fcee68f2555e3813ab34279552c20b964c0e338b1
 F src/vdbeapi.c 6cdcbe5c7afa754c998e73d2d5d2805556268362914b952811bdfb9c78a37cf1
 F src/vdbeaux.c 81687c55682b9f4d942186695f4f7fa4743c564a985e0889def52eded9076d61
 F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692
-F src/vdbemem.c 05610ea8423c4c852a9039e47fb6a2706d4d848758602ebf30da6c3212344695
+F src/vdbemem.c 763fdd94602cbefbf7f7aeef6066fdcd538bc78a26389b5e36f077619d12836c
 F src/vdbesort.c b69220f4ea9ffea5fdef34d968c60305444eea909252a81933b54c296d9cca70
 F src/vdbetrace.c 49e689f751505839742f4a243a1a566e57d5c9eaf0d33bbaa26e2de3febf7b41
 F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
@@ -2195,10 +2195,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
 F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
 F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P 58f4e058f1cbb798b8a48208c6310fd10ca9cd1fc7c550f3ed283cf38ae45c2f
-Q -276c350313a1ac2ebc70c1e8e50ed4baecd4be4d4c93ba04cf5e0078da18700e
-Q -52f76c59f27152dd62069bd833e2409d57d0cd36ccaa568b2ec4ec823e98cb44
-R b4db3c6c015737ad24a5d476714da47b
+P 7568d264be3988df195401158d8d07105b8e9e018eccf98ac948219bee9388ac
+R aa44cc101bc358c488049f6ff4abf07f
 U drh
-Z 58981fb16285e99654df81a8b96e29a9
+Z 14ff26432a141106839fde7c9ab19978
 # Remove this line to create a well-formed Fossil manifest.
index 2d7cd3c86ff3b92247aba48bb3604ffe14b5dcdb..73e7dea186930a1428ef7b22cc66c0b98ff1d906 100644 (file)
@@ -1 +1 @@
-7568d264be3988df195401158d8d07105b8e9e018eccf98ac948219bee9388ac
+97ee48b6ef65fb55633196282c9e75b3b0a3b81ba9755f63493a38e3f1a5610c
index b44ac8dca8eacdc8588cc7dea5f7532f80bbfb17..990d16c70da48af631ed929ca5c1df77a01304ec 100644 (file)
@@ -4716,6 +4716,17 @@ int sqlite3_test_control(int op, ...){
       break;
     }
 
+    /* sqlite3_test_control(SQLITE_TESTCTRL_ATOF, const char *z, double *p);
+    **
+    ** Test access to the sqlite3AtoF() routine.
+    */
+    case SQLITE_TESTCTRL_ATOF: {
+      const char *z = va_arg(ap,const char*);
+      double *pR = va_arg(ap,double*);
+      rc = sqlite3AtoF(z,pR);
+      break;
+    }
+
 #if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
     /* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue)
     **
index 20683b177329f7ffea939058156b16f6ed1c8acf..a1fe64b42c4542b5e3771441a22ae38d5493c738 100644 (file)
@@ -8711,6 +8711,7 @@ int sqlite3_test_control(int op, ...);
 #define SQLITE_TESTCTRL_TUNE                    32
 #define SQLITE_TESTCTRL_LOGEST                  33
 #define SQLITE_TESTCTRL_USELONGDOUBLE           34  /* NOT USED */
+#define SQLITE_TESTCTRL_ATOF                    34
 #define SQLITE_TESTCTRL_LAST                    34  /* Largest TESTCTRL */
 
 /*
index d7ecdc0108d75d7f53701334ec6ce801bddb05f1..03b310aa7dc63c12a01432a7ebd19e3e0bd40a9d 100644 (file)
@@ -822,23 +822,29 @@ static double sqlite3Fp10Convert2(u64 d, int p){
 ** zero or negative if the string is empty or contains extraneous text.
 ** More specifically:
 **
+**      2          =>  The input has a decimal point and/or eNNN clause
 **      1          =>  The input string is a pure integer
-**      2 or more  =>  The input has a decimal point or eNNN clause
-**      0 or less  =>  The input string is not well-formed
+**      0          =>  The input string is not well-formed
 **     -1          =>  The input is not well-formed, but it does begin
-**                     with a well-formed floating-point literal (with
-**                     a "." or a "eNNN" suffix or both) followed by
-**                     other extraneous text.
+**                     with a well-formed integer prefix
+**     -2          =>  The input is not well-formed, but it does begin
+**                     with a well-formed floating-point prefix with a
+**                     decimal point and/or eNNN clause
 **
-** Valid numbers are in one of these formats:
+** Return codes are organized as follows:
+**
+**     1 or more   =>  Input string is well-formed
+**     0           =>  No prefix of the input looks like a number
+**     -1 or less  =>  Some prefix of the input looks like a number
+**                     but the prefix is followed by extraneous text
+**
+** Leading and trailing whitespace is ignored.  Valid numbers are in
+** one of the formats below:
 **
 **    [+-]digits[E[+-]digits]
 **    [+-]digits.[digits][E[+-]digits]
 **    [+-].digits[E[+-]digits]
 **
-** Leading and trailing whitespace is ignored for the purpose of determining
-** validity.
-**
 ** Algorithm sketch:  Compute an unsigned 64-bit integer s and a base-10
 ** exponent d such that the value encoding by the input is s*pow(10,d).
 ** Then invoke sqlite3Fp10Convert2() to calculated the closest possible
@@ -943,9 +949,6 @@ int sqlite3AtoF(const char *zIn, double *pResult){
     }
   }
 
-  /* skip trailing spaces */
-  while( sqlite3Isspace(*z) ) z++;
-
   /* Convert s*pow(10,d) into real */
   *pResult = s ? sqlite3Fp10Convert2(s,d) : 0.0;
   if( neg ) *pResult = -*pResult;
@@ -954,13 +957,16 @@ int sqlite3AtoF(const char *zIn, double *pResult){
   /* return true if number and no extra non-whitespace characters after */
   if( z[0]==0 ){
     return seenFP+1;
-  }else if( seenFP ){
-    return -1;   /* Prefix is a floating point number */
-  }else{
-    return 0;    /* Prefix is just an integer */
   }
+  if( sqlite3Isspace(z[0]) ){
+    do{ z++; }while( sqlite3Isspace(*z) );
+    if( z[0]==0 ){
+      return seenFP+1;
+    }
+  }
+  return -1-seenFP;
 #else
-  return !sqlite3Atoi64(z, pResult, strlen(z), SQLITE_UTF8);
+  return sqlite3Atoi64(z, pResult, strlen(z), SQLITE_UTF8)==0;
 #endif /* SQLITE_OMIT_FLOATING_POINT */
 }
 
index 0fcd26992b9b1241cf1ab25035f9fad46a4e67aa..e1b78a90f3c05230307f219de7eaa468aec823fc 100644 (file)
@@ -475,7 +475,7 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
   }
   rc = sqlite3MemRealValueRC(pMem, &pMem->u.r);
   if( rc<=0 ){
-    if( rc==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){
+    if( rc>=(-1) && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){
       pMem->u.i = ix;
       return MEM_Int;
     }else{
index 5fe1e03963bd226025831826065d03b90b87e227..ce247a0e5e5bbc5f8caca17160086d90a33a8228 100644 (file)
@@ -658,9 +658,20 @@ i64 sqlite3VdbeIntValue(const Mem *pMem){
 
 /*
 ** This routine implements the uncommon and slower path for
-** sqlite3MemValueRC().  It is broken out into a separate
-** no-inline routine so that the main routine can avoid unnecessary
+** sqlite3MemRealValueRC() that has to deal with input strings
+** that are not UTF8 or that are not zero-terminated.  It is
+** broken out into a separate no-inline routine so that the
+** main sqlite3MemRealValueRC() routine can avoid unnecessary
 ** stack pushes.
+**
+** A text->float translation of pMem->z is written into *pValue.
+**
+** Return values:
+**
+**    0 or less     =>   ERROR: Input string not well-formed, or OOM
+**    1             =>   Input string is a well-formed integer
+**    2 or more     =>   Input string is well-formed
+**   
 */
 static SQLITE_NOINLINE int sqlite3MemRealValueRCSlowPath(
   Mem *pMem,
@@ -706,12 +717,18 @@ static SQLITE_NOINLINE int sqlite3MemRealValueRCSlowPath(
 }
 
 /*
-** Invoke sqlite3AtoF() on the text value of pMem and return the
-** double result.  If sqlite3AtoF() returns an error code, write
-** that code into *pRC if (*pRC)!=NULL.
+** Invoke sqlite3AtoF() on the text value of pMem.  Write the
+** translation of the text input into *pValue.
 **
 ** The caller must ensure that pMem->db!=0 and that pMem is in
 ** mode MEM_Str or MEM_Blob.
+**
+** Return values:
+**
+**    0 or less     =>   ERROR: Input string not well-formed, or OOM
+**    1             =>   Input string is a well-formed integer
+**    2 or more     =>   Input string is well-formed
+**   
 */
 int sqlite3MemRealValueRC(Mem *pMem, double *pValue){
   assert( pMem->db!=0 );
@@ -883,7 +900,7 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
     assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
     assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
     rc = sqlite3MemRealValueRC(pMem, &pMem->u.r);
-    if( ((rc==0 || rc==1) && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1)
+    if( (rc<2 && rc>-2 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<2)
      || sqlite3RealSameAsInt(pMem->u.r, (ix = sqlite3RealToI64(pMem->u.r)))
     ){
       pMem->u.i = ix;