diff --git a/ext/misc/base64.c b/ext/misc/base64.c old mode 100644 new mode 100755 index 6e3a6b5cb7..7bb7683d1f --- a/ext/misc/base64.c +++ b/ext/misc/base64.c @@ -92,42 +92,46 @@ static const char b64Numerals[64+1] #define IS_BX_DIGIT(bdp) (((ubyte)(bdp))<0x80) #define IS_BX_WS(bdp) ((bdp)==WS) #define IS_BX_PAD(bdp) ((bdp)==PC) -#define BX_NUMERAL(dv) (b64Numerals[dv]) +#define BX_NUMERAL(dv) (b64Numerals[(ubyte)(dv)]) /* Width of base64 lines. Should be an integer multiple of 4. */ #define B64_DARK_MAX 72 -/* Encode a byte buffer into base64 text. If pSep!=0, it's a C string -** to be appended to encoded groups to limit their length to B64_DARK_MAX -** or to terminate the last group (to aid concatenation.) +/* Encode a byte buffer into base64 text with linefeeds appended to limit +** encoded group lengths to B64_DARK_MAX or to terminate the last group. */ -static char* toBase64( ubyte *pIn, int nbIn, char *pOut, char *pSep ){ +static char* toBase64( ubyte *pIn, int nbIn, char *pOut ){ int nCol = 0; - *pOut = 0; - while( nbIn > 0 ){ - static signed char ncio[] = { 0, 2, 3, 4 }; - int nbi = (nbIn > 3)? 3 : nbIn; - signed char nc; - int nbe; - unsigned long qv = (ubyte)*pIn++; - for( nbe=1; nbe<3; ++nbe ){ - ubyte b = (nbe= 3 ){ + /* Do the bit-shuffle, exploiting unsigned input to avoid masking. */ + pOut[0] = BX_NUMERAL(pIn[0]>>2); + pOut[1] = BX_NUMERAL(((pIn[0]<<4)|(pIn[1]>>4))&0x3f); + pOut[2] = BX_NUMERAL(((pIn[1]&0xf)<<2)|(pIn[2]>>6)); + pOut[3] = BX_NUMERAL(pIn[2]&0x3f); + pOut += 4; + nbIn -= 3; + pIn += 3; + if( (nCol += 4)>=B64_DARK_MAX || nbIn<=0 ){ + *pOut++ = '\n'; + nCol = 0; + } + } + if( nbIn > 0 ){ + signed char nco = nbIn+1; + int nbe; + unsigned long qv = *pIn++; + for( nbe=1; nbe<3; ++nbe ){ + qv <<= 8; + if( nbe=0; --nbe ){ - char ce = (nbe>= 6; pOut[nbe] = ce; } pOut += 4; - if( pSep && ((nCol += 4)>=B64_DARK_MAX || nbIn<=0) ){ - char *p = pSep; - while( *p ) *pOut++ = *p++; - nCol = 0; - } - *pOut = 0; + *pOut++ = '\n'; } + *pOut = 0; return pOut; } @@ -157,11 +161,12 @@ static ubyte* fromBase64( char *pIn, int ncIn, ubyte *pOut ){ ubyte bdp = BX_DV_PROTO(c); switch( bdp ){ case ND: - /* Treat non-digits as pad, but they terminate decode too. */ + /* Treat dark non-digits as pad, but they terminate decode too. */ ncIn = 0; /* fall thru */ case WS: - /* Treat whitespace as pad */ + /* Treat whitespace as pad and terminate this group.*/ + nti = nac; /* fall thru */ case PC: bdp = 0; @@ -172,10 +177,15 @@ static ubyte* fromBase64( char *pIn, int ncIn, ubyte *pOut ){ break; } } - nti = 2; - while( nbo-- > 0 ){ - *pOut++ = (qv >> (8*nti--))&0xff; + switch( nbo ){ + case 3: + pOut[2] = (qv) & 0xff; + case 2: + pOut[1] = (qv>>8) & 0xff; + case 1: + pOut[0] = (qv>>16) & 0xff; } + pOut += nbo; } return pOut; } @@ -200,7 +210,7 @@ static void base64(sqlite3_context *context, int na, sqlite3_value *av[]){ cBuf = sqlite3_malloc(nc); if( !cBuf ) goto memFail; bBuf = (ubyte*)sqlite3_value_blob(av[0]); - nc = (int)(toBase64(bBuf, nb, cBuf, "\n") - cBuf); + nc = (int)(toBase64(bBuf, nb, cBuf) - cBuf); sqlite3_result_text(context, cBuf, nc, sqlite3_free); break; case SQLITE_TEXT: diff --git a/manifest b/manifest index 6d54a98758..56f984f662 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\smore\sbaseNN\stests,\sget\soversize\serror\strapping\sworking,\sand\ssync\sw/trunk -D 2022-11-22T22:46:41.866 +C Speed\sup\sbase64\sconversions,\sand\sadd\stest\swith\smore\sdata\sfor\sthe\sbaseNN\sconversion\sto\sgrind. +D 2022-11-24T02:59:33.748 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -289,7 +289,7 @@ F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f23 F ext/misc/amatch.c e3ad5532799cee9a97647f483f67f43b38796b84b5a8c60594fe782a4338f358 F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824 -F ext/misc/base64.c 0472f388e1a6c168912a363dfbe88d2d588325fba7ce6101f726d01b54fe6d3b +F ext/misc/base64.c 6333194e5c2e85b0748116ad4004bf3e070347cc09984aaa8d462fb3fc0566b6 x F ext/misc/base85.c 9005549904fc06ec2f3ff96970709f92f76e2d9ec2b785553ac32908ddc1baa0 F ext/misc/basexx.c 678dcc83894f78c26fd3662b322886777cc26bf2b40809236cd2abdad532a33c F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a @@ -816,7 +816,7 @@ F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135 F test/backup_malloc.test 0c9abdf74c51e7bedb66d504cd684f28d4bd4027 F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f F test/badutf2.test f310fd3b24a491b6b77bccdf14923b85d6ebcce751068c180d93a6b8ff854399 -F test/basexx1.test 9b12557d2b5bd017f9f8a8698239438ced5899c3ee55d9a549f74d90b16e51a6 +F test/basexx1.test d8a50f0744b93dca656625597bcd3499ff4b9a4ea2a82432b119b7d46e3e0c08 F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c F test/bestindex1.test 856a453dff8c68b4568601eed5a8b5e20b4763af9229f3947c215729ed878db0 F test/bestindex2.test 394ff8fbf34703391247116d6a44e1c50ee7282236ee77909044573cefc37bc0 @@ -2063,8 +2063,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 ff67460e1a3d21c9ca7cbd171fbc5e6cbdb3797de359887f851776b73b732fdf 9ec923b5dc24d6082da8d42bc0ee8ab1c418912625c0c56de9627be2c818ef98 -R 36565c16629af64673142ebb24820a85 +P 03819e9368fd9f78f351147a1dc865743f9634893e43a9d1e3d7cbaf4c966069 +R f94c977ea1969bc60efbcf2158a80ba4 U larrybr -Z 3e47c0e49ec42d7b0a58333b563577b4 +Z 312bc23355f0a0c3b5b7524b3c0fa709 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 825fd93e96..11257f9dab 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -03819e9368fd9f78f351147a1dc865743f9634893e43a9d1e3d7cbaf4c966069 \ No newline at end of file +6c84ae4ba83713c751fddff8be41686bbcb525ac8135e1520436c62d0bc23d2c \ No newline at end of file diff --git a/test/basexx1.test b/test/basexx1.test index 8855a78634..947a5678f3 100644 --- a/test/basexx1.test +++ b/test/basexx1.test @@ -138,4 +138,18 @@ do_catchsql_test 116 { SELECT is_base85(x'00'); } {1 {is_base85 accepts only text or NULL}} +# Round-trip many bigger random blobs. + +do_execsql_test 117 { + CREATE TABLE bs(b blob, num); + INSERT INTO bs SELECT randomblob(4000 + n%3), n + FROM ( + WITH RECURSIVE seq(n) AS ( + VALUES(1) UNION ALL SELECT n+1 + FROM seq WHERE n<100 + ) SELECT n FROM seq); + SELECT num FROM bs WHERE base64(base64(b))!=b; + SELECT num FROM bs WHERE base85(base85(b))!=b; +} {} + finish_test