Skip to content

Commit 61d3bc8

Browse files
author
drh
committed
Revamp the return code from sqlite3AtoF() for additional information and
for small speed improvement and size reduction. FossilOrigin-Name: f10a431eade20ecd4c4d501fc534e2dae6ab2fe67302ea7bb3cd6eba127848fc
1 parent f9a3b78 commit 61d3bc8

5 files changed

Lines changed: 54 additions & 51 deletions

File tree

manifest

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
C Improvements\sto\sthe\ssqlite3AtoF()\sinterface.\s\sAdd\sa\stest-control\sfor\ndirect\stesting\sof\ssqlite3AtoF().
2-
D 2026-03-26T14:19:34.547
1+
C Revamp\sthe\sreturn\scode\sfrom\ssqlite3AtoF()\sfor\sadditional\sinformation\sand\nfor\ssmall\sspeed\simprovement\sand\ssize\sreduction.
2+
D 2026-03-26T16:33:03.990
33
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
44
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
55
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -798,15 +798,15 @@ F src/trigger.c 4bf3bfb3851d165e4404a9f9e69357345f3f7103378c07e07139fdd8aeb7bd20
798798
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
799799
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
800800
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
801-
F src/util.c 70a0a775c6eb824f271862b0acc11557370d2c4e5e2c21188bae60123393748e
801+
F src/util.c 363fb8548ac2f321b01de1d2847d4492a5dd8932c61961fe555eb779093b52c5
802802
F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
803-
F src/vdbe.c edff242cffa6d8fbd887415e93c36eadd021c6c66fbdd4f674d77d2baf7721d8
803+
F src/vdbe.c 6c57525d7db0232d52687d30da1093db0c152f14206c2ef1adf0c19a09d863e3
804804
F src/vdbe.h 70e862ac8a11b590f8c1eaac17a0078429d42bc4ea3f757a9af0f451dd966a71
805805
F src/vdbeInt.h c31ba4dc8d280c2b1dc89c6fcee68f2555e3813ab34279552c20b964c0e338b1
806806
F src/vdbeapi.c 6cdcbe5c7afa754c998e73d2d5d2805556268362914b952811bdfb9c78a37cf1
807807
F src/vdbeaux.c 81687c55682b9f4d942186695f4f7fa4743c564a985e0889def52eded9076d61
808808
F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692
809-
F src/vdbemem.c 763fdd94602cbefbf7f7aeef6066fdcd538bc78a26389b5e36f077619d12836c
809+
F src/vdbemem.c 5af6cf1253ac2aed0612b85138a1faf43f30ad38777d554db6c85b7281fa79fb
810810
F src/vdbesort.c b69220f4ea9ffea5fdef34d968c60305444eea909252a81933b54c296d9cca70
811811
F src/vdbetrace.c 49e689f751505839742f4a243a1a566e57d5c9eaf0d33bbaa26e2de3febf7b41
812812
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
@@ -2195,8 +2195,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
21952195
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
21962196
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
21972197
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
2198-
P 7568d264be3988df195401158d8d07105b8e9e018eccf98ac948219bee9388ac
2199-
R aa44cc101bc358c488049f6ff4abf07f
2198+
P 97ee48b6ef65fb55633196282c9e75b3b0a3b81ba9755f63493a38e3f1a5610c
2199+
R ddd719e3f218d9b203be0a8d1b14da98
22002200
U drh
2201-
Z 14ff26432a141106839fde7c9ab19978
2201+
Z e90bb32a1cf83cea1813c00b1f84eb7b
22022202
# Remove this line to create a well-formed Fossil manifest.

manifest.uuid

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
97ee48b6ef65fb55633196282c9e75b3b0a3b81ba9755f63493a38e3f1a5610c
1+
f10a431eade20ecd4c4d501fc534e2dae6ab2fe67302ea7bb3cd6eba127848fc

src/util.c

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -820,23 +820,19 @@ static double sqlite3Fp10Convert2(u64 d, int p){
820820
**
821821
** Return positive if the result is a valid real number (or integer) and
822822
** zero or negative if the string is empty or contains extraneous text.
823-
** More specifically:
823+
** Lower bits of the return value contain addition information about the
824+
** parse:
824825
**
825-
** 2 => The input has a decimal point and/or eNNN clause
826-
** 1 => The input string is a pure integer
827-
** 0 => The input string is not well-formed
828-
** -1 => The input is not well-formed, but it does begin
829-
** with a well-formed integer prefix
830-
** -2 => The input is not well-formed, but it does begin
831-
** with a well-formed floating-point prefix with a
832-
** decimal point and/or eNNN clause
826+
** bit 0 => Set for any valid input
827+
** bit 1 => Input contains a decimal point or eNNN clause
828+
** This bit is zero if the input is an integer
829+
** bit 2 => The input is exactly 0.0, not an underflow from
830+
** some value near zero
833831
**
834-
** Return codes are organized as follows:
835-
**
836-
** 1 or more => Input string is well-formed
837-
** 0 => No prefix of the input looks like a number
838-
** -1 or less => Some prefix of the input looks like a number
839-
** but the prefix is followed by extraneous text
832+
** If the input contains a syntax error but begins with text that might
833+
** be a valid number of some kind, then the result is negative. The
834+
** result is only zero if no prefix of the input could be interpreted as
835+
** a number.
840836
**
841837
** Leading and trailing whitespace is ignored. Valid numbers are in
842838
** one of the formats below:
@@ -865,14 +861,13 @@ int sqlite3AtoF(const char *zIn, double *pResult){
865861
int neg = 0; /* True for a negative value */
866862
u64 s = 0; /* mantissa */
867863
int d = 0; /* Value is s * pow(10,d) */
868-
int seenDigit = 0; /* true if any digits seen */
869-
int seenFP = 0; /* True if we've seen a "." or a "e" */
864+
int mState = 0; /* 1: digit seen 2: fp 4: hard-zero */
870865
unsigned v; /* Value of a single digit */
871866

872867
start_of_text:
873868
if( (v = (unsigned)z[0] - '0')<10 ){
874869
parse_integer_part:
875-
seenDigit = 1;
870+
mState = 1;
876871
s = v;
877872
z++;
878873
while( (v = (unsigned)z[0] - '0')<10 ){
@@ -900,20 +895,21 @@ int sqlite3AtoF(const char *zIn, double *pResult){
900895
/* if decimal point is present */
901896
if( *z=='.' ){
902897
z++;
903-
seenFP = 1;
904898
if( sqlite3Isdigit(z[0]) ){
905-
seenDigit = 1;
899+
mState |= 1;
906900
do{
907901
if( s<((LARGEST_INT64-9)/10) ){
908902
s = s*10 + z[0] - '0';
909903
d--;
910904
}
911905
z++;
912906
}while( sqlite3Isdigit(z[0]) );
907+
}else if( mState==0 ){
908+
*pResult = 0.0;
909+
return 0;
913910
}
914-
}
915-
916-
if( !seenDigit ){
911+
mState |= 2;
912+
}else if( mState==0 ){
917913
*pResult = 0.0;
918914
return 0;
919915
}
@@ -937,7 +933,7 @@ int sqlite3AtoF(const char *zIn, double *pResult){
937933
if( (v = (unsigned)z[0] - '0')<10 ){
938934
int exp = v;
939935
z++;
940-
seenFP = 1;
936+
mState |= 2;
941937
while( (v = (unsigned)z[0] - '0')<10 ){
942938
exp = exp<10000 ? (exp*10 + v) : 10000;
943939
z++;
@@ -950,21 +946,26 @@ int sqlite3AtoF(const char *zIn, double *pResult){
950946
}
951947

952948
/* Convert s*pow(10,d) into real */
953-
*pResult = s ? sqlite3Fp10Convert2(s,d) : 0.0;
949+
if( s==0 ){
950+
*pResult = 0.0;
951+
mState |= 4;
952+
}else{
953+
*pResult = sqlite3Fp10Convert2(s,d);
954+
}
954955
if( neg ) *pResult = -*pResult;
955956
assert( !sqlite3IsNaN(*pResult) );
956957

957958
/* return true if number and no extra non-whitespace characters after */
958959
if( z[0]==0 ){
959-
return seenFP+1;
960+
return mState;
960961
}
961962
if( sqlite3Isspace(z[0]) ){
962963
do{ z++; }while( sqlite3Isspace(*z) );
963964
if( z[0]==0 ){
964-
return seenFP+1;
965+
return mState;
965966
}
966967
}
967-
return -1-seenFP;
968+
return 0xfffffff0 | mState;
968969
#else
969970
return sqlite3Atoi64(z, pResult, strlen(z), SQLITE_UTF8)==0;
970971
#endif /* SQLITE_OMIT_FLOATING_POINT */

src/vdbe.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){
357357
assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_IntReal))==MEM_Str );
358358
rc = sqlite3MemRealValueRC(pRec, &rValue);
359359
if( rc<=0 ) return;
360-
if( rc==1 && alsoAnInt(pRec, rValue, &pRec->u.i) ){
360+
if( (rc&2)==0 && alsoAnInt(pRec, rValue, &pRec->u.i) ){
361361
pRec->flags |= MEM_Int;
362362
}else{
363363
pRec->u.r = rValue;
@@ -475,13 +475,13 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
475475
}
476476
rc = sqlite3MemRealValueRC(pMem, &pMem->u.r);
477477
if( rc<=0 ){
478-
if( rc>=(-1) && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){
478+
if( (rc&2)==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){
479479
pMem->u.i = ix;
480480
return MEM_Int;
481481
}else{
482482
return MEM_Real;
483483
}
484-
}else if( rc==1 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)==0 ){
484+
}else if( (rc&2)==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)==0 ){
485485
pMem->u.i = ix;
486486
return MEM_Int;
487487
}

src/vdbemem.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -666,12 +666,13 @@ i64 sqlite3VdbeIntValue(const Mem *pMem){
666666
**
667667
** A text->float translation of pMem->z is written into *pValue.
668668
**
669-
** Return values:
669+
** Result code invariants:
670670
**
671-
** 0 or less => ERROR: Input string not well-formed, or OOM
672-
** 1 => Input string is a well-formed integer
673-
** 2 or more => Input string is well-formed
674-
**
671+
** rc==0 => ERROR: Input string not well-formed, or OOM
672+
** rc<0 => Some prefix of the input is well-formed
673+
** rc>0 => All of the input is well-formed
674+
** (rc&2)==0 => The number is expressed as an integer, with no
675+
** decimal point or eNNN suffix.
675676
*/
676677
static SQLITE_NOINLINE int sqlite3MemRealValueRCSlowPath(
677678
Mem *pMem,
@@ -723,12 +724,13 @@ static SQLITE_NOINLINE int sqlite3MemRealValueRCSlowPath(
723724
** The caller must ensure that pMem->db!=0 and that pMem is in
724725
** mode MEM_Str or MEM_Blob.
725726
**
726-
** Return values:
727+
** Result code invariants:
727728
**
728-
** 0 or less => ERROR: Input string not well-formed, or OOM
729-
** 1 => Input string is a well-formed integer
730-
** 2 or more => Input string is well-formed
731-
**
729+
** rc==0 => ERROR: Input string not well-formed, or OOM
730+
** rc<0 => Some prefix of the input is well-formed
731+
** rc>0 => All of the input is well-formed
732+
** (rc&2)==0 => The number is expressed as an integer, with no
733+
** decimal point or eNNN suffix.
732734
*/
733735
int sqlite3MemRealValueRC(Mem *pMem, double *pValue){
734736
assert( pMem->db!=0 );
@@ -900,7 +902,7 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
900902
assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
901903
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
902904
rc = sqlite3MemRealValueRC(pMem, &pMem->u.r);
903-
if( (rc<2 && rc>-2 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<2)
905+
if( ((rc&2)==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<2)
904906
|| sqlite3RealSameAsInt(pMem->u.r, (ix = sqlite3RealToI64(pMem->u.r)))
905907
){
906908
pMem->u.i = ix;

0 commit comments

Comments
 (0)