]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Speed up base64 conversions, and add test with more data for the baseNN conversion...
authorlarrybr <larrybr@noemail.net>
Thu, 24 Nov 2022 02:59:33 +0000 (02:59 +0000)
committerlarrybr <larrybr@noemail.net>
Thu, 24 Nov 2022 02:59:33 +0000 (02:59 +0000)
FossilOrigin-Name: 6c84ae4ba83713c751fddff8be41686bbcb525ac8135e1520436c62d0bc23d2c

ext/misc/base64.c [changed mode: 0644->0755]
manifest
manifest.uuid
test/basexx1.test

old mode 100644 (file)
new mode 100755 (executable)
index 6e3a6b5..7bb7683
@@ -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;
+  while( nbIn >= 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 = (ubyte)*pIn++;
+    unsigned long qv = *pIn++;
     for( nbe=1; nbe<3; ++nbe ){
-      ubyte b = (nbe<nbi)? *pIn++ : 0;
-      qv = (qv<<8) | b;
+      qv <<= 8;
+      if( nbe<nbIn ) qv |= *pIn++;
     }
-    nc = ncio[nbi];
-    nbIn -= nbi;
     for( nbe=3; nbe>=0; --nbe ){
-      char ce = (nbe<nc)? BX_NUMERAL((ubyte)(qv & 0x3f)) : PAD_CHAR;
+      char ce = (nbe<nco)? BX_NUMERAL((ubyte)(qv & 0x3f)) : PAD_CHAR;
       qv >>= 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:
index 6d54a98758c9439fb076b391091758912bd2295f..56f984f662e6d7b3ff95e46509316d43ec55038f 100644 (file)
--- 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.
index 825fd93e96d2d5cccadefe3e265729e8abcb182c..11257f9dabf5aaeeeea5e7b34cf4a5f04a6e02bd 100644 (file)
@@ -1 +1 @@
-03819e9368fd9f78f351147a1dc865743f9634893e43a9d1e3d7cbaf4c966069
\ No newline at end of file
+6c84ae4ba83713c751fddff8be41686bbcb525ac8135e1520436c62d0bc23d2c
\ No newline at end of file
index 8855a7863487338cb838937daaabc694c367baf9..947a5678f328b43b1e8af3e13449a115ead7e340 100644 (file)
@@ -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