/* The sqlite3AtoF() routine is much much faster than atof(), if it
** is available */
double r;
- (void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8);
+ assert( p->z[j]==0 );
+ (void)sqlite3AtoF((const char*)p->z, &r);
*pVal = r;
#else
*pVal = (GeoCoord)atof((const char*)p->z);
-C Fix\sa\sproblem\swith\sidentifying\sON\sclauses\sattached\sto\sRIGHT\sor\sFULL\sJOINs\s(which\sis\san\serror)\sif\sthe\sjoin\sappeared\sin\sa\sflattened\ssub-query.
-D 2026-02-16T11:59:14.701
+C Refactor\sthe\ssqlite3AtoF()\sroutine\sso\sthat\sit\srequires\sa\szero-terminated\nUTF-8\sinput.\s\sWhen\sthe\sneed\sarises\sto\sconvert\sUTF16\sor\snon-terminated\nstrings,\swrapper\sfunctions\sare\sused.\s\sTogether,\sthis\smakes\sthe\scode\sslightly\nsmaller\sand\sfaster.
+D 2026-02-16T16:56:59.150
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 734aa36238bcd2dee91db5dba107d5fcbdb02396612811377a8ad50f1272b1c1
-F ext/rtree/geopoly.c f0573d5109fdc658a180db0db6eec86ab2a1cf5ce58ec66cbf3356167ea757eb
+F ext/rtree/geopoly.c 8317e860e8b2b61c7772956e6da5351268428d1530f5bc5345f50c82e90fa5c0
F ext/rtree/rtree.c 9331997a76b88a9bc04e156bdfd6e2fe35c0aa93bc338ebc6aa0ae470fe4a852
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test e0608db762b2aadca0ecb6f97396cf66244490adc3ba88f2a292b27be3e1da3e
F src/callback.c 3605bbf02bd7ed46c79cd48346db4a32fc51d67624400539c0532f4eead804ad
F src/carray.c 3efe3982d5fb323334c29328a4e189ccaef6b95612a6084ad5fa124fd5db1179
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
-F src/date.c e19e0cfff9a41bfdd884c655755f6f00bca4c1a22272b56e0dd6667b7ea893a2
+F src/date.c e1a6c5ac4753016198d664d633b8541fa4ad4ccde2beb12548fa99e746f38cec
F src/dbpage.c c9ea81c11727f27e02874611e92773e68e2a90a875ef2404b084564c235fd91f
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 901499bed747c3b4b2be45be1abe912ba50a3f6a40ba88cc006ccf279f2d0e97
-F src/expr.c c4ff8dcacbc8962fb670fc7c9723c8346398795b16ce2f78439234769baee2e6
+F src/expr.c 8c3b23cb35f43c2d0570c1058b9a269e561e769e09c81ba192992c95022c1939
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c fb0f74c57d19a2d3f113f3476826919d68feda7ff334abfdb479a9a6353b9fcd
-F src/func.c 6b6797b1b8d90c40482795a9a571041ca09bd520c5fa85cb1a49be143eda0bcf
+F src/func.c 785f62a6e00636c9b185ccee0cde17be711458227340137d57492ed3226d4253
F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
F src/hash.c 03c8c0f4be9e8bcb6de65aa26d34a61d48a9430747084a69f9469fbb00ea52ca
F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
F src/hwtime.h 21c2cf1f736e7b97502c3674d0c386db3f06870d6f10d0cf8174e2a4b8cb726e
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
-F src/json.c af766b62caee01c735cfe7795cc91ffea5a5e1c555a5d8a9aa5a301f00a1b0ad
+F src/json.c 8b6341a419150b28530cc21e3951b2238c35cdc312f11b2ca29017fe4b1dedc0
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 56a542244fbefc739a2ef57fac007c16b2aefdb4377f584e9547db2ce3e071f9
F src/main.c e95aa130478fc98a49181ddf094baab45f319286411129253618efe0008f0dc4
F src/prepare.c f6a6e28a281bd1d1da12f47d370a81af46159b40f73bf7fa0b276b664f9c8b7d
F src/printf.c b1b29b5e58e1530d5daeee5963d3c318d8ab2d7e38437580e28755753e0c1ded
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
-F src/resolve.c c1dcb80bea2c37e6d01fea793e4f5f6f6254569f3a3aecf18d88b6fc3702a84b
+F src/resolve.c 57020e1b499b7189953c59ce8a4db9fe7fdc849b47d583b1e1eb50c9dd1d1733
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 615d62112f5c14fb24facf9391492b42403875bfd4288db6ba10d7e6fbc22c4c
F src/shell.c.in b944a21d98cc4c6107bfd1ec702440579cb4bf86435125b67ff661180e9453b5
F src/sqlite.h.in 8bcbaecfe2cbecf8c5c1381354fcdd7d307443e88b4953fccb222456c1267b61
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca
-F src/sqliteInt.h 908d5522b3b362c2b968b6a6ee2f495a32e2d4da971209ac43810a0b081f1d90
+F src/sqliteInt.h cd77fd03f7bf9d7b012a28c96cacdd20f09054bfe4edcebd92f789f0bc37c9fb
F src/sqliteLimit.h 904a3f520362c7065c18165aaabd504fb13cc1b76cb411f38bd41ac219e4af1e
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
-F src/util.c 0cc410d538fe13a2cda90a8d0087c82cf4c1ab0d5055b8e3a595f28266f190c7
+F src/util.c 16c7fcce87e43c612dd579c87d11a085ce5243565b7c324806f4a506c5e696a4
F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
-F src/vdbe.c fa28a8f740f3d94c4e6b6d42ba90c220472683486268e753017512a70ef715f5
+F src/vdbe.c 5328c99dd256ee8132383565a86e253543a85daccfd7477c52f20bac6b385a7f
F src/vdbe.h 966d0677a540b7ea6549b7c4e1312fc0d830fce3a235a58c801f2cc31cf5ecf9
-F src/vdbeInt.h c45d0195dad0a9099132109e3b63697f4f119baddeb391c36ca226cee530a485
+F src/vdbeInt.h 42488247a80cd9d300627833c6c85ace067ae5011a99e7614e2358130d62feea
F src/vdbeapi.c 6cdcbe5c7afa754c998e73d2d5d2805556268362914b952811bdfb9c78a37cf1
F src/vdbeaux.c 396d38a62a357b807eabae0cae441fc89d2767a57ab08026b7072bf7aa2dd00c
F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692
-F src/vdbemem.c 699d2fb0a59a00cf9b77898653167673de60fa5577e07bd6bee6adaef5fdc374
+F src/vdbemem.c bdfda8e65933cfee34aa29c2bfa31fc07609f3d56d147aa8a367a297533d33d1
F src/vdbesort.c b69220f4ea9ffea5fdef34d968c60305444eea909252a81933b54c296d9cca70
F src/vdbetrace.c 49e689f751505839742f4a243a1a566e57d5c9eaf0d33bbaa26e2de3febf7b41
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
F src/where.c 7a7fe745dd8104d0276a3d3f6e6ac7f087af3dd9f34a90bc937e5e7aea817e15
F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
F src/wherecode.c 783ecd30061c875c919a5163e4b55f9a0eccdaf7c9b17ad2908a1668a8766bc4
-F src/whereexpr.c bb649ce81bd6dc0eabfa2533ff5656fc7a16411e520a6c59be43e73e51503cce
+F src/whereexpr.c e9f7185fba366d9365aa7a97329609e4cf00b3dd0400d069fbaa5187350c17c6
F src/window.c c0a38cd32473e8e8e7bc435039f914a36ca42465506dc491c65870c01ddac9fb
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P b5ebbd004183f81902fa79a143222204b33dbe1cacb918194556b8dac67bd567
-R 962f4ef1dbd316a124811ac609d56f62
-U dan
-Z 5af30b1d418ec7aa73d461b781393237
+P cf2dc6dfad275dad8fef763a57baaaf6301b0d3bf1916be90f22200cbe0115d0
+R 437155dd45848e71532967f5113d7bd1
+T *branch * numeric-conversion-perf
+T *sym-numeric-conversion-perf *
+T -sym-trunk *
+U drh
+Z 37bb3fa124d03f3d009e27255e0475da
# Remove this line to create a well-formed Fossil manifest.
-branch trunk
-tag trunk
+branch numeric-conversion-perf
+tag numeric-conversion-perf
-cf2dc6dfad275dad8fef763a57baaaf6301b0d3bf1916be90f22200cbe0115d0
+67c7c72e9bdf04c920d77006538a202c923fa74b47c81dc3014c2929dac7277d
return 0;
}else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){
return setDateTimeToCurrent(context, p);
- }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8)>0 ){
+ }else if( sqlite3AtoF(zDate, &r)>0 ){
setRawDateNumber(p, r);
return 0;
}else if( (sqlite3StrICmp(zDate,"subsec")==0
** date is already on the appropriate weekday, this is a no-op.
*/
if( sqlite3_strnicmp(z, "weekday ", 8)==0
- && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)>0
+ && sqlite3AtoF(&z[8], &r)>0
&& r>=0.0 && r<7.0 && (n=(int)r)==r ){
sqlite3_int64 Z;
computeYMD_HMS(p);
case '8':
case '9': {
double rRounder;
- int i;
+ int i, rx;
int Y,M,D,h,m,x;
const char *z2 = z;
+ char *zCopy;
+ sqlite3 *db = sqlite3_context_db_handle(pCtx);
char z0 = z[0];
for(n=1; z[n]; n++){
if( z[n]==':' ) break;
if( n==6 && getDigits(&z[1], "50f", &Y)==1 ) break;
}
}
- if( sqlite3AtoF(z, &r, n, SQLITE_UTF8)<=0 ){
+ zCopy = sqlite3DbStrNDup(db, z, n);
+ if( zCopy==0 ) break;
+ rx = sqlite3AtoF(zCopy, &r)<=0;
+ sqlite3DbFree(db, zCopy);
+ if( rx ){
assert( rc==1 );
break;
}
static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
if( ALWAYS(z!=0) ){
double value;
- sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
+ sqlite3AtoF(z, &value);
assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */
if( negateFlag ) value = -value;
sqlite3VdbeAddOp4Dup8(v, OP_Real, 0, iMem, 0, (u8*)&value, P4_REAL);
sqlite3_result_error_nomem(context);
return;
}
- sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8);
+ sqlite3AtoF(zBuf, &r);
sqlite3_free(zBuf);
}
sqlite3_result_double(context, r);
sqlite3_str_appendf(pStr, "%!0.15g", r1);
zVal = sqlite3_str_value(pStr);
if( zVal ){
- sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8);
+ sqlite3AtoF(zVal, &r2);
if( r1!=r2 ){
sqlite3_str_reset(pStr);
sqlite3_str_appendf(pStr, "%!0.20e", r1);
to_double:
z = sqlite3DbStrNDup(db, (const char*)&pParse->aBlob[i+n], (int)sz);
if( z==0 ) goto returnfromblob_oom;
- rc = sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8);
+ rc = sqlite3AtoF(z, &r);
sqlite3DbFree(db, z);
if( rc<=0 ) goto returnfromblob_malformed;
sqlite3_result_double(pCtx, r);
double r = -1.0;
if( p->op!=TK_FLOAT ) return -1;
assert( !ExprHasProperty(p, EP_IntValue) );
- sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8);
+ sqlite3AtoF(p->u.zToken, &r);
assert( r>=0.0 );
if( r>1.0 ) return -1;
return (int)(r*134217728.0);
int sqlite3RealSameAsInt(double,sqlite3_int64);
i64 sqlite3RealToI64(double);
int sqlite3Int64ToText(i64,char*);
-int sqlite3AtoF(const char *z, double*, int, u8);
+int sqlite3AtoF(const char *z, double*);
int sqlite3GetInt32(const char *, int*);
int sqlite3GetUInt32(const char*, u32*);
int sqlite3Atoi(const char*);
** The string z[] is an text representation of a real number.
** Convert this string to a double and write it into *pResult.
**
-** The string z[] is length bytes in length (bytes, not characters) and
-** uses the encoding enc. The string is not necessarily zero-terminated.
+** z[] must be UTF-8 and zero-terminated.
**
** Return TRUE if the result is a valid real number (or integer) and FALSE
** if the string is empty or contains extraneous text. More specifically
#if defined(_MSC_VER)
#pragma warning(disable : 4756)
#endif
-int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
+int sqlite3AtoF(const char *z, double *pResult){
#ifndef SQLITE_OMIT_FLOATING_POINT
- int incr;
- const char *zEnd;
/* sign * significand * (10 ^ (esign * exponent)) */
int sign = 1; /* sign of significand */
u64 s = 0; /* significand */
int e = 0; /* exponent */
int eValid = 1; /* True exponent is either not used or is well-formed */
int nDigit = 0; /* Number of digits processed */
- int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */
+ int eType = 1; /* 1: pure integer, 2+: fractional */
- assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
*pResult = 0.0; /* Default return value, in case of an error */
- if( length==0 ) return 0;
-
- if( enc==SQLITE_UTF8 ){
- incr = 1;
- zEnd = z + length;
- }else{
- int i;
- incr = 2;
- length &= ~1;
- assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
- testcase( enc==SQLITE_UTF16LE );
- testcase( enc==SQLITE_UTF16BE );
- for(i=3-enc; i<length && z[i]==0; i+=2){}
- if( i<length ) eType = -100;
- zEnd = &z[i^1];
- z += (enc&1);
- }
/* skip leading spaces */
- while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
- if( z>=zEnd ) return 0;
+ while( sqlite3Isspace(*z) ) z++;
/* get sign of significand */
if( *z=='-' ){
sign = -1;
- z+=incr;
+ z++;
}else if( *z=='+' ){
- z+=incr;
+ z++;
}
/* copy max significant digits to significand */
- while( z<zEnd && sqlite3Isdigit(*z) ){
+ while( sqlite3Isdigit(*z) ){
s = s*10 + (*z - '0');
- z+=incr; nDigit++;
+ z++; nDigit++;
if( s>=((LARGEST_INT64-9)/10) ){
/* skip non-significant significand digits
** (increase exponent by d to shift decimal left) */
- while( z<zEnd && sqlite3Isdigit(*z) ){ z+=incr; d++; }
+ while( sqlite3Isdigit(*z) ){ z++; d++; }
}
}
- if( z>=zEnd ) goto do_atof_calc;
/* if decimal point is present */
if( *z=='.' ){
- z+=incr;
+ z++;
eType++;
/* copy digits from after decimal to significand
** (decrease exponent by d to shift decimal right) */
- while( z<zEnd && sqlite3Isdigit(*z) ){
+ while( sqlite3Isdigit(*z) ){
if( s<((LARGEST_INT64-9)/10) ){
s = s*10 + (*z - '0');
d--;
nDigit++;
}
- z+=incr;
+ z++;
}
}
- if( z>=zEnd ) goto do_atof_calc;
/* if exponent is present */
if( *z=='e' || *z=='E' ){
- z+=incr;
+ z++;
eValid = 0;
eType++;
- /* This branch is needed to avoid a (harmless) buffer overread. The
- ** special comment alerts the mutation tester that the correct answer
- ** is obtained even if the branch is omitted */
- if( z>=zEnd ) goto do_atof_calc; /*PREVENTS-HARMLESS-OVERREAD*/
-
/* get sign of exponent */
if( *z=='-' ){
esign = -1;
- z+=incr;
+ z++;
}else if( *z=='+' ){
- z+=incr;
+ z++;
}
/* copy digits to exponent */
- while( z<zEnd && sqlite3Isdigit(*z) ){
+ while( sqlite3Isdigit(*z) ){
e = e<10000 ? (e*10 + (*z - '0')) : 10000;
- z+=incr;
+ z++;
eValid = 1;
}
}
/* skip trailing spaces */
- while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
+ while( sqlite3Isspace(*z) ) z++;
-do_atof_calc:
/* Zero is a special case */
if( s==0 ){
*pResult = sign<0 ? -0.0 : +0.0;
- goto atof_return;
+ goto atofz_return;
}
/* adjust exponent by d, and update sign */
if( sign<0 ) *pResult = -*pResult;
assert( !sqlite3IsNaN(*pResult) );
-atof_return:
+atofz_return:
/* return true if number and no extra non-whitespace characters after */
- if( z==zEnd && nDigit>0 && eValid && eType>0 ){
+ if( z[0]==0 && nDigit>0 && eValid ){
return eType;
}else if( eType>=2 && (eType==3 || eValid) && nDigit>0 ){
return -1;
return 0;
}
#else
- return !sqlite3Atoi64(z, pResult, length, enc);
+ return !sqlite3Atoi64(z, pResult, strlen(z), SQLITE_UTF8);
#endif /* SQLITE_OMIT_FLOATING_POINT */
}
#if defined(_MSC_VER)
#pragma warning(default : 4756)
#endif
+
+
+
/*
** Render an signed 64-bit integer as text. Store the result in zOut[] and
** return the length of the string that was stored, in bytes. The value
*/
static void applyNumericAffinity(Mem *pRec, int bTryForInt){
double rValue;
- u8 enc = pRec->enc;
int rc;
assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_IntReal))==MEM_Str );
- rc = sqlite3AtoF(pRec->z, &rValue, pRec->n, enc);
+ rValue = sqlite3MemRealValueRC(pRec, &rc);
if( rc<=0 ) return;
if( rc==1 && alsoAnInt(pRec, rValue, &pRec->u.i) ){
pRec->flags |= MEM_Int;
int eType = sqlite3_value_type(pVal);
if( eType==SQLITE_TEXT ){
Mem *pMem = (Mem*)pVal;
+ assert( pMem->db!=0 );
+ sqlite3_mutex_enter(pMem->db->mutex);
applyNumericAffinity(pMem, 0);
+ sqlite3_mutex_leave(pMem->db->mutex);
eType = sqlite3_value_type(pVal);
}
return eType;
pMem->u.i = 0;
return MEM_Int;
}
- rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
+ pMem->u.r = sqlite3MemRealValueRC(pMem, &rc);
if( rc<=0 ){
if( rc==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){
pMem->u.i = ix;
int sqlite3VdbeMemIsRowSet(const Mem*);
#endif
int sqlite3VdbeMemSetRowSet(Mem*);
-void sqlite3VdbeMemZeroTerminateIfAble(Mem*);
+int sqlite3VdbeMemZeroTerminateIfAble(Mem*);
int sqlite3VdbeMemMakeWriteable(Mem*);
int sqlite3VdbeMemStringify(Mem*, u8, u8);
int sqlite3IntFloatCompare(i64,double);
i64 sqlite3VdbeIntValue(const Mem*);
int sqlite3VdbeMemIntegerify(Mem*);
double sqlite3VdbeRealValue(Mem*);
+SQLITE_NOINLINE double sqlite3MemRealValueRC(Mem*, int*);
int sqlite3VdbeBooleanValue(Mem*, int ifNull);
void sqlite3VdbeIntegerAffinity(Mem*);
int sqlite3VdbeMemRealify(Mem*);
**
** This is an optimization. Correct operation continues even if
** this routine is a no-op.
+**
+** Return true if the strig is zero-terminated after this routine is
+** called and false if it is not.
*/
-void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){
+int sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){
if( (pMem->flags & (MEM_Str|MEM_Term|MEM_Ephem|MEM_Static))!=MEM_Str ){
/* pMem must be a string, and it cannot be an ephemeral or static string */
- return;
+ return 0;
}
- if( pMem->enc!=SQLITE_UTF8 ) return;
+ if( pMem->enc!=SQLITE_UTF8 ) return 0;
assert( pMem->z!=0 );
if( pMem->flags & MEM_Dyn ){
if( pMem->xDel==sqlite3_free
){
pMem->z[pMem->n] = 0;
pMem->flags |= MEM_Term;
- return;
+ return 1;
}
if( pMem->xDel==sqlite3RCStrUnref ){
/* Blindly assume that all RCStr objects are zero-terminated */
pMem->flags |= MEM_Term;
- return;
+ return 1;
}
}else if( pMem->szMalloc >= pMem->n+1 ){
pMem->z[pMem->n] = 0;
pMem->flags |= MEM_Term;
- return;
+ return 1;
}
+ return 0;
}
/*
}
}
+/*
+** 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.
+**
+** The caller must ensure that pMem->db!=0 and that pMem is in
+** mode MEM_Str or MEM_Blob.
+*/
+SQLITE_NOINLINE double sqlite3MemRealValueRC(Mem *pMem, int *pRC){
+ double val = (double)0;
+ int rc = 0;
+ assert( pMem->db!=0 );
+ assert( pMem->flags & (MEM_Str|MEM_Blob) );
+ if( pMem->z==0 ){
+ /* no-op */
+ }else if( pMem->enc==SQLITE_UTF8
+ && ((pMem->flags & MEM_Term)!=0 || sqlite3VdbeMemZeroTerminateIfAble(pMem))
+ ){
+ rc = sqlite3AtoF(pMem->z, &val);
+ }else if( pMem->n==0 ){
+ /* no-op */
+ }else if( pMem->enc==SQLITE_UTF8 ){
+ char *zCopy = sqlite3DbStrNDup(pMem->db, pMem->z, pMem->n);
+ if( zCopy ){
+ rc = sqlite3AtoF(zCopy, &val);
+ sqlite3DbFree(pMem->db, zCopy);
+ }
+ }else{
+ int n, i, j;
+ char *zCopy;
+ const char *z;
+
+ n = pMem->n & ~1;
+ zCopy = sqlite3DbMallocRaw(pMem->db, n/2 + 2);
+ if( zCopy ){
+ z = pMem->z;
+ if( pMem->enc==SQLITE_UTF16LE ){
+ for(i=j=0; i<n-1; i+=2, j++){
+ zCopy[j] = z[i];
+ if( z[i+1]!=0 ) break;
+ }
+ }else{
+ for(i=j=0; i<n-1; i+=2, j++){
+ if( z[i]!=0 ) break;
+ zCopy[j] = z[i+1];
+ }
+ }
+ assert( j<=n/2 );
+ zCopy[j] = 0;
+ rc = sqlite3AtoF(zCopy, &val);
+ if( i<n ) rc = -100;
+ sqlite3DbFree(pMem->db, zCopy);
+ }
+ }
+ if( pRC ) *pRC = rc;
+ return val;
+}
+
/*
** Return the best representation of pMem that we can get into a
** double. If pMem is already a double or an integer, return its
** value. If it is a string or blob, try to convert it to a double.
** If it is a NULL, return 0.0.
*/
-static SQLITE_NOINLINE double memRealValue(Mem *pMem){
- /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
- double val = (double)0;
- sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc);
- return val;
-}
double sqlite3VdbeRealValue(Mem *pMem){
assert( pMem!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
testcase( pMem->flags & MEM_IntReal );
return (double)pMem->u.i;
}else if( pMem->flags & (MEM_Str|MEM_Blob) ){
- return memRealValue(pMem);
+ return sqlite3MemRealValueRC(pMem, 0);
}else{
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
return (double)0;
sqlite3_int64 ix;
assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
+ pMem->u.r = sqlite3MemRealValueRC(pMem, &rc);
if( ((rc==0 || rc==1) && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1)
|| sqlite3RealSameAsInt(pMem->u.r, (ix = sqlite3RealToI64(pMem->u.r)))
){
if( affinity==SQLITE_AFF_BLOB ){
if( op==TK_FLOAT ){
assert( pVal && pVal->z && pVal->flags==(MEM_Str|MEM_Term) );
- sqlite3AtoF(pVal->z, &pVal->u.r, pVal->n, SQLITE_UTF8);
+ sqlite3AtoF(pVal->z, &pVal->u.r);
pVal->flags = MEM_Real;
}else if( op==TK_INTEGER ){
/* This case is required by -9223372036854775808 and other strings
){
int isNum;
double rDummy;
- isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
+ assert( zNew[iTo]==0 );
+ isNum = sqlite3AtoF(zNew, &rDummy);
if( isNum<=0 ){
if( iTo==1 && zNew[0]=='-' ){
isNum = +1;
}else{
zNew[iTo-1]++;
- isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
+ isNum = sqlite3AtoF(zNew, &rDummy);
zNew[iTo-1]--;
}
}