diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/sqliteInt.h | 4 | ||||
-rw-r--r-- | src/util.c | 4 | ||||
-rw-r--r-- | src/vdbeaux.c | 158 |
3 files changed, 162 insertions, 4 deletions
diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 8360f493a..c2a5be917 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.226 2004/05/10 07:17:31 danielk1977 Exp $ +** @(#) $Id: sqliteInt.h,v 1.227 2004/05/10 10:05:54 danielk1977 Exp $ */ #include "config.h" #include "sqlite.h" @@ -1285,6 +1285,6 @@ void *sqlite3utf8to16le(const unsigned char *pIn, int N); void sqlite3utf16to16le(void *pData, int N); void sqlite3utf16to16be(void *pData, int N); int sqlite3PutVarint(unsigned char *, u64); -int sqlite3GetVarint(unsigned char *, u64 *); +int sqlite3GetVarint(const unsigned char *, u64 *); int sqlite3VarintLen(u64 v); diff --git a/src/util.c b/src/util.c index a3df127d3..420a7c207 100644 --- a/src/util.c +++ b/src/util.c @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.77 2004/05/10 07:17:32 danielk1977 Exp $ +** $Id: util.c,v 1.78 2004/05/10 10:05:54 danielk1977 Exp $ */ #include "sqliteInt.h" #include <stdarg.h> @@ -1144,7 +1144,7 @@ int sqlite3PutVarint(unsigned char *p, u64 v){ return i; } -int sqlite3GetVarint(unsigned char *p, u64 *v){ +int sqlite3GetVarint(const unsigned char *p, u64 *v){ u64 x = p[0] & 0x7f; int n = 0; while( (p[n++]&0x80)!=0 ){ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 2900af6e6..1bfb10e77 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1101,6 +1101,31 @@ int sqlite2BtreeKeyCompare( } /* +** The following three functions: +** +** sqlite3VdbeSerialize() +** sqlite3VdbeSerialLen() +** sqlite3VdbeDeserialize() +** +** encapsulate the code that serializes values for storage in SQLite +** databases. Each serialized value consists of a variable length integer +** followed by type specific storage. +** +** initial varint bytes to follow type +** -------------- --------------- --------------- +** 0 0 NULL +** 1 1 signed integer +** 2 2 signed integer +** 3 4 signed integer +** 4 8 signed integer +** 5 8 IEEE float +** 6..12 reserved for expansion +** N>=12 and even (N-12)/2 BLOB +** N>=13 and odd (N-13)/2 text +** +*/ + +/* ** Write the serialized form of the value held by pMem into zBuf. Return ** the number of bytes written. */ @@ -1108,6 +1133,58 @@ int sqlite3VdbeSerialize( const Mem *pMem, /* Pointer to vdbe value to serialize */ unsigned char *zBuf /* Buffer to write to */ ){ + if( pMem->flags&MEM_Null ){ + return sqlite3PutVarint(zBuf, 0); + } + + if( pMem->flags&MEM_Real ){ + assert(!"TODO: float"); + } + + if( pMem->flags&MEM_Str ){ + int data_type_len; + u64 data_type = (pMem->n*2+31); + + data_type_len = sqlite3PutVarint(zBuf, data_type); + memcpy(&zBuf[data_type_len], pMem->z, pMem->n); + return pMem->n + data_type_len; + } + + if( pMem->flags& MEM_Int ){ + u64 absval; + int size = 8; + int ii; + + if( pMem->i<0 ){ + absval = pMem->i * -1; + }else{ + absval = pMem->i; + } + if( absval<=127 ){ + size = 1; + sqlite3PutVarint(zBuf, 1); + }else if( absval<=32767 ){ + size = 2; + sqlite3PutVarint(zBuf, 2); + }else if( absval<=2147483647 ){ + size = 4; + sqlite3PutVarint(zBuf, 3); + }else{ + size = 8; + sqlite3PutVarint(zBuf, 4); + } + + for(ii=0; ii<size; ii++){ + zBuf[ii+1] = (pMem->i >> (8*ii)) & 0xFF; + } + if( pMem->i<0 ){ + zBuf[size] = zBuf[size] & 0x80; + } + + return size+1; + } + + return -1; } /* @@ -1115,6 +1192,29 @@ int sqlite3VdbeSerialize( ** form of the value held by pMem. Return negative if an error occurs. */ int sqlite3VdbeSerialLen(const Mem *pMem){ + if( pMem->flags&MEM_Null ){ + return 1; /* Varint 0 is 1 byte */ + } + if( pMem->flags&MEM_Real ){ + return 9; /* Varing 5 (1 byte) + 8 bytes IEEE float */ + } + if( pMem->flags&MEM_Str ){ + return pMem->n + sqlite3VarintLen((pMem->n*2)+13); + } + if( pMem->flags& MEM_Int ){ + u64 absval; + if( pMem->i<0 ){ + absval = pMem->i * -1; + }else{ + absval = pMem->i; + } + if( absval<=127 ) return 2; /* 1 byte integer */ + if( absval<=32767 ) return 3; /* 2 byte integer */ + if( absval<=2147483647 ) return 5; /* 4 byte integer */ + return 9; /* 8 byte integer */ + } + + return -1; } /* @@ -1125,6 +1225,64 @@ int sqlite3VdbeDeserialize( Mem *pMem, /* structure to write new value to */ const unsigned char *zBuf /* Buffer to read from */ ){ + u64 data_type; + int ret; + int len; + + memset(pMem, 0, sizeof(Mem)); + ret = sqlite3GetVarint(zBuf, &data_type); + + if( data_type==0 ){ /* NULL */ + pMem->flags = MEM_Null; + return ret; + } + + /* FIX ME: update for 8-byte integers */ + if( data_type>0 && data_type<5 ){ /* 1, 2, 4 or 8 byte integer */ + int ii; + int bytes = 1 << (data_type-1); + + pMem->flags = MEM_Int; + pMem->i = 0; + + for(ii=0; ii<bytes; ii++){ + pMem->i = pMem->i<<8 + zBuf[ii+ret]; + } + + /* If this is a 1, 2 or 4 byte integer, extend the sign-bit if need be. */ + if( bytes<8 && pMem->i & (1<<(bytes*8-1)) ){ + pMem->i = pMem->i - (1<<(bytes*8)); + } + + return ret+bytes; + } + + if( data_type==5 ){ /* IEEE float */ + assert(!"TODO: float"); + } + + /* Must be text or a blob */ + assert( data_type>=12 ); + len = (data_type-12)/2; + pMem->flags = MEM_Str; /* FIX ME: there should be a MEM_Blob or similar */ + + /* If the length of the text or blob is greater than NBFS, use space + ** dynamically allocated. Otherwise, store the value in Mem::zShort. + */ + if( len>NBFS ){ + pMem->z = sqliteMalloc( len ); + if( !pMem->z ){ + return -1; + } + pMem->flags |= MEM_Dyn; + }else{ + pMem->z = pMem->zShort; + pMem->flags |= MEM_Short; + } + memcpy(pMem->z, &zBuf[ret], len); + ret += len; + + return ret; } /* |