mirror of
				https://github.com/sqlite/sqlite.git
				synced 2025-11-03 16:53:36 +03:00 
			
		
		
		
	the differences between the "zlib format" used by SQLAR, the raw deflate format used by ZIP, and the custom format used by compress.c. No changes to code. FossilOrigin-Name: c13415c5caf06eaa73086c500907451dfcdfd1354ac4a9ab63edb7255edbfa1b
		
			
				
	
	
		
			130 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
** 2014-06-13
 | 
						|
**
 | 
						|
** 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 SQLite extension implements SQL compression functions
 | 
						|
** compress() and uncompress() using ZLIB.
 | 
						|
*/
 | 
						|
#include "sqlite3ext.h"
 | 
						|
SQLITE_EXTENSION_INIT1
 | 
						|
#include <zlib.h>
 | 
						|
 | 
						|
/*
 | 
						|
** Implementation of the "compress(X)" SQL function.  The input X is
 | 
						|
** compressed using zLib and the output is returned.
 | 
						|
**
 | 
						|
** The output is a BLOB that begins with a variable-length integer that
 | 
						|
** is the input size in bytes (the size of X before compression).  The
 | 
						|
** variable-length integer is implemented as 1 to 5 bytes.  There are
 | 
						|
** seven bits per integer stored in the lower seven bits of each byte.
 | 
						|
** More significant bits occur first.  The most significant bit (0x80)
 | 
						|
** is a flag to indicate the end of the integer.
 | 
						|
**
 | 
						|
** This function, SQLAR, and ZIP all use the same "deflate" compression
 | 
						|
** algorithm, but each is subtly different:
 | 
						|
**
 | 
						|
**   *  ZIP uses raw deflate.
 | 
						|
**
 | 
						|
**   *  SQLAR uses the "zlib format" which is raw deflate with a two-byte
 | 
						|
**      algorithm-identification header and a four-byte checksum at the end.
 | 
						|
**
 | 
						|
**   *  This utility uses the "zlib format" like SQLAR, but adds the variable-
 | 
						|
**      length integer uncompressed size value at the beginning.
 | 
						|
**
 | 
						|
** This function might be extended in the future to support compression
 | 
						|
** formats other than deflate, by providing a different algorithm-id
 | 
						|
** mark following the variable-length integer size parameter.
 | 
						|
*/
 | 
						|
static void compressFunc(
 | 
						|
  sqlite3_context *context,
 | 
						|
  int argc,
 | 
						|
  sqlite3_value **argv
 | 
						|
){
 | 
						|
  const unsigned char *pIn;
 | 
						|
  unsigned char *pOut;
 | 
						|
  unsigned int nIn;
 | 
						|
  unsigned long int nOut;
 | 
						|
  unsigned char x[8];
 | 
						|
  int rc;
 | 
						|
  int i, j;
 | 
						|
 | 
						|
  pIn = sqlite3_value_blob(argv[0]);
 | 
						|
  nIn = sqlite3_value_bytes(argv[0]);
 | 
						|
  nOut = 13 + nIn + (nIn+999)/1000;
 | 
						|
  pOut = sqlite3_malloc( nOut+5 );
 | 
						|
  for(i=4; i>=0; i--){
 | 
						|
    x[i] = (nIn >> (7*(4-i)))&0x7f;
 | 
						|
  }
 | 
						|
  for(i=0; i<4 && x[i]==0; i++){}
 | 
						|
  for(j=0; i<=4; i++, j++) pOut[j] = x[i];
 | 
						|
  pOut[j-1] |= 0x80;
 | 
						|
  rc = compress(&pOut[j], &nOut, pIn, nIn);
 | 
						|
  if( rc==Z_OK ){
 | 
						|
    sqlite3_result_blob(context, pOut, nOut+j, sqlite3_free);
 | 
						|
  }else{
 | 
						|
    sqlite3_free(pOut);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** Implementation of the "uncompress(X)" SQL function.  The argument X
 | 
						|
** is a blob which was obtained from compress(Y).  The output will be
 | 
						|
** the value Y.
 | 
						|
*/
 | 
						|
static void uncompressFunc(
 | 
						|
  sqlite3_context *context,
 | 
						|
  int argc,
 | 
						|
  sqlite3_value **argv
 | 
						|
){
 | 
						|
  const unsigned char *pIn;
 | 
						|
  unsigned char *pOut;
 | 
						|
  unsigned int nIn;
 | 
						|
  unsigned long int nOut;
 | 
						|
  int rc;
 | 
						|
  int i;
 | 
						|
 | 
						|
  pIn = sqlite3_value_blob(argv[0]);
 | 
						|
  nIn = sqlite3_value_bytes(argv[0]);
 | 
						|
  nOut = 0;
 | 
						|
  for(i=0; i<nIn && i<5; i++){
 | 
						|
    nOut = (nOut<<7) | (pIn[i]&0x7f);
 | 
						|
    if( (pIn[i]&0x80)!=0 ){ i++; break; }
 | 
						|
  }
 | 
						|
  pOut = sqlite3_malloc( nOut+1 );
 | 
						|
  rc = uncompress(pOut, &nOut, &pIn[i], nIn-i);
 | 
						|
  if( rc==Z_OK ){
 | 
						|
    sqlite3_result_blob(context, pOut, nOut, sqlite3_free);
 | 
						|
  }else{
 | 
						|
    sqlite3_free(pOut);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#ifdef _WIN32
 | 
						|
__declspec(dllexport)
 | 
						|
#endif
 | 
						|
int sqlite3_compress_init(
 | 
						|
  sqlite3 *db, 
 | 
						|
  char **pzErrMsg, 
 | 
						|
  const sqlite3_api_routines *pApi
 | 
						|
){
 | 
						|
  int rc = SQLITE_OK;
 | 
						|
  SQLITE_EXTENSION_INIT2(pApi);
 | 
						|
  (void)pzErrMsg;  /* Unused parameter */
 | 
						|
  rc = sqlite3_create_function(db, "compress", 1, SQLITE_UTF8, 0,
 | 
						|
                               compressFunc, 0, 0);
 | 
						|
  if( rc==SQLITE_OK ){
 | 
						|
    rc = sqlite3_create_function(db, "uncompress", 1, SQLITE_UTF8, 0,
 | 
						|
                                 uncompressFunc, 0, 0);
 | 
						|
  }
 | 
						|
  return rc;
 | 
						|
}
 |