From: drh <> Date: Thu, 26 Mar 2026 16:33:03 +0000 (+0000) Subject: Revamp the return code from sqlite3AtoF() for additional information and X-Git-Tag: major-release~43 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=61d3bc8ddcd890ecbd12773abd5139a3bee2cc27;p=thirdparty%2Fsqlite.git Revamp the return code from sqlite3AtoF() for additional information and for small speed improvement and size reduction. FossilOrigin-Name: f10a431eade20ecd4c4d501fc534e2dae6ab2fe67302ea7bb3cd6eba127848fc --- diff --git a/manifest b/manifest index 4848e32c6d..015227fdbc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improvements\sto\sthe\ssqlite3AtoF()\sinterface.\s\sAdd\sa\stest-control\sfor\ndirect\stesting\sof\ssqlite3AtoF(). -D 2026-03-26T14:19:34.547 +C Revamp\sthe\sreturn\scode\sfrom\ssqlite3AtoF()\sfor\sadditional\sinformation\sand\nfor\ssmall\sspeed\simprovement\sand\ssize\sreduction. +D 2026-03-26T16:33:03.990 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -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 70a0a775c6eb824f271862b0acc11557370d2c4e5e2c21188bae60123393748e +F src/util.c 363fb8548ac2f321b01de1d2847d4492a5dd8932c61961fe555eb779093b52c5 F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82 -F src/vdbe.c edff242cffa6d8fbd887415e93c36eadd021c6c66fbdd4f674d77d2baf7721d8 +F src/vdbe.c 6c57525d7db0232d52687d30da1093db0c152f14206c2ef1adf0c19a09d863e3 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 763fdd94602cbefbf7f7aeef6066fdcd538bc78a26389b5e36f077619d12836c +F src/vdbemem.c 5af6cf1253ac2aed0612b85138a1faf43f30ad38777d554db6c85b7281fa79fb F src/vdbesort.c b69220f4ea9ffea5fdef34d968c60305444eea909252a81933b54c296d9cca70 F src/vdbetrace.c 49e689f751505839742f4a243a1a566e57d5c9eaf0d33bbaa26e2de3febf7b41 F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3 @@ -2195,8 +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 7568d264be3988df195401158d8d07105b8e9e018eccf98ac948219bee9388ac -R aa44cc101bc358c488049f6ff4abf07f +P 97ee48b6ef65fb55633196282c9e75b3b0a3b81ba9755f63493a38e3f1a5610c +R ddd719e3f218d9b203be0a8d1b14da98 U drh -Z 14ff26432a141106839fde7c9ab19978 +Z e90bb32a1cf83cea1813c00b1f84eb7b # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 73e7dea186..e702f74828 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -97ee48b6ef65fb55633196282c9e75b3b0a3b81ba9755f63493a38e3f1a5610c +f10a431eade20ecd4c4d501fc534e2dae6ab2fe67302ea7bb3cd6eba127848fc diff --git a/src/util.c b/src/util.c index 03b310aa7d..b4e7031cb3 100644 --- a/src/util.c +++ b/src/util.c @@ -820,23 +820,19 @@ static double sqlite3Fp10Convert2(u64 d, int p){ ** ** Return positive if the result is a valid real number (or integer) and ** zero or negative if the string is empty or contains extraneous text. -** More specifically: +** Lower bits of the return value contain addition information about the +** parse: ** -** 2 => The input has a decimal point and/or eNNN clause -** 1 => The input string is a pure integer -** 0 => The input string is not well-formed -** -1 => The input is not well-formed, but it does begin -** 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 +** bit 0 => Set for any valid input +** bit 1 => Input contains a decimal point or eNNN clause +** This bit is zero if the input is an integer +** bit 2 => The input is exactly 0.0, not an underflow from +** some value near zero ** -** 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 +** If the input contains a syntax error but begins with text that might +** be a valid number of some kind, then the result is negative. The +** result is only zero if no prefix of the input could be interpreted as +** a number. ** ** Leading and trailing whitespace is ignored. Valid numbers are in ** one of the formats below: @@ -865,14 +861,13 @@ int sqlite3AtoF(const char *zIn, double *pResult){ int neg = 0; /* True for a negative value */ u64 s = 0; /* mantissa */ int d = 0; /* Value is s * pow(10,d) */ - int seenDigit = 0; /* true if any digits seen */ - int seenFP = 0; /* True if we've seen a "." or a "e" */ + int mState = 0; /* 1: digit seen 2: fp 4: hard-zero */ unsigned v; /* Value of a single digit */ start_of_text: if( (v = (unsigned)z[0] - '0')<10 ){ parse_integer_part: - seenDigit = 1; + mState = 1; s = v; z++; while( (v = (unsigned)z[0] - '0')<10 ){ @@ -900,9 +895,8 @@ int sqlite3AtoF(const char *zIn, double *pResult){ /* if decimal point is present */ if( *z=='.' ){ z++; - seenFP = 1; if( sqlite3Isdigit(z[0]) ){ - seenDigit = 1; + mState |= 1; do{ if( s<((LARGEST_INT64-9)/10) ){ s = s*10 + z[0] - '0'; @@ -910,10 +904,12 @@ int sqlite3AtoF(const char *zIn, double *pResult){ } z++; }while( sqlite3Isdigit(z[0]) ); + }else if( mState==0 ){ + *pResult = 0.0; + return 0; } - } - - if( !seenDigit ){ + mState |= 2; + }else if( mState==0 ){ *pResult = 0.0; return 0; } @@ -937,7 +933,7 @@ int sqlite3AtoF(const char *zIn, double *pResult){ if( (v = (unsigned)z[0] - '0')<10 ){ int exp = v; z++; - seenFP = 1; + mState |= 2; while( (v = (unsigned)z[0] - '0')<10 ){ exp = exp<10000 ? (exp*10 + v) : 10000; z++; @@ -950,21 +946,26 @@ int sqlite3AtoF(const char *zIn, double *pResult){ } /* Convert s*pow(10,d) into real */ - *pResult = s ? sqlite3Fp10Convert2(s,d) : 0.0; + if( s==0 ){ + *pResult = 0.0; + mState |= 4; + }else{ + *pResult = sqlite3Fp10Convert2(s,d); + } if( neg ) *pResult = -*pResult; assert( !sqlite3IsNaN(*pResult) ); /* return true if number and no extra non-whitespace characters after */ if( z[0]==0 ){ - return seenFP+1; + return mState; } if( sqlite3Isspace(z[0]) ){ do{ z++; }while( sqlite3Isspace(*z) ); if( z[0]==0 ){ - return seenFP+1; + return mState; } } - return -1-seenFP; + return 0xfffffff0 | mState; #else return sqlite3Atoi64(z, pResult, strlen(z), SQLITE_UTF8)==0; #endif /* SQLITE_OMIT_FLOATING_POINT */ diff --git a/src/vdbe.c b/src/vdbe.c index e1b78a90f3..20b96d4721 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -357,7 +357,7 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){ assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_IntReal))==MEM_Str ); rc = sqlite3MemRealValueRC(pRec, &rValue); if( rc<=0 ) return; - if( rc==1 && alsoAnInt(pRec, rValue, &pRec->u.i) ){ + if( (rc&2)==0 && alsoAnInt(pRec, rValue, &pRec->u.i) ){ pRec->flags |= MEM_Int; }else{ pRec->u.r = rValue; @@ -475,13 +475,13 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){ } rc = sqlite3MemRealValueRC(pMem, &pMem->u.r); if( rc<=0 ){ - if( rc>=(-1) && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){ + if( (rc&2)==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){ pMem->u.i = ix; return MEM_Int; }else{ return MEM_Real; } - }else if( rc==1 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)==0 ){ + }else if( (rc&2)==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)==0 ){ pMem->u.i = ix; return MEM_Int; } diff --git a/src/vdbemem.c b/src/vdbemem.c index ce247a0e5e..c4e7a8fc56 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -666,12 +666,13 @@ i64 sqlite3VdbeIntValue(const Mem *pMem){ ** ** A text->float translation of pMem->z is written into *pValue. ** -** Return values: +** Result code invariants: ** -** 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 -** +** rc==0 => ERROR: Input string not well-formed, or OOM +** rc<0 => Some prefix of the input is well-formed +** rc>0 => All of the input is well-formed +** (rc&2)==0 => The number is expressed as an integer, with no +** decimal point or eNNN suffix. */ static SQLITE_NOINLINE int sqlite3MemRealValueRCSlowPath( Mem *pMem, @@ -723,12 +724,13 @@ static SQLITE_NOINLINE int sqlite3MemRealValueRCSlowPath( ** The caller must ensure that pMem->db!=0 and that pMem is in ** mode MEM_Str or MEM_Blob. ** -** Return values: +** Result code invariants: ** -** 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 -** +** rc==0 => ERROR: Input string not well-formed, or OOM +** rc<0 => Some prefix of the input is well-formed +** rc>0 => All of the input is well-formed +** (rc&2)==0 => The number is expressed as an integer, with no +** decimal point or eNNN suffix. */ int sqlite3MemRealValueRC(Mem *pMem, double *pValue){ assert( pMem->db!=0 ); @@ -900,7 +902,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<2 && rc>-2 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<2) + if( ((rc&2)==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<2) || sqlite3RealSameAsInt(pMem->u.r, (ix = sqlite3RealToI64(pMem->u.r))) ){ pMem->u.i = ix;