Fix for retrieving UTF-16 little-endian text from a big-endian database. (CVS 1446)
FossilOrigin-Name: 8104baf23dd28fc982cf260e3e8c90f0c582f602
This commit is contained in:
parent
8a6b5411b3
commit
bd7e46086e
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
||||
C Have\sthe\svdbe\shandle\sstrings\sin\sthe\ssame\sencoding\sas\sthe\sdatabase.\s(CVS\s1445)
|
||||
D 2004-05-24T07:04:26
|
||||
C Fix\sfor\sretrieving\sUTF-16\slittle-endian\stext\sfrom\sa\sbig-endian\sdatabase.\s(CVS\s1446)
|
||||
D 2004-05-24T07:34:48
|
||||
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||
@ -69,7 +69,7 @@ F src/update.c 1a5e9182596f3ea8c7a141e308a3d2a7e5689fee
|
||||
F src/utf.c 441c5918ee3777cd8e9611cbb810312ed314737d
|
||||
F src/util.c 4c0adcbc9ce6678dd046931253e45d623c6d279f
|
||||
F src/vacuum.c 8734f89742f246abd91dbd3e087fc153bddbfbad
|
||||
F src/vdbe.c d5d15429c0be735d325d53d0dadbb2197a9f405d
|
||||
F src/vdbe.c 58ba70a2216d720a25fe5fc8dbea9e8102f74cd3
|
||||
F src/vdbe.h 391d5642a83af686f35c228fcd36cb4456d68f44
|
||||
F src/vdbeInt.h 6c2444a60fc030b275dc0cff407cdaa79d84ce86
|
||||
F src/vdbeaux.c 7f0c4ad22d5e61465d509467e2535293b468373a
|
||||
@ -129,7 +129,7 @@ F test/pager2.test 7ff175a28484fd324df9315dfe35f6fb159910ec
|
||||
F test/pragma.test e763be8238c8a5a0cd8b75e8eec70b957da6081b
|
||||
F test/printf.test 46b3d07d59d871d0831b4a657f6dfcafe0574850
|
||||
F test/progress.test 701b6115c2613128ececdfe1398a1bd0e1a4cfb3 x
|
||||
F test/quick.test f5d81aa4d609a2a47e9000a43c58ae78b359b868
|
||||
F test/quick.test 8800cd2f6b45ce2cafadb0e3d5161688c61c946a
|
||||
F test/quote.test 08f23385c685d3dc7914ec760d492cacea7f6e3d
|
||||
F test/rowid.test 863e6e75878cccf03d166fe52023f20e09508683
|
||||
F test/select1.test 3bfcccd2eadcddbb07f1f5da6550aee8484ea4fb
|
||||
@ -202,7 +202,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
||||
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
|
||||
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||
P f47de3a933b51b37629a0ca2e492a534a12e7339
|
||||
R 0d8b15870c4105fdf982c7cf1ceb6e90
|
||||
P b7155db2b13aa3ca5f6c68e948d9e8740ebcac47
|
||||
R 126af0b27186d92fd9082fbe410f6f8b
|
||||
U danielk1977
|
||||
Z 680dc16bbdc1913b8e540b4d62c8fcee
|
||||
Z b2514b88eb1049ff9f7f80c33c5b5ddd
|
||||
|
@ -1 +1 @@
|
||||
b7155db2b13aa3ca5f6c68e948d9e8740ebcac47
|
||||
8104baf23dd28fc982cf260e3e8c90f0c582f602
|
237
src/vdbe.c
237
src/vdbe.c
@ -43,7 +43,7 @@
|
||||
** in this file for details. If in doubt, do not deviate from existing
|
||||
** commenting and indentation practices when changing or adding code.
|
||||
**
|
||||
** $Id: vdbe.c,v 1.322 2004/05/24 07:04:27 danielk1977 Exp $
|
||||
** $Id: vdbe.c,v 1.323 2004/05/24 07:34:48 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@ -142,6 +142,100 @@ static int encToFlags(u8 enc){
|
||||
*/
|
||||
#define SetEncodingFlags(pMem, enc) ((pMem)->flags = \
|
||||
((pMem->flags & ~(MEM_Utf8|MEM_Utf16le|MEM_Utf16be))) | encToFlags(enc))
|
||||
static int SetEncoding(Mem*, int);
|
||||
|
||||
/*
|
||||
** Convert the given stack entity into a string if it isn't one
|
||||
** already. Return non-zero if a malloc() fails.
|
||||
*/
|
||||
#define Stringify(P, enc) \
|
||||
(!((P)->flags&(MEM_Str|MEM_Blob)) && hardStringify(P, enc))
|
||||
static int hardStringify(Mem *pStack, u8 enc){
|
||||
int rc = SQLITE_OK;
|
||||
int fg = pStack->flags;
|
||||
|
||||
assert( !(fg&(MEM_Str|MEM_Blob)) );
|
||||
assert( fg&(MEM_Int|MEM_Real|MEM_Null) );
|
||||
|
||||
if( fg & MEM_Null ){
|
||||
/* A NULL value is converted to a zero length string */
|
||||
pStack->zShort[0] = 0;
|
||||
pStack->zShort[1] = 0;
|
||||
pStack->flags = MEM_Str | MEM_Short | MEM_Term;
|
||||
pStack->z = pStack->zShort;
|
||||
pStack->n = (enc==TEXT_Utf8?1:2);
|
||||
}else{
|
||||
/* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8
|
||||
** string representation of the value. Then, if the required encoding
|
||||
** is UTF-16le or UTF-16be do a translation.
|
||||
**
|
||||
** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16.
|
||||
*/
|
||||
if( fg & MEM_Real ){
|
||||
sqlite3_snprintf(NBFS, pStack->zShort, "%.15g", pStack->r);
|
||||
}else if( fg & MEM_Int ){
|
||||
sqlite3_snprintf(NBFS, pStack->zShort, "%lld", pStack->i);
|
||||
}
|
||||
pStack->n = strlen(pStack->zShort) + 1;
|
||||
pStack->z = pStack->zShort;
|
||||
pStack->flags = MEM_Str | MEM_Short | MEM_Term;
|
||||
|
||||
/* Flip the string to UTF-16 if required */
|
||||
SetEncodingFlags(pStack, TEXT_Utf8);
|
||||
rc = SetEncoding(pStack, encToFlags(enc)|MEM_Term);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Convert the given stack entity into a string that has been obtained
|
||||
** from sqliteMalloc(). This is different from Stringify() above in that
|
||||
** Stringify() will use the NBFS bytes of static string space if the string
|
||||
** will fit but this routine always mallocs for space.
|
||||
** Return non-zero if we run out of memory.
|
||||
*/
|
||||
#define Dynamicify(P, enc) \
|
||||
(((P)->flags & MEM_Dyn)==0 ? hardDynamicify(P, enc):0)
|
||||
static int hardDynamicify(Mem *pStack, u8 enc){
|
||||
int fg = pStack->flags;
|
||||
char *z;
|
||||
if( (fg & MEM_Str)==0 ){
|
||||
hardStringify(pStack, enc);
|
||||
}
|
||||
assert( (fg & MEM_Dyn)==0 );
|
||||
z = sqliteMallocRaw( pStack->n );
|
||||
if( z==0 ) return 1;
|
||||
memcpy(z, pStack->z, pStack->n);
|
||||
pStack->z = z;
|
||||
pStack->flags |= MEM_Dyn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** An ephemeral string value (signified by the MEM_Ephem flag) contains
|
||||
** a pointer to a dynamically allocated string where some other entity
|
||||
** is responsible for deallocating that string. Because the stack entry
|
||||
** does not control the string, it might be deleted without the stack
|
||||
** entry knowing it.
|
||||
**
|
||||
** This routine converts an ephemeral string into a dynamically allocated
|
||||
** string that the stack entry itself controls. In other words, it
|
||||
** converts an MEM_Ephem string into an MEM_Dyn string.
|
||||
*/
|
||||
#define Deephemeralize(P) \
|
||||
if( ((P)->flags&MEM_Ephem)!=0 && hardDeephem(P) ){ goto no_mem;}
|
||||
static int hardDeephem(Mem *pStack){
|
||||
char *z;
|
||||
assert( (pStack->flags & MEM_Ephem)!=0 );
|
||||
z = sqliteMallocRaw( pStack->n );
|
||||
if( z==0 ) return 1;
|
||||
memcpy(z, pStack->z, pStack->n);
|
||||
pStack->z = z;
|
||||
pStack->flags &= ~MEM_Ephem;
|
||||
pStack->flags |= MEM_Dyn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** If pMem is a string object, this routine sets the encoding of the string
|
||||
@ -171,23 +265,37 @@ int SetEncoding(Mem *pMem, int flags){
|
||||
enc2 = flagsToEnc(flags);
|
||||
|
||||
if( enc1!=enc2 ){
|
||||
/* If the current encoding does not match the desired encoding, then
|
||||
** we will need to do some translation between encodings.
|
||||
*/
|
||||
char *z;
|
||||
int n;
|
||||
int rc = sqlite3utfTranslate(pMem->z,pMem->n,enc1,(void **)&z,&n,enc2);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
if( enc1==TEXT_Utf8 || enc2==TEXT_Utf8 ){
|
||||
/* If the current encoding does not match the desired encoding, then
|
||||
** we will need to do some translation between encodings.
|
||||
*/
|
||||
char *z;
|
||||
int n;
|
||||
int rc = sqlite3utfTranslate(pMem->z,pMem->n,enc1,(void **)&z,&n,enc2);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Result of sqlite3utfTranslate is currently always dynamically
|
||||
** allocated and nul terminated. This might be altered as a performance
|
||||
** enhancement later.
|
||||
*/
|
||||
pMem->z = z;
|
||||
pMem->n = n;
|
||||
pMem->flags = (MEM_Str | MEM_Dyn | MEM_Term | flags);
|
||||
}else{
|
||||
/* Must be translating between UTF-16le and UTF-16be. */
|
||||
int i;
|
||||
if( pMem->flags&MEM_Static ){
|
||||
Dynamicify(pMem, enc1);
|
||||
}
|
||||
for(i=0; i<pMem->n; i+=2){
|
||||
char c = pMem->z[i];
|
||||
pMem->z[i] = pMem->z[i+1];
|
||||
pMem->z[i+1] = c;
|
||||
}
|
||||
SetEncodingFlags(pMem, enc2);
|
||||
}
|
||||
|
||||
/* Result of sqlite3utfTranslate is currently always dynamically
|
||||
** allocated and nul terminated. This might be altered as a performance
|
||||
** enhancement later.
|
||||
*/
|
||||
pMem->z = z;
|
||||
pMem->n = n;
|
||||
pMem->flags = (MEM_Str | MEM_Dyn | MEM_Term | flags);
|
||||
}
|
||||
|
||||
if( (flags&MEM_Term) && !(pMem->flags&MEM_Term) ){
|
||||
@ -289,101 +397,6 @@ static void hardRealify(Mem *pStack, u8 enc){
|
||||
pStack->flags = MEM_Real;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Convert the given stack entity into a string if it isn't one
|
||||
** already. Return non-zero if a malloc() fails.
|
||||
*/
|
||||
#define Stringify(P, enc) \
|
||||
(!((P)->flags&(MEM_Str|MEM_Blob)) && hardStringify(P, enc))
|
||||
static int hardStringify(Mem *pStack, u8 enc){
|
||||
int rc = SQLITE_OK;
|
||||
int fg = pStack->flags;
|
||||
|
||||
assert( !(fg&(MEM_Str|MEM_Blob)) );
|
||||
assert( fg&(MEM_Int|MEM_Real|MEM_Null) );
|
||||
|
||||
if( fg & MEM_Null ){
|
||||
/* A NULL value is converted to a zero length string */
|
||||
pStack->zShort[0] = 0;
|
||||
pStack->zShort[1] = 0;
|
||||
pStack->flags = MEM_Str | MEM_Short | MEM_Term;
|
||||
pStack->z = pStack->zShort;
|
||||
pStack->n = (enc==TEXT_Utf8?1:2);
|
||||
}else{
|
||||
/* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8
|
||||
** string representation of the value. Then, if the required encoding
|
||||
** is UTF-16le or UTF-16be do a translation.
|
||||
**
|
||||
** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16.
|
||||
*/
|
||||
if( fg & MEM_Real ){
|
||||
sqlite3_snprintf(NBFS, pStack->zShort, "%.15g", pStack->r);
|
||||
}else if( fg & MEM_Int ){
|
||||
sqlite3_snprintf(NBFS, pStack->zShort, "%lld", pStack->i);
|
||||
}
|
||||
pStack->n = strlen(pStack->zShort) + 1;
|
||||
pStack->z = pStack->zShort;
|
||||
pStack->flags = MEM_Str | MEM_Short | MEM_Term;
|
||||
|
||||
/* Flip the string to UTF-16 if required */
|
||||
SetEncodingFlags(pStack, TEXT_Utf8);
|
||||
rc = SetEncoding(pStack, encToFlags(enc)|MEM_Term);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Convert the given stack entity into a string that has been obtained
|
||||
** from sqliteMalloc(). This is different from Stringify() above in that
|
||||
** Stringify() will use the NBFS bytes of static string space if the string
|
||||
** will fit but this routine always mallocs for space.
|
||||
** Return non-zero if we run out of memory.
|
||||
*/
|
||||
#define Dynamicify(P, enc) \
|
||||
(((P)->flags & MEM_Dyn)==0 ? hardDynamicify(P, enc):0)
|
||||
static int hardDynamicify(Mem *pStack, u8 enc){
|
||||
int fg = pStack->flags;
|
||||
char *z;
|
||||
if( (fg & MEM_Str)==0 ){
|
||||
hardStringify(pStack, enc);
|
||||
}
|
||||
assert( (fg & MEM_Dyn)==0 );
|
||||
z = sqliteMallocRaw( pStack->n );
|
||||
if( z==0 ) return 1;
|
||||
memcpy(z, pStack->z, pStack->n);
|
||||
pStack->z = z;
|
||||
pStack->flags |= MEM_Dyn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** An ephemeral string value (signified by the MEM_Ephem flag) contains
|
||||
** a pointer to a dynamically allocated string where some other entity
|
||||
** is responsible for deallocating that string. Because the stack entry
|
||||
** does not control the string, it might be deleted without the stack
|
||||
** entry knowing it.
|
||||
**
|
||||
** This routine converts an ephemeral string into a dynamically allocated
|
||||
** string that the stack entry itself controls. In other words, it
|
||||
** converts an MEM_Ephem string into an MEM_Dyn string.
|
||||
*/
|
||||
#define Deephemeralize(P) \
|
||||
if( ((P)->flags&MEM_Ephem)!=0 && hardDeephem(P) ){ goto no_mem;}
|
||||
static int hardDeephem(Mem *pStack){
|
||||
char *z;
|
||||
assert( (pStack->flags & MEM_Ephem)!=0 );
|
||||
z = sqliteMallocRaw( pStack->n );
|
||||
if( z==0 ) return 1;
|
||||
memcpy(z, pStack->z, pStack->n);
|
||||
pStack->z = z;
|
||||
pStack->flags &= ~MEM_Ephem;
|
||||
pStack->flags |= MEM_Dyn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Advance the virtual machine to the next output row.
|
||||
**
|
||||
|
@ -10,7 +10,7 @@
|
||||
#***********************************************************************
|
||||
# This file runs all tests.
|
||||
#
|
||||
# $Id: quick.test,v 1.18 2004/05/23 13:30:59 danielk1977 Exp $
|
||||
# $Id: quick.test,v 1.19 2004/05/24 07:34:49 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -40,8 +40,6 @@ lappend EXCLUDE version.test ;# uses the btree_meta API (not updated)
|
||||
# Some tests fail in these file as a result of the partial manifest types
|
||||
# implementation.
|
||||
lappend EXCLUDE capi2.test
|
||||
lappend EXCLUDE enc2.test
|
||||
|
||||
|
||||
if {[sqlite -has-codec]} {
|
||||
lappend EXCLUDE \
|
||||
|
Loading…
x
Reference in New Issue
Block a user