From: larrybr Date: Tue, 22 Nov 2022 19:04:09 +0000 (+0000) Subject: Add test/basexx1.test to test is_base85(t), base85(x) and base64(x). Sync w/trunk. X-Git-Tag: version-3.41.0~363^2~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bf82c95e08e9c0e442ded343ee8644778f873eef;p=thirdparty%2Fsqlite.git Add test/basexx1.test to test is_base85(t), base85(x) and base64(x). Sync w/trunk. FossilOrigin-Name: 4e4334547795f659b4a5dc5fdaf842535643750a5f1ce1af799c526931a473e4 --- bf82c95e08e9c0e442ded343ee8644778f873eef diff --cc Makefile.in index 09e75bb882,09e75bb882..c5eedf52f9 --- a/Makefile.in +++ b/Makefile.in @@@ -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 \ diff --cc ext/misc/base64.c index 1ab0dc4ead,0000000000..dfeadcb165 mode 100644,000000..100644 --- a/ext/misc/base64.c +++ b/ext/misc/base64.c @@@ -1,250 -1,0 +1,254 @@@ +/* +** 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 - ** data to limit visible line lengths to 72 characters. ++** 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= +** *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 + +#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=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; + } + 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 ){ - char c = (nac<=nti)? *pIn++ : PAD_CHAR; ++ char c = (nac 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 6d28b2a340,e1376b3753..f83d8ca586 --- a/manifest +++ 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 81f4745948,1264b5622a..eb38a17bd2 --- a/manifest.uuid +++ b/manifest.uuid @@@ -1,1 -1,1 +1,1 @@@ - da940d507e9e31a84daedede44a56f743198d7258a9e83892511fe8dd4c78d2b -6d5dc9eed54b7d883aa7dbe2eb5ff17d2a703eabdb7d548a27cccc1fe5addb4a ++4e4334547795f659b4a5dc5fdaf842535643750a5f1ce1af799c526931a473e4 diff --cc src/test1.c index ba1a2252fd,ba1a2252fd..c127d49870 --- a/src/test1.c +++ b/src/test1.c @@@ -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*); @@@ -7740,6 -7740,6 +7741,7 @@@ } 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 }, diff --cc test/basexx1.test index 0000000000,0000000000..3a5b8f8fbc new file mode 100644 --- /dev/null +++ b/test/basexx1.test @@@ -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