From: drh <> Date: Thu, 29 Jun 2023 23:03:30 +0000 (+0000) Subject: Cleanup and commenting of the new DECIMAL extension code. No functional X-Git-Tag: version-3.43.0~168 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2ddfa6a360ede3e370201b9f45737f8a350be198;p=thirdparty%2Fsqlite.git Cleanup and commenting of the new DECIMAL extension code. No functional changes. FossilOrigin-Name: 5124481663eb8e74a9f861be98adb7075ea911fcff0216d98c658e955acadf14 --- diff --git a/ext/misc/decimal.c b/ext/misc/decimal.c index 6c080c200f..06286f23fd 100644 --- a/ext/misc/decimal.c +++ b/ext/misc/decimal.c @@ -58,41 +58,24 @@ static void decimal_free(Decimal *p){ } /* -** Allocate a new Decimal object. Initialize it to the number given -** by the input string. +** Allocate a new Decimal object initialized to the text in zIn[]. +** Return NULL if any kind of error occurs. */ -static Decimal *decimal_new( - sqlite3_context *pCtx, - sqlite3_value *pIn, - int nAlt, - const unsigned char *zAlt -){ - Decimal *p; - int n, i; - const unsigned char *zIn; +static Decimal *decimalNewFromText(const char *zIn, int n){ + Decimal *p = 0; + int i; int iExp = 0; + p = sqlite3_malloc( sizeof(*p) ); - if( p==0 ) goto new_no_mem; + if( p==0 ) goto new_from_text_failed; p->sign = 0; p->oom = 0; p->isInit = 1; p->isNull = 0; p->nDigit = 0; p->nFrac = 0; - if( zAlt ){ - n = nAlt, - zIn = zAlt; - }else{ - if( sqlite3_value_type(pIn)==SQLITE_NULL ){ - p->a = 0; - p->isNull = 1; - return p; - } - n = sqlite3_value_bytes(pIn); - zIn = sqlite3_value_text(pIn); - } p->a = sqlite3_malloc64( n+1 ); - if( p->a==0 ) goto new_no_mem; + if( p->a==0 ) goto new_from_text_failed; for(i=0; isspace(zIn[i]); i++){} if( zIn[i]=='-' ){ p->sign = 1; @@ -143,7 +126,7 @@ static Decimal *decimal_new( } if( iExp>0 ){ p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 ); - if( p->a==0 ) goto new_no_mem; + if( p->a==0 ) goto new_from_text_failed; memset(p->a+p->nDigit, 0, iExp); p->nDigit += iExp; } @@ -162,7 +145,7 @@ static Decimal *decimal_new( } if( iExp>0 ){ p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 ); - if( p->a==0 ) goto new_no_mem; + if( p->a==0 ) goto new_from_text_failed; memmove(p->a+iExp, p->a, p->nDigit); memset(p->a, 0, iExp); p->nDigit += iExp; @@ -171,7 +154,76 @@ static Decimal *decimal_new( } return p; -new_no_mem: +new_from_text_failed: + if( p ){ + if( p->a ) sqlite3_free(p->a); + sqlite3_free(p); + } + return 0; +} + +/* Forward reference */ +static Decimal *decimalFromDouble(double); + +/* +** Allocate a new Decimal object from an sqlite3_value. Return a pointer +** to the new object, or NULL if there is an error. If the pCtx argument +** is not NULL, then errors are reported on it as well. +** +** If the pIn argument is SQLITE_TEXT or SQLITE_INTEGER, it is converted +** directly into a Decimal. For SQLITE_FLOAT or for SQLITE_BLOB of length +** 8 bytes, the resulting double value is expanded into its decimal equivalent. +** If pIn is NULL or if it is a BLOB that is not exactly 8 bytes in length, +** then NULL is returned. +*/ +static Decimal *decimal_new( + sqlite3_context *pCtx, /* Report error here, if not null */ + sqlite3_value *pIn, /* Construct the decimal object from this */ + int bTextOnly /* Always interpret pIn as text if true */ +){ + Decimal *p = 0; + int eType = sqlite3_value_type(pIn); + if( bTextOnly && (eType==SQLITE_FLOAT || eType==SQLITE_BLOB) ){ + eType = SQLITE_TEXT; + } + switch( eType ){ + case SQLITE_TEXT: + case SQLITE_INTEGER: { + const char *zIn = (const char*)sqlite3_value_text(pIn); + int n = sqlite3_value_bytes(pIn); + p = decimalNewFromText(zIn, n); + if( p==0 ) goto new_failed; + break; + } + + case SQLITE_FLOAT: { + p = decimalFromDouble(sqlite3_value_double(pIn)); + break; + } + + case SQLITE_BLOB: { + const unsigned char *x; + unsigned int i; + sqlite3_uint64 v = 0; + double r; + + if( sqlite3_value_bytes(pIn)!=sizeof(r) ) break; + x = sqlite3_value_blob(pIn); + for(i=0; iisNull ) goto cmp_done; - pB = decimal_new(context, argv[1], 0, 0); + pB = decimal_new(context, argv[1], 1); if( pB==0 || pB->isNull ) goto cmp_done; rc = decimal_cmp(pA, pB); if( rc<0 ) rc = -1; @@ -512,14 +564,14 @@ static Decimal *decimalPow2(int N){ Decimal *pA = 0; /* The result to be returned */ Decimal *pX = 0; /* Multiplier */ if( N<-20000 || N>20000 ) goto pow2_fault; - pA = decimal_new(0, 0, 3, (unsigned char*)"1.0"); + pA = decimalNewFromText("1.0", 3); if( pA==0 || pA->oom ) goto pow2_fault; if( N==0 ) return pA; if( N>0 ){ - pX = decimal_new(0, 0, 3, (unsigned char*)"2.0"); + pX = decimalNewFromText("2.0", 3); }else{ N = -N; - pX = decimal_new(0, 0, 3, (unsigned char*)"0.5"); + pX = decimalNewFromText("0.5", 3); } if( pX==0 || pX->oom ) goto pow2_fault; while( 1 /* Exit by break */ ){ @@ -581,7 +633,7 @@ static Decimal *decimalFromDouble(double r){ /* At this point m is the integer significand and e is the exponent */ sqlite3_snprintf(sizeof(zNum), zNum, "%lld", m); - pA = decimal_new(0, 0, (int)strlen(zNum), (unsigned char*)zNum); + pA = decimalNewFromText(zNum, (int)strlen(zNum)); pX = decimalPow2(e); decimalMul(pA, pX); decimal_free(pX); @@ -590,52 +642,24 @@ static Decimal *decimalFromDouble(double r){ /* ** SQL Function: decimal(X) +** OR: decimal_sci(X) ** ** Convert input X into decimal and then back into text. ** -** If X is originally a float, then a full decoding of that floating +** If X is originally a float, then a full decimal expansion of that floating ** point value is done. Or if X is an 8-byte blob, it is interpreted ** as a float and similarly expanded. +** +** The decimal_sci(X) function returns the result in scientific notation. +** decimal(X) returns a complete decimal, without the e+NNN at the end. */ static void decimalFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ - Decimal *p = 0; + Decimal *p = decimal_new(context, argv[0], 0); UNUSED_PARAMETER(argc); - switch( sqlite3_value_type(argv[0]) ){ - case SQLITE_TEXT: - case SQLITE_INTEGER: { - p = decimal_new(context, argv[0], 0, 0); - break; - } - - case SQLITE_FLOAT: { - p = decimalFromDouble(sqlite3_value_double(argv[0])); - break; - } - - case SQLITE_BLOB: { - const unsigned char *x; - unsigned int i; - sqlite3_uint64 v = 0; - double r; - - if( sqlite3_value_bytes(argv[0])!=sizeof(r) ) break; - x = sqlite3_value_blob(argv[0]); - for(i=0; isign = !pB->sign; @@ -734,7 +758,7 @@ static void decimalSumStep( p->nFrac = 0; } if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - pArg = decimal_new(context, argv[0], 0, 0); + pArg = decimal_new(context, argv[0], 1); decimal_add(p, pArg); decimal_free(pArg); } @@ -749,7 +773,7 @@ static void decimalSumInverse( p = sqlite3_aggregate_context(context, sizeof(*p)); if( p==0 ) return; if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - pArg = decimal_new(context, argv[0], 0, 0); + pArg = decimal_new(context, argv[0], 1); if( pArg ) pArg->sign = !pArg->sign; decimal_add(p, pArg); decimal_free(pArg); @@ -776,8 +800,8 @@ static void decimalMulFunc( int argc, sqlite3_value **argv ){ - Decimal *pA = decimal_new(context, argv[0], 0, 0); - Decimal *pB = decimal_new(context, argv[1], 0, 0); + Decimal *pA = decimal_new(context, argv[0], 1); + Decimal *pB = decimal_new(context, argv[1], 1); UNUSED_PARAMETER(argc); if( pA==0 || pA->oom || pA->isNull || pB==0 || pB->oom || pB->isNull @@ -829,11 +853,11 @@ int sqlite3_decimal_init( void (*xFunc)(sqlite3_context*,int,sqlite3_value**); } aFunc[] = { { "decimal", 1, 0, decimalFunc }, + { "decimal_sci", 1, 1, decimalFunc }, { "decimal_cmp", 2, 0, decimalCmpFunc }, { "decimal_add", 2, 0, decimalAddFunc }, { "decimal_sub", 2, 0, decimalSubFunc }, { "decimal_mul", 2, 0, decimalMulFunc }, - { "decimal_sci", 1, 1, decimalFunc }, { "decimal_pow2", 1, 0, decimalPow2Func }, }; unsigned int i; diff --git a/manifest b/manifest index 84770747b1..b40dd24f82 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhancements\sto\sthe\sDECIMAL\sextension:\n(1)\sIf\sthe\sargument\sto\sdecimal(X)\sis\sa\sfloating\spoint\svalue\s(or\san\s8-byte\sblob),\nthe\sfloating\spoint\svalue\sis\sexpanded\sinto\sits\sexact\sdecimal\srepresentation.\n(2)\sFunction\sdecimal_sci(X)\sworks\sthe\ssame\sexcept\sit\sreturns\sthe\sresult\sin\nscientific\snotation.\n(3)\sNew\sfunction\sdecimal_pow2(N)\sreturns\sthe\sfull\sdecimal\sexpansion\sof\sthe\sN-th\ninteger\spower\sof\s2. -D 2023-06-29T20:28:03.266 +C Cleanup\sand\scommenting\sof\sthe\snew\sDECIMAL\sextension\scode.\s\sNo\sfunctional\nchanges. +D 2023-06-29T23:03:30.242 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -287,7 +287,7 @@ F ext/misc/completion.c 6dafd7f4348eecc7be9e920d4b419d1fb2af75d938cd9c59a20cfe8b F ext/misc/compress.c 3354c77a7c8e86e07d849916000cdac451ed96500bfb5bd83b20eb61eee012c9 F ext/misc/csv.c ca8d6dafc5469639de81937cb66ae2e6b358542aba94c4f791910d355a8e7f73 F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f823e01 -F ext/misc/decimal.c 9899f6c3d2622f12a658530bdaff931ad1633d6e65d58e4a5092122dd188d97d +F ext/misc/decimal.c a61343b36672760e1d6d5b20a42cb52264db55bcd11d0a44e2e06e8ce23227e3 F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1 F ext/misc/explain.c 0086fab288d4352ea638cf40ac382aad3b0dc5e845a1ea829a694c015fd970fe F ext/misc/fileio.c 4e7f7cd30de8df4820c552f14af3c9ca451c5ffe1f2e7bef34d598a12ebfb720 @@ -2041,8 +2041,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 24927c1377314a10177da4a57191593440aa97fd0c5949fdf25a22df1d947600 -R 3c66bdef3f553aa91a9987834f7b8233 +P 8baf8c10aecb261751f2b154356ab224b79d07230929ec9f123791278e601bba +R 675d9c81a919ee8e5fecf85fab690bbe U drh -Z 21790c2ceaea39dee44b1391a0c9d87f +Z 280a7e7c456f8f31c265ce2d679ab403 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index b959f005c9..4f0273de25 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8baf8c10aecb261751f2b154356ab224b79d07230929ec9f123791278e601bba \ No newline at end of file +5124481663eb8e74a9f861be98adb7075ea911fcff0216d98c658e955acadf14 \ No newline at end of file