xref: /sqlite-3.40.0/ext/misc/compress.c (revision 38d69855)
1 /*
2 ** 2014-06-13
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 ** This SQLite extension implements SQL compression functions
14 ** compress() and uncompress() using ZLIB.
15 */
16 #include "sqlite3ext.h"
17 SQLITE_EXTENSION_INIT1
18 #include <zlib.h>
19 
20 /*
21 ** Implementation of the "compress(X)" SQL function.  The input X is
22 ** compressed using zLib and the output is returned.
23 **
24 ** The output is a BLOB that begins with a variable-length integer that
25 ** is the input size in bytes (the size of X before compression).  The
26 ** variable-length integer is implemented as 1 to 5 bytes.  There are
27 ** seven bits per integer stored in the lower seven bits of each byte.
28 ** More significant bits occur first.  The most significant bit (0x80)
29 ** is a flag to indicate the end of the integer.
30 */
31 static void compressFunc(
32   sqlite3_context *context,
33   int argc,
34   sqlite3_value **argv
35 ){
36   const unsigned char *pIn;
37   unsigned char *pOut;
38   unsigned int nIn;
39   unsigned long int nOut;
40   unsigned char x[8];
41   int rc;
42   int i, j;
43 
44   pIn = sqlite3_value_blob(argv[0]);
45   nIn = sqlite3_value_bytes(argv[0]);
46   nOut = 13 + nIn + (nIn+999)/1000;
47   pOut = sqlite3_malloc( nOut+5 );
48   for(i=4; i>=0; i--){
49     x[i] = (nIn >> (7*(4-i)))&0x7f;
50   }
51   for(i=0; i<4 && x[i]==0; i++){}
52   for(j=0; i<=4; i++, j++) pOut[j] = x[i];
53   pOut[j-1] |= 0x80;
54   rc = compress(&pOut[j], &nOut, pIn, nIn);
55   if( rc==Z_OK ){
56     sqlite3_result_blob(context, pOut, nOut+j, sqlite3_free);
57   }else{
58     sqlite3_free(pOut);
59   }
60 }
61 
62 /*
63 ** Implementation of the "uncompress(X)" SQL function.  The argument X
64 ** is a blob which was obtained from compress(Y).  The output will be
65 ** the value Y.
66 */
67 static void uncompressFunc(
68   sqlite3_context *context,
69   int argc,
70   sqlite3_value **argv
71 ){
72   const unsigned char *pIn;
73   unsigned char *pOut;
74   unsigned int nIn;
75   unsigned long int nOut;
76   int rc;
77   int i;
78 
79   pIn = sqlite3_value_blob(argv[0]);
80   nIn = sqlite3_value_bytes(argv[0]);
81   nOut = 0;
82   for(i=0; i<nIn && i<5; i++){
83     nOut = (nOut<<7) | (pIn[i]&0x7f);
84     if( (pIn[i]&0x80)!=0 ){ i++; break; }
85   }
86   pOut = sqlite3_malloc( nOut+1 );
87   rc = uncompress(pOut, &nOut, &pIn[i], nIn-i);
88   if( rc==Z_OK ){
89     sqlite3_result_blob(context, pOut, nOut, sqlite3_free);
90   }else{
91     sqlite3_free(pOut);
92   }
93 }
94 
95 
96 #ifdef _WIN32
97 __declspec(dllexport)
98 #endif
99 int sqlite3_compress_init(
100   sqlite3 *db,
101   char **pzErrMsg,
102   const sqlite3_api_routines *pApi
103 ){
104   int rc = SQLITE_OK;
105   SQLITE_EXTENSION_INIT2(pApi);
106   (void)pzErrMsg;  /* Unused parameter */
107   rc = sqlite3_create_function(db, "compress", 1, SQLITE_UTF8, 0,
108                                compressFunc, 0, 0);
109   if( rc==SQLITE_OK ){
110     rc = sqlite3_create_function(db, "uncompress", 1, SQLITE_UTF8, 0,
111                                  uncompressFunc, 0, 0);
112   }
113   return rc;
114 }
115