]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add test/basexx1.test to test is_base85(t), base85(x) and base64(x). Sync w/trunk.
authorlarrybr <larrybr@noemail.net>
Tue, 22 Nov 2022 19:04:09 +0000 (19:04 +0000)
committerlarrybr <larrybr@noemail.net>
Tue, 22 Nov 2022 19:04:09 +0000 (19:04 +0000)
FossilOrigin-Name: 4e4334547795f659b4a5dc5fdaf842535643750a5f1ce1af799c526931a473e4

1  2 
Makefile.in
ext/misc/base64.c
manifest
manifest.uuid
src/test1.c
test/basexx1.test

diff --cc Makefile.in
index 09e75bb882f525b316165f752770db8dc1bc353b,09e75bb882f525b316165f752770db8dc1bc353b..c5eedf52f9d13caa551a97d9ac72fa39579b0e2c
@@@ -446,6 -446,6 +446,7 @@@ TESTSRC += 
    $(TOP)/ext/expert/test_expert.c \
    $(TOP)/ext/misc/amatch.c \
    $(TOP)/ext/misc/appendvfs.c \
++  $(TOP)/ext/misc/basexx.c \
    $(TOP)/ext/misc/carray.c \
    $(TOP)/ext/misc/cksumvfs.c \
    $(TOP)/ext/misc/closure.c \
index 1ab0dc4ead23efdd7e474d6a2a1d2a82596d448d,0000000000000000000000000000000000000000..dfeadcb165789b13b1cacae3b37c88438925ad17
mode 100644,000000..100644
--- /dev/null
@@@ -1,250 -1,0 +1,254 @@@
- ** data to limit visible line lengths to 72 characters.
 +/*
 +** 2022-11-18
 +**
 +** The author disclaims copyright to this source code.  In place of
 +** a legal notice, here is a blessing:
 +**
 +**    May you do good and not evil.
 +**    May you find forgiveness for yourself and forgive others.
 +**    May you share freely, never taking more than you give.
 +**
 +*************************************************************************
 +**
 +** This is a SQLite extension for converting in either direction
 +** between a (binary) blob and base64 text. Base64 can transit a
 +** sane USASCII channel unmolested. It also plays nicely in CSV or
 +** written as TCL brace-enclosed literals or SQL string literals,
 +** and can be used unmodified in XML-like documents.
 +**
 +** This is an independent implementation of conversions specified in
 +** RFC 4648, done on the above date by the author (Larry Brasfield)
 +** who thereby has the right to put this into the public domain.
 +**
 +** The conversions meet RFC 4648 requirements, provided that this
 +** C source specifies that line-feeds are included in the encoded
-       char c = (nac<=nti)? *pIn++ : PAD_CHAR;
++** data to limit visible line lengths to 72 characters and to
++** terminate any encoded blob having non-zero length.
 +**
 +** Length limitations are not imposed except that the runtime
 +** SQLite string or blob length limits are respected. Otherwise,
 +** any length binary sequence can be represented and recovered.
 +** Generated base64 sequences, with their line-feeds included,
 +** can be concatenated; the result converted back to binary will
 +** be the concatenation of the represented binary sequences.
 +**
 +** This SQLite3 extension creates a function, base64(x), which
 +** either: converts text x containing base64 to a returned blob;
 +** or converts a blob x to returned text containing base64. An
 +** error will be thrown for other input argument types.
 +**
 +** This code relies on UTF-8 encoding only with respect to the
 +** meaning of the first 128 (7-bit) codes matching that of USASCII.
 +** It will fail miserably if somehow made to try to convert EBCDIC.
 +** Because it is table-driven, it could be enhanced to handle that,
 +** but the world and SQLite have moved on from that anachronism.
 +**
 +** To build the extension:
 +** Set shell variable SQDIR=<your favorite SQLite checkout directory>
 +** *Nix: gcc -O2 -shared -I$SQDIR -fPIC -o base64.so base64.c
 +** OSX: gcc -O2 -dynamiclib -fPIC -I$SQDIR -o base64.dylib base64.c
 +** Win32: gcc -O2 -shared -I%SQDIR% -o base64.dll base64.c
 +** Win32: cl /Os -I%SQDIR% base64.c -link -dll -out:base64.dll
 +*/
 +
 +#include <assert.h>
 +
 +#ifndef SQLITE_SHELL_EXTFUNCS /* Guard for #include as built-in extension. */
 +#include "sqlite3ext.h"
 +#endif
 +
 +SQLITE_EXTENSION_INIT1;
 +
 +#define PC 0x80 /* pad character */
 +#define WS 0x81 /* whitespace */
 +#define ND 0x82 /* Not above or digit-value */
 +#define PAD_CHAR '='
 +
 +typedef unsigned char ubyte;
 +
 +static const ubyte b64DigitValues[128] = {
 +  /*                             HT LF VT  FF CR       */
 +    ND,ND,ND,ND, ND,ND,ND,ND, ND,WS,WS,WS, WS,WS,ND,ND,
 +  /*                                                US */
 +    ND,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,ND,
 +  /*sp                                  +            / */
 +    WS,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,62, ND,ND,ND,63,
 +  /* 0  1            5            9            =       */
 +    52,53,54,55, 56,57,58,59, 60,61,ND,ND, ND,PC,ND,ND,
 +  /*    A                                            O */
 +    ND, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,
 +  /* P                               Z                 */
 +    15,16,17,18, 19,20,21,22, 23,24,25,ND, ND,ND,ND,ND,
 +  /*    a                                            o */
 +    ND,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
 +  /* p                               z                 */
 +    41,42,43,44, 45,46,47,48, 49,50,51,ND, ND,ND,ND,ND
 +};
 +
 +static const char b64Numerals[64+1]
 += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 +
 +#define BX_DV_PROTO(c) ((((ubyte)(c))<0x80)? b64DigitValues[c] : 0x80)
 +#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])
 +/* 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.)
 +*/
 +static char* toBase64( ubyte *pIn, int nbIn, char *pOut, char *pSep ){
 +  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<nbi)? *pIn++ : 0;
 +      qv = (qv<<8) | b;
 +    }
 +    nc = ncio[nbi];
 +    nbIn -= nbi;
 +    for( nbe=3; nbe>=0; --nbe ){
 +      char ce = (nbe<nc)? 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;
 +  }
 +  return pOut;
 +}
 +
 +/* Skip over text which is not base64 numeral(s). */
 +static char * skipNonB64( char *s ){
 +  char c;
 +  while( (c = *s) && !IS_BX_DIGIT(BX_DV_PROTO(c)) ) ++s;
 +  return s;
 +}
 +
 +/* Decode base64 text into a byte buffer. */
 +static ubyte* fromBase64( char *pIn, int ncIn, ubyte *pOut ){
 +  if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn;
 +  while( ncIn>0 && *pIn!=PAD_CHAR ){
 +    static signed char nboi[] = { 0, 0, 1, 2, 3 };
 +    char *pUse = skipNonB64(pIn);
 +    unsigned long qv = 0L;
 +    int nti, nbo, nac;
 +    ncIn -= (pUse - pIn);
 +    pIn = pUse;
 +    nti = (ncIn>4)? 4 : ncIn;
++    ncIn -= nti;
 +    nbo = nboi[nti];
 +    if( nbo==0 ) break;
 +    for( nac=0; nac<4; ++nac ){
-       --ncIn;
++      char c = (nac<nti)? *pIn++ : b64Numerals[0];
 +      ubyte bdp = BX_DV_PROTO(c);
-       case WS:
 +      switch( bdp ){
-         nti = 0;
-         break;
 +      case ND:
++        /*  Treat non-digits as pad, but they terminate decode too. */
++        ncIn = 0;
++        /* fall thru */
++      case WS:
++        /* Treat whitespace as pad */
++        /* fall thru */
 +      case PC:
 +        bdp = 0;
 +        --nbo;
 +         /* fall thru */
 +      default: /* bdp is the digit value. */
 +        qv = qv<<6 | bdp;
 +        break;
 +      }
 +    }
 +    nti = 2;
 +    while( nbo-- > 0 ){
 +      *pOut++ = (qv >> (8*nti--))&0xff;
 +    }
 +  }
 +  return pOut;
 +}
 +
 +/* This function does the work for the SQLite base64(x) UDF. */
 +static void base64(sqlite3_context *context, int na, sqlite3_value *av[]){
 +  int nb, nc, nv = sqlite3_value_bytes(av[0]);
 +  int nvMax = sqlite3_limit(sqlite3_context_db_handle(context),
 +                            SQLITE_LIMIT_LENGTH, -1);
 +  char *cBuf;
 +  ubyte *bBuf;
 +  assert(na==1);
 +  switch( sqlite3_value_type(av[0]) ){
 +  case SQLITE_BLOB:
 +    nb = nv;
 +    nc = 4*(nv+2/3); /* quads needed */
 +    nc += (nc+(B64_DARK_MAX-1))/B64_DARK_MAX + 1; /* LFs and a 0-terminator */
 +    if( nvMax < nc ){
 +      sqlite3_result_error(context, "blob expanded to base64 too big.", -1);
 +    }
 +    cBuf = sqlite3_malloc(nc);
 +    if( !cBuf ) goto memFail;
 +    bBuf = (ubyte*)sqlite3_value_blob(av[0]);
 +    nc = (int)(toBase64(bBuf, nb, cBuf, "\n") - cBuf);
 +    sqlite3_result_text(context, cBuf, nc, sqlite3_free);
 +    break;
 +  case SQLITE_TEXT:
 +    nc = nv;
 +    nb = 3*((nv+3)/4); /* may overestimate due to LF and padding */
 +    if( nvMax < nb ){
 +      sqlite3_result_error(context, "blob from base64 may be too big.", -1);
 +    }else if( nb<1 ){
 +      nb = 1;
 +    }
 +    bBuf = sqlite3_malloc(nb);
 +    if( !bBuf ) goto memFail;
 +    cBuf = (char *)sqlite3_value_text(av[0]);
 +    nb = (int)(fromBase64(cBuf, nc, bBuf) - bBuf);
 +    sqlite3_result_blob(context, bBuf, nb, sqlite3_free);
 +    break;
 +  default:
 +    sqlite3_result_error(context, "base64 accepts only blob or text.", -1);
 +    break;
 +  }
 +  return;
 + memFail:
 +  sqlite3_result_error(context, "base64 OOM", -1);
 +}
 +
 +/*
 +** Establish linkage to running SQLite library.
 +*/
 +#ifndef SQLITE_SHELL_EXTFUNCS
 +#ifdef _WIN32
 +__declspec(dllexport)
 +#endif
 +int sqlite3_base_init
 +#else
 +static int sqlite3_base64_init
 +#endif
 +(sqlite3 *db, char **pzErr, const sqlite3_api_routines *pApi){
 +  SQLITE_EXTENSION_INIT2(pApi);
 +  (void)pzErr;
 +  return sqlite3_create_function
 +    (db, "base64", 1,
 +     SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_DIRECTONLY|SQLITE_UTF8,
 +     0, base64, 0, 0);
 +}
 +
 +/*
 +** Define some macros to allow this extension to be built into the shell
 +** conveniently, in conjunction with use of SQLITE_SHELL_EXTFUNCS. This
 +** allows shell.c, as distributed, to have this extension built in.
 +*/
 +#define BASE64_INIT(db) sqlite3_base64_init(db, 0, 0)
 +#define BASE64_EXPOSE(db, pzErr) /* Not needed, ..._init() does this. */
diff --cc manifest
index 6d28b2a3407c9bc5a9f02c5d9a60d328ea326862,e1376b37537084fb631cc1636636c5135262b86d..f83d8ca586ec2905bc23b41e41f194b47b99212b
+++ b/manifest
@@@ -1,9 -1,9 +1,9 @@@
- C Get\sclean\sbuilds\sfor\sMS\stools.\sAdd\sbuild\sexamples\sfor\sextension\sglommer\s(basexx.c)\nMake\ssure\sextensions\sbuild\sfor\sdynamic\sload\sand\sbuilt\sinto\sshell.
- D 2022-11-21T02:18:12.614
 -C Fix\slast\sfunction\spointer\sin\ssqlite3Apis\sinit.\sReported\sat\shttps://sqlite.org/forum/info/eba0faa96d
 -D 2022-11-22T15:41:32.493
++C Add\stest/basexx1.test\sto\stest\sis_base85(t),\sbase85(x)\sand\sbase64(x).\sSync\sw/trunk.
++D 2022-11-22T19:04:09.365
  F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
  F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
  F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
--F Makefile.in 78e4c4916f2c3993a8a454018745ff02094a8029d449d0c22db98f1cf8260420
++F Makefile.in 4a16a05d210813cf8448b3143c80f73335a08a79728569de49d6984442b3f4cf
  F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
  F Makefile.msc e7a564ceec71f0d9666031d5638cf0d4f88b050b44e8df5d32125137cd259ac0
  F README.md 8b8df9ca852aeac4864eb1e400002633ee6db84065bd01b78c33817f97d31f5e
@@@ -289,9 -289,6 +289,9 @@@ F ext/misc/README.md d6dd0fe1d8af770402
  F ext/misc/amatch.c e3ad5532799cee9a97647f483f67f43b38796b84b5a8c60594fe782a4338f358
  F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
  F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824
- F ext/misc/base64.c e611e8ce552b16251c1691191d95912f9e03400637311dbd458062d2d0b95e2a
++F ext/misc/base64.c e18d1d35c5eaadb189aff7b5abe7d73655f46396031ce006d24c5fa2f7ee74e8
 +F ext/misc/base85.c 2c680ca7733f9a86f5d292fec71d10777290e68e7ae59d90597ae75fc44a88b6
 +F ext/misc/basexx.c 678dcc83894f78c26fd3662b322886777cc26bf2b40809236cd2abdad532a33c
  F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
  F ext/misc/btreeinfo.c d28ce349b40054eaa9473e835837bad7a71deec33ba13e39f963d50933bfa0f9
  F ext/misc/carray.c b752f46411e4e47e34dce6f0c88bc8e51bb821ba9e49bfcd882506451c928f69
@@@ -551,11 -549,14 +552,14 @@@ F ext/wasm/sql/000-mandelbrot.sql 77533
  F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5
  F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555e685bce3da8c3f
  F ext/wasm/test-opfs-vfs.js 44363db07b2a20e73b0eb1808de4400ca71b703af718d0fa6d962f15e73bf2ac
- F ext/wasm/tester1-worker.html 51bf39e2b87f974ae3d5bc3086e2fb36d258f3698c54f6e21ba4b3b99636fa27
- F ext/wasm/tester1.html 624ec41cd9f78a1f2b6d7df70aaa7a6394396b1f2455ecbd6de5775c1275b121
- F ext/wasm/tester1.js bff806de454de115922d78c056f11d523ec7ed9ed3839d4e21433a9f72558b88
+ F ext/wasm/tester1-worker.html 5ef353348c37cf2e4fd0b23da562d3275523e036260b510734e9a3239ba8c987
 -F ext/wasm/tester1.c-pp.html 74aa9b31c75f12490653f814b53c3dd39f40cd3f70d6a53a716f4e8587107399
 -F ext/wasm/tester1.c-pp.js 0c129495d057c77788b59715152d51f9bf9002ebbcce759ef8b028272ce3519d
++F ext/wasm/tester1.c-pp.html 74aa9b31c75f12490653f814b53c3dd39f40cd3f70d6a53a716f4e8587107399 w ext/wasm/tester1.html
++F ext/wasm/tester1.c-pp.js 0c129495d057c77788b59715152d51f9bf9002ebbcce759ef8b028272ce3519d w ext/wasm/tester1.js
+ F ext/wasm/tests/opfs/concurrency/index.html bb9b0f6da86df34c67fa506db9c45b7c4cf0045a211611cc6b8d2b53fa983481
+ F ext/wasm/tests/opfs/concurrency/test.js 5993c08657d547d3a26b78ff3480122aed2b7361823bc127e96e558931093aff
+ F ext/wasm/tests/opfs/concurrency/worker.js df065bb386ff994951f7fbdd76e12f16e58fbef0e929b2caf74553359da40afc
  F ext/wasm/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd72273503ae7d5
- F ext/wasm/wasmfs.make edfd60691d10fd19ada4c061280fd7fbe4cf5f6bf6b913268e8ebedfccea6ab5
+ F ext/wasm/wasmfs.make 8fea9b4f3cde06141de1fc4c586ab405bd32c3f401554f4ebb18c797401a678d
  F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
  F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
  F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
@@@ -640,8 -641,8 +644,8 @@@ F src/printf.c e99ee9741e79ae3873458146
  F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
  F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633
  F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
- F src/select.c 9886d6669f5787471aab6ae52af76fad90b53edb1c218fc9ed9d953363bc5184
+ F src/select.c 3fc60a8f0b54db15e86584c5fd68dbf63c20fe86886a39267ce7dfc17b68853d
 -F src/shell.c.in 16740a86346ba9823f92528ec588f2b74f68166dac965dabd19883ace230f11d
 +F src/shell.c.in 49b6aeaf950b9b7a74aca7b80e6d004ed32f0a16d2c9471e34587cc4755d5eaa
  F src/sqlite.h.in 100fc660c2f19961b8ed8437b9d53d687de2f8eb2b96437ec6da216adcb643ca
  F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
  F src/sqlite3ext.h c4b9fa7a7e2bcdf850cfeb4b8a91d5ec47b7a00033bc996fd2ee96cbf2741f5f
@@@ -650,7 -651,7 +654,7 @@@ F src/sqliteLimit.h d7323ffea5208c6af27
  F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
  F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
  F src/tclsqlite.c 4e64ba300a5a26e0f1170e09032429faeb65e45e8f3d1a7833e8edb69fc2979e
--F src/test1.c 40c9a40975512985762f87b83d0c63e4904833a9fe78cbcca664a37095301b1d
++F src/test1.c 09ad3f2bf5f0efe70eb16e460054954b36be8ed09dfcafa0642b37d25d379f6f
  F src/test2.c 827446e259a3b7ab949da1542953edda7b5117982576d3e6f1c24a0dd20a5cef
  F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
  F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664
@@@ -812,6 -813,6 +816,7 @@@ F test/backup_ioerr.test 4c3c7147cee85b
  F test/backup_malloc.test 0c9abdf74c51e7bedb66d504cd684f28d4bd4027
  F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
  F test/badutf2.test f310fd3b24a491b6b77bccdf14923b85d6ebcce751068c180d93a6b8ff854399
++F test/basexx1.test 46454750d40888174eebcd4206c9d16cfeb7a0ffa3f04a00ab2e69a6140f1587
  F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c
  F test/bestindex1.test 856a453dff8c68b4568601eed5a8b5e20b4763af9229f3947c215729ed878db0
  F test/bestindex2.test 394ff8fbf34703391247116d6a44e1c50ee7282236ee77909044573cefc37bc0
@@@ -2058,8 -2059,8 +2063,8 @@@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a9
  F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
  F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
  F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
- P 07543d23a98c2a851393a2674e59d3cf1df37c244fb451cb7436f49c95c1423f
- R 1b52ba3002b9af5fda34f27079570bff
 -P 21e80a29737c367babcc0cf2533eed61b5d0fcf3cc3c33ab88761899e394eaf3
 -R b2f32015706aa1808841626a0ff1391c
++P da940d507e9e31a84daedede44a56f743198d7258a9e83892511fe8dd4c78d2b 6d5dc9eed54b7d883aa7dbe2eb5ff17d2a703eabdb7d548a27cccc1fe5addb4a
++R 8126534722ae13c74b5c3a4e8e3049df
  U larrybr
- Z 7a2c313c3d99c0b1eaaafc6ea380893a
 -Z d9d2dcaeb03b2f8d48cf12bc3dcb589d
++Z a05ff028bb3426fe686b2f69a24ff770
  # Remove this line to create a well-formed Fossil manifest.
diff --cc manifest.uuid
index 81f47459488a776a74831e35e3da7408bb266798,1264b5622a0e156649380942f2ae2110e3d5265a..eb38a17bd2f3b82897086e82181ea2eb01812e0e
@@@ -1,1 -1,1 +1,1 @@@
- da940d507e9e31a84daedede44a56f743198d7258a9e83892511fe8dd4c78d2b
 -6d5dc9eed54b7d883aa7dbe2eb5ff17d2a703eabdb7d548a27cccc1fe5addb4a
++4e4334547795f659b4a5dc5fdaf842535643750a5f1ce1af799c526931a473e4
diff --cc src/test1.c
index ba1a2252fd13e4585c0185660dacec2c069ccd1d,ba1a2252fd13e4585c0185660dacec2c069ccd1d..c127d49870f1e8651af15c34d797fa0263aa31aa
@@@ -7709,6 -7709,6 +7709,7 @@@ static int SQLITE_TCLAPI tclLoadStaticE
  ){
    extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*);
    extern int sqlite3_appendvfs_init(sqlite3*,char**,const sqlite3_api_routines*);
++  extern int sqlite3_basexx_init(sqlite3*,char**,const sqlite3_api_routines*);
    extern int sqlite3_carray_init(sqlite3*,char**,const sqlite3_api_routines*);
    extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
    extern int sqlite3_csv_init(sqlite3*,char**,const sqlite3_api_routines*);
    } aExtension[] = {
      { "amatch",                sqlite3_amatch_init               },
      { "appendvfs",             sqlite3_appendvfs_init            },
++    { "basexx",                sqlite3_basexx_init               },
      { "carray",                sqlite3_carray_init               },
      { "closure",               sqlite3_closure_init              },
      { "csv",                   sqlite3_csv_init                  },
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..3a5b8f8fbc34e5bf291e7ff07d16485f70dd4ce9
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,113 @@@
++# 2022 November 22
++#
++# The author disclaims copyright to this source code.  In place of
++# a legal notice, here is a blessing:
++#
++#    May you do good and not evil.
++#    May you find forgiveness for yourself and forgive others.
++#    May you share freely, never taking more than you give.
++#
++#***********************************************************************
++#
++
++set testdir [file dirname $argv0]
++source $testdir/tester.tcl
++set testprefix basexx
++
++if {[catch {load_static_extension db basexx} error]} {
++  puts "Skipping basexx tests, hit load error: $error"
++  finish_test; return
++}
++
++# Empty blobs encode to empty strings.
++do_execsql_test 100 {
++  SELECT base64(x'')||base85(x'');
++} {{}}
++
++# Empty strings decode to empty blobs.
++do_execsql_test 101 {
++  SELECT hex(x'01'||base64('')||base85('')||x'02');
++} {0102}
++
++# Basic base64 encoding
++do_execsql_test 102 {
++  SELECT base64(x'000102030405');
++  SELECT base64(x'0001020304');
++  SELECT base64(x'00010203');
++} {{AAECAwQF
++} {AAECAwQ=
++} {AAECAw==
++}}
++
++# Basic base64 decoding with pad chars
++do_execsql_test 103 {
++  SELECT hex(base64('AAECAwQF'));
++  SELECT hex(base64('AAECAwQ='));
++  SELECT hex(base64('AAECAw=='));
++} {000102030405 0001020304 00010203}
++
++# Basic base64 decoding without pad chars and with whitespace
++do_execsql_test 104 {
++  SELECT hex(base64(' AAECAwQF '));
++  SELECT hex(base64(' AAECAwQ'));
++  SELECT hex(base64('AAECAw '));
++} {000102030405 0001020304 00010203}
++
++# Basic base85 encoding
++do_execsql_test 105 {
++  SELECT base85(x'000102030405');
++  SELECT base85(x'0001020304');
++  SELECT base85(x'00010203');
++} {{##/2,#2/
++} {##/2,#*
++} {##/2,
++}}
++
++# Basic base85 decoding with and without whitespace
++do_execsql_test 106 {
++  SELECT hex(base85('##/2,#2/'));
++  SELECT hex(base85('##/2,#*'));
++  SELECT hex(base85('##/2,'));
++  SELECT hex(base85(' ##/2,#2/ '));
++  SELECT hex(base85(' ##/2,#*'));
++  SELECT hex(base85('##/2, '));
++} {000102030405 0001020304 00010203 000102030405 0001020304 00010203}
++
++# Round-trip some random blobs.
++do_execsql_test 107 {
++  CREATE TEMP TABLE rb( len int, b blob ) STRICT;
++  INSERT INTO rb(len) VALUES (1),(2),(3),(4),(5),(150),(151),(152),(153),(1054);
++  UPDATE rb SET b = randomblob(len);
++  SELECT len, base64(base64(b))=b, base85(base85(b))=b
++  FROM rb ORDER BY len;
++} {1 1 1 2 1 1 3 1 1 4 1 1 5 1 1 150 1 1 151 1 1 152 1 1 153 1 1 1054 1 1}
++
++# Same round-trip but with space or junk prepended and/or appended or not.
++do_execsql_test 108 {
++  CREATE TEMP TABLE junk(j text, rank int);
++  INSERT INTO junk VALUES ('',0),(' ',1),('~',2);
++  SELECT len, base64(j.j||base64(b)||j.j)=b, base85(j.j||base85(b)||j.j)=b
++  FROM rb r, junk j WHERE j.rank=(r.len+r.len/25)%3 ORDER BY len;
++} {1 1 1 2 1 1 3 1 1 4 1 1 5 1 1 150 1 1 151 1 1 152 1 1 153 1 1 1054 1 1}
++
++# Exercise the fail-on-too-large result feature.
++# ToDo: See if extension code for this can be eliminated.
++
++set inLimit [sqlite3_limit db SQLITE_LIMIT_LENGTH -1]
++sqlite3_limit db SQLITE_LIMIT_LENGTH 1060
++
++do_catchsql_test 109 {
++  SELECT len, base64(b) FROM rb WHERE len>200;
++} {1 {string or blob too big}}
++
++do_catchsql_test 110 {
++  SELECT len, base85(b) FROM rb WHERE len>200;
++} {1 {string or blob too big}}
++
++sqlite3_limit db SQLITE_LIMIT_LENGTH $inLimit
++
++do_execsql_test 111 {
++  SELECT is_base85(base85(x'123456')), is_base85('~');
++} {1 0}
++
++finish_test