1 /* 2 ** 2017-12-17 3 ** 4 ** The author disclaims copyright to this source code. In place of 5 ** a legal notice, here is a blessing: 6 ** 7 ** May you do good and not evil. 8 ** May you find forgiveness for yourself and forgive others. 9 ** May you share freely, never taking more than you give. 10 ** 11 ****************************************************************************** 12 ** 13 ** Utility functions sqlar_compress() and sqlar_uncompress(). Useful 14 ** for working with sqlar archives and used by the shell tool's built-in 15 ** sqlar support. 16 */ 17 #include "sqlite3ext.h" 18 SQLITE_EXTENSION_INIT1 19 #include <zlib.h> 20 21 /* 22 ** Implementation of the "sqlar_compress(X)" SQL function. 23 ** 24 ** If the type of X is SQLITE_BLOB, and compressing that blob using 25 ** zlib utility function compress() yields a smaller blob, return the 26 ** compressed blob. Otherwise, return a copy of X. 27 ** 28 ** SQLar uses the "zlib format" for compressed content. The zlib format 29 ** contains a two-byte identification header and a four-byte checksum at 30 ** the end. This is different from ZIP which uses the raw deflate format. 31 ** 32 ** Future enhancements to SQLar might add support for new compression formats. 33 ** If so, those new formats will be identified by alternative headers in the 34 ** compressed data. 35 */ 36 static void sqlarCompressFunc( 37 sqlite3_context *context, 38 int argc, 39 sqlite3_value **argv 40 ){ 41 assert( argc==1 ); 42 if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ 43 const Bytef *pData = sqlite3_value_blob(argv[0]); 44 uLong nData = sqlite3_value_bytes(argv[0]); 45 uLongf nOut = compressBound(nData); 46 Bytef *pOut; 47 48 pOut = (Bytef*)sqlite3_malloc(nOut); 49 if( pOut==0 ){ 50 sqlite3_result_error_nomem(context); 51 return; 52 }else{ 53 if( Z_OK!=compress(pOut, &nOut, pData, nData) ){ 54 sqlite3_result_error(context, "error in compress()", -1); 55 }else if( nOut<nData ){ 56 sqlite3_result_blob(context, pOut, nOut, SQLITE_TRANSIENT); 57 }else{ 58 sqlite3_result_value(context, argv[0]); 59 } 60 sqlite3_free(pOut); 61 } 62 }else{ 63 sqlite3_result_value(context, argv[0]); 64 } 65 } 66 67 /* 68 ** Implementation of the "sqlar_uncompress(X,SZ)" SQL function 69 ** 70 ** Parameter SZ is interpreted as an integer. If it is less than or 71 ** equal to zero, then this function returns a copy of X. Or, if 72 ** SZ is equal to the size of X when interpreted as a blob, also 73 ** return a copy of X. Otherwise, decompress blob X using zlib 74 ** utility function uncompress() and return the results (another 75 ** blob). 76 */ 77 static void sqlarUncompressFunc( 78 sqlite3_context *context, 79 int argc, 80 sqlite3_value **argv 81 ){ 82 uLong nData; 83 uLongf sz; 84 85 assert( argc==2 ); 86 sz = sqlite3_value_int(argv[1]); 87 88 if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){ 89 sqlite3_result_value(context, argv[0]); 90 }else{ 91 const Bytef *pData= sqlite3_value_blob(argv[0]); 92 Bytef *pOut = sqlite3_malloc(sz); 93 if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){ 94 sqlite3_result_error(context, "error in uncompress()", -1); 95 }else{ 96 sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT); 97 } 98 sqlite3_free(pOut); 99 } 100 } 101 102 103 #ifdef _WIN32 104 __declspec(dllexport) 105 #endif 106 int sqlite3_sqlar_init( 107 sqlite3 *db, 108 char **pzErrMsg, 109 const sqlite3_api_routines *pApi 110 ){ 111 int rc = SQLITE_OK; 112 SQLITE_EXTENSION_INIT2(pApi); 113 (void)pzErrMsg; /* Unused parameter */ 114 rc = sqlite3_create_function(db, "sqlar_compress", 1, 115 SQLITE_UTF8|SQLITE_INNOCUOUS, 0, 116 sqlarCompressFunc, 0, 0); 117 if( rc==SQLITE_OK ){ 118 rc = sqlite3_create_function(db, "sqlar_uncompress", 2, 119 SQLITE_UTF8|SQLITE_INNOCUOUS, 0, 120 sqlarUncompressFunc, 0, 0); 121 } 122 return rc; 123 } 124