summaryrefslogtreecommitdiff
path: root/ext/sqlite/libsqlite/src/encode.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/sqlite/libsqlite/src/encode.c')
-rw-r--r--ext/sqlite/libsqlite/src/encode.c67
1 files changed, 38 insertions, 29 deletions
diff --git a/ext/sqlite/libsqlite/src/encode.c b/ext/sqlite/libsqlite/src/encode.c
index 5614999ab9..7d959b00ca 100644
--- a/ext/sqlite/libsqlite/src/encode.c
+++ b/ext/sqlite/libsqlite/src/encode.c
@@ -18,6 +18,7 @@
** $Id$
*/
#include <string.h>
+#include <assert.h>
/*
** How This Encoder Works
@@ -26,7 +27,7 @@
** 0x00. This is accomplished by using an escape character to encode
** 0x27 and 0x00 as a two-byte sequence. The escape character is always
** 0x01. An 0x00 is encoded as the two byte sequence 0x01 0x01. The
-** 0x27 character is encoded as the two byte sequence 0x01 0x03. Finally,
+** 0x27 character is encoded as the two byte sequence 0x01 0x28. Finally,
** the escape character itself is encoded as the two-character sequence
** 0x01 0x02.
**
@@ -34,7 +35,7 @@
**
** 0x00 -> 0x01 0x01
** 0x01 -> 0x01 0x02
-** 0x27 -> 0x01 0x03
+** 0x27 -> 0x01 0x28
**
** If that were all the encoder did, it would work, but in certain cases
** it could double the size of the encoded string. For example, to
@@ -80,7 +81,7 @@
** the offset in step 7 below.
**
** (6) Convert each 0x01 0x01 sequence into a single character 0x00.
-** Convert 0x01 0x02 into 0x01. Convert 0x01 0x03 into 0x27.
+** Convert 0x01 0x02 into 0x01. Convert 0x01 0x28 into 0x27.
**
** (7) Subtract the offset value that was the first character of
** the encoded buffer from all characters in the output buffer.
@@ -114,13 +115,20 @@
**
** The return value is the number of characters in the encoded
** string, excluding the "\000" terminator.
+**
+** If out==NULL then no output is generated but the routine still returns
+** the number of characters that would have been generated if out had
+** not been NULL.
*/
int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out){
int i, j, e, m;
+ unsigned char x;
int cnt[256];
if( n<=0 ){
- out[0] = 'x';
- out[1] = 0;
+ if( out ){
+ out[0] = 'x';
+ out[1] = 0;
+ }
return 1;
}
memset(cnt, 0, sizeof(cnt));
@@ -136,24 +144,21 @@ int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out){
if( m==0 ) break;
}
}
+ if( out==0 ){
+ return n+m+1;
+ }
out[0] = e;
j = 1;
for(i=0; i<n; i++){
- int c = (in[i] - e)&0xff;
- if( c==0 ){
- out[j++] = 1;
- out[j++] = 1;
- }else if( c==1 ){
+ x = in[i] - e;
+ if( x==0 || x==1 || x=='\''){
out[j++] = 1;
- out[j++] = 2;
- }else if( c=='\'' ){
- out[j++] = 1;
- out[j++] = 3;
- }else{
- out[j++] = c;
+ x++;
}
+ out[j++] = x;
}
out[j] = 0;
+ assert( j==n+m+1 );
return j;
}
@@ -168,38 +173,32 @@ int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out){
** to decode a string in place.
*/
int sqlite_decode_binary(const unsigned char *in, unsigned char *out){
- int i, c, e;
+ int i, e;
+ unsigned char c;
e = *(in++);
i = 0;
while( (c = *(in++))!=0 ){
if( c==1 ){
- c = *(in++);
- if( c==1 ){
- c = 0;
- }else if( c==2 ){
- c = 1;
- }else if( c==3 ){
- c = '\'';
- }else{
- return -1;
- }
+ c = *(in++) - 1;
}
- out[i++] = (c + e)&0xff;
+ out[i++] = c + e;
}
return i;
}
#ifdef ENCODER_TEST
+#include <stdio.h>
/*
** The subroutines above are not tested by the usual test suite. To test
** these routines, compile just this one file with a -DENCODER_TEST=1 option
** and run the result.
*/
int main(int argc, char **argv){
- int i, j, n, m, nOut;
+ int i, j, n, m, nOut, nByteIn, nByteOut;
unsigned char in[30000];
unsigned char out[33000];
+ nByteIn = nByteOut = 0;
for(i=0; i<sizeof(in); i++){
printf("Test %d: ", i+1);
n = rand() % (i+1);
@@ -213,11 +212,17 @@ int main(int argc, char **argv){
}else{
for(j=0; j<n; j++) in[j] = rand() & 0xff;
}
+ nByteIn += n;
nOut = sqlite_encode_binary(in, n, out);
+ nByteOut += nOut;
if( nOut!=strlen(out) ){
printf(" ERROR return value is %d instead of %d\n", nOut, strlen(out));
exit(1);
}
+ if( nOut!=sqlite_encode_binary(in, n, 0) ){
+ printf(" ERROR actual output size disagrees with predicted size\n");
+ exit(1);
+ }
m = (256*n + 1262)/253;
printf("size %d->%d (max %d)", n, strlen(out)+1, m);
if( strlen(out)+1>m ){
@@ -241,5 +246,9 @@ int main(int argc, char **argv){
}
printf(" OK\n");
}
+ fprintf(stderr,"Finished. Total encoding: %d->%d bytes\n",
+ nByteIn, nByteOut);
+ fprintf(stderr,"Avg size increase: %.3f%%\n",
+ (nByteOut-nByteIn)*100.0/(double)nByteIn);
}
#endif /* ENCODER_TEST */