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 static void sqlarCompressFunc( 29 sqlite3_context *context, 30 int argc, 31 sqlite3_value **argv 32 ){ 33 assert( argc==1 ); 34 if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ 35 const Bytef *pData = sqlite3_value_blob(argv[0]); 36 uLong nData = sqlite3_value_bytes(argv[0]); 37 uLongf nOut = compressBound(nData); 38 Bytef *pOut; 39 40 pOut = (Bytef*)sqlite3_malloc(nOut); 41 if( pOut==0 ){ 42 sqlite3_result_error_nomem(context); 43 return; 44 }else{ 45 if( Z_OK!=compress(pOut, &nOut, pData, nData) ){ 46 sqlite3_result_error(context, "error in compress()", -1); 47 }else if( nOut<nData ){ 48 sqlite3_result_blob(context, pOut, nOut, SQLITE_TRANSIENT); 49 }else{ 50 sqlite3_result_value(context, argv[0]); 51 } 52 sqlite3_free(pOut); 53 } 54 }else{ 55 sqlite3_result_value(context, argv[0]); 56 } 57 } 58 59 /* 60 ** Implementation of the "sqlar_uncompress(X,SZ)" SQL function 61 ** 62 ** Parameter SZ is interpreted as an integer. If it is less than or 63 ** equal to zero, then this function returns a copy of X. Or, if 64 ** SZ is equal to the size of X when interpreted as a blob, also 65 ** return a copy of X. Otherwise, decompress blob X using zlib 66 ** utility function uncompress() and return the results (another 67 ** blob). 68 */ 69 static void sqlarUncompressFunc( 70 sqlite3_context *context, 71 int argc, 72 sqlite3_value **argv 73 ){ 74 uLong nData; 75 uLongf sz; 76 77 assert( argc==2 ); 78 sz = sqlite3_value_int(argv[1]); 79 80 if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){ 81 sqlite3_result_value(context, argv[0]); 82 }else{ 83 const Bytef *pData= sqlite3_value_blob(argv[0]); 84 Bytef *pOut = sqlite3_malloc(sz); 85 if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){ 86 sqlite3_result_error(context, "error in uncompress()", -1); 87 }else{ 88 sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT); 89 } 90 sqlite3_free(pOut); 91 } 92 } 93 94 95 #ifdef _WIN32 96 __declspec(dllexport) 97 #endif 98 int sqlite3_sqlar_init( 99 sqlite3 *db, 100 char **pzErrMsg, 101 const sqlite3_api_routines *pApi 102 ){ 103 int rc = SQLITE_OK; 104 SQLITE_EXTENSION_INIT2(pApi); 105 (void)pzErrMsg; /* Unused parameter */ 106 rc = sqlite3_create_function(db, "sqlar_compress", 1, SQLITE_UTF8, 0, 107 sqlarCompressFunc, 0, 0); 108 if( rc==SQLITE_OK ){ 109 rc = sqlite3_create_function(db, "sqlar_uncompress", 2, SQLITE_UTF8, 0, 110 sqlarUncompressFunc, 0, 0); 111 } 112 return rc; 113 } 114