Improved error and help messages for the ".archive" command and "-A" option
[sqlite.git] / ext / misc / compress.c
blob6e7d8b614844cd5f2658b3f18707c48865182841
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.
11 ******************************************************************************
13 ** This SQLite extension implements SQL compression functions
14 ** compress() and uncompress() using ZLIB.
16 #include "sqlite3ext.h"
17 SQLITE_EXTENSION_INIT1
18 #include <zlib.h>
21 ** Implementation of the "compress(X)" SQL function. The input X is
22 ** compressed using zLib and the output is returned.
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.
31 ** This function, SQLAR, and ZIP all use the same "deflate" compression
32 ** algorithm, but each is subtly different:
34 ** * ZIP uses raw deflate.
36 ** * SQLAR uses the "zlib format" which is raw deflate with a two-byte
37 ** algorithm-identification header and a four-byte checksum at the end.
39 ** * This utility uses the "zlib format" like SQLAR, but adds the variable-
40 ** length integer uncompressed size value at the beginning.
42 ** This function might be extended in the future to support compression
43 ** formats other than deflate, by providing a different algorithm-id
44 ** mark following the variable-length integer size parameter.
46 static void compressFunc(
47 sqlite3_context *context,
48 int argc,
49 sqlite3_value **argv
51 const unsigned char *pIn;
52 unsigned char *pOut;
53 unsigned int nIn;
54 unsigned long int nOut;
55 unsigned char x[8];
56 int rc;
57 int i, j;
59 pIn = sqlite3_value_blob(argv[0]);
60 nIn = sqlite3_value_bytes(argv[0]);
61 nOut = 13 + nIn + (nIn+999)/1000;
62 pOut = sqlite3_malloc( nOut+5 );
63 for(i=4; i>=0; i--){
64 x[i] = (nIn >> (7*(4-i)))&0x7f;
66 for(i=0; i<4 && x[i]==0; i++){}
67 for(j=0; i<=4; i++, j++) pOut[j] = x[i];
68 pOut[j-1] |= 0x80;
69 rc = compress(&pOut[j], &nOut, pIn, nIn);
70 if( rc==Z_OK ){
71 sqlite3_result_blob(context, pOut, nOut+j, sqlite3_free);
72 }else{
73 sqlite3_free(pOut);
78 ** Implementation of the "uncompress(X)" SQL function. The argument X
79 ** is a blob which was obtained from compress(Y). The output will be
80 ** the value Y.
82 static void uncompressFunc(
83 sqlite3_context *context,
84 int argc,
85 sqlite3_value **argv
87 const unsigned char *pIn;
88 unsigned char *pOut;
89 unsigned int nIn;
90 unsigned long int nOut;
91 int rc;
92 int i;
94 pIn = sqlite3_value_blob(argv[0]);
95 nIn = sqlite3_value_bytes(argv[0]);
96 nOut = 0;
97 for(i=0; i<nIn && i<5; i++){
98 nOut = (nOut<<7) | (pIn[i]&0x7f);
99 if( (pIn[i]&0x80)!=0 ){ i++; break; }
101 pOut = sqlite3_malloc( nOut+1 );
102 rc = uncompress(pOut, &nOut, &pIn[i], nIn-i);
103 if( rc==Z_OK ){
104 sqlite3_result_blob(context, pOut, nOut, sqlite3_free);
105 }else{
106 sqlite3_free(pOut);
111 #ifdef _WIN32
112 __declspec(dllexport)
113 #endif
114 int sqlite3_compress_init(
115 sqlite3 *db,
116 char **pzErrMsg,
117 const sqlite3_api_routines *pApi
119 int rc = SQLITE_OK;
120 SQLITE_EXTENSION_INIT2(pApi);
121 (void)pzErrMsg; /* Unused parameter */
122 rc = sqlite3_create_function(db, "compress", 1, SQLITE_UTF8, 0,
123 compressFunc, 0, 0);
124 if( rc==SQLITE_OK ){
125 rc = sqlite3_create_function(db, "uncompress", 1, SQLITE_UTF8, 0,
126 uncompressFunc, 0, 0);
128 return rc;