--- parser3/src/main/pa_charset.C 2003/11/06 08:22:49 1.39 +++ parser3/src/main/pa_charset.C 2005/08/09 08:14:51 1.52 @@ -1,11 +1,11 @@ /** @file Parser: Charset connection implementation. - Copyright(c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com) + Copyright(c) 2001-2005 ArtLebedev Group (http://www.artlebedev.com) Author: Alexander Petrosyan(http://paf.design.ru) */ -static const char* IDENT_CHARSET_C="$Date: 2003/11/06 08:22:49 $"; +static const char * const IDENT_CHARSET_C="$Date: 2005/08/09 08:14:51 $"; #include "pa_charset.h" #include "pa_charsets.h" @@ -14,6 +14,8 @@ static const char* IDENT_CHARSET_C="$Dat #include "libxml/encoding.h" #endif +//#define PA_PATCHED_LIBXML_BACKWARD + // globals Charset::UTF8CaseTable::Rec UTF8CaseToUpperRecords[]={ @@ -126,7 +128,7 @@ void Charset::load_definition(Request_ch // parse cells char *row; - while(row=getrow(&data)) { + while((row=getrow(&data))) { // remove empty&comment lines if(!*row || *row=='#') continue; @@ -134,7 +136,7 @@ void Charset::load_definition(Request_ch // char white-space digit hex-digit letter word lowercase unicode1 unicode2 unsigned int c=0; char *cell; - for(int column=0; cell=lsplit(&row, '\t'); column++) { + for(int column=0; (cell=lsplit(&row, '\t')); column++) { switch(column) { case 0: c=to_wchar_code(cell); break; // pcre_tables @@ -391,7 +393,7 @@ static int transcodeFromUTF8(const XMLBy default: throw Exception(0, 0, - "transcodeFromUTF8 error: wrong trailingBytes value(%d)", trailingBytes); + "transcodeFromUTF8 error: wrong trailingBytes value(%d)", trailingBytes); // never } tmpVal-=gUTFOffsets[trailingBytes]; @@ -401,12 +403,14 @@ static int transcodeFromUTF8(const XMLBy if(!(tmpVal & 0xFFFF0000)) { if(XMLByte xlat=xlatOneTo(tmpVal, tables, 0)) *outPtr++=xlat; - else - outPtr+=sprintf((char *)outPtr, "&#%d;", tmpVal); // &#decimal; - } else - throw Exception(0, - 0, - "transcodeFromUTF8 error: too big tmpVal(0x%08X)", tmpVal); + else { + outPtr+=sprintf((char *)outPtr, "&#%u;", tmpVal); // &#decimal; + } + } else { + const XMLByte* recoverPtr=srcPtr-trailingBytes-1; + for(uint i=0; i<=trailingBytes; i++) + outPtr+=sprintf((char*)outPtr, "%%%02X", *recoverPtr++); + } } // Update the bytes eaten @@ -439,7 +443,7 @@ const String::C Charset::transcodeToUTF8 (XMLByte *)src.str, src_length, dest_body, dest_length, tables)<0) - throw(0, 0, + throw Exception(0, 0, "Charset::transcodeToUTF8 buffer overflow"); @@ -519,13 +523,19 @@ static void change_case_UTF8(XMLCh src, const Charset::UTF8CaseTable& table) { store_UTF8(change_case_UTF8(src, table), outPtr); }; -void change_case_UTF8(const XMLByte* srcData, XMLByte* toFill, - const Charset::UTF8CaseTable& table) { +void change_case_UTF8(const XMLByte* srcData, size_t srcLen, + XMLByte* toFill, size_t toFillLen, + const Charset::UTF8CaseTable& table) { const XMLByte* srcPtr=srcData; + const XMLByte* srcEnd=srcData+srcLen; XMLByte* outPtr=toFill; + XMLByte* outEnd=toFill+toFillLen; + + // We now loop until we either run out of input data, or room to store + while ((srcPtr < srcEnd) && (outPtr < outEnd)) { + // Get the next leading byte out + const XMLByte firstByte =* srcPtr; - // Get the next leading byte out - while (const XMLByte firstByte = *srcPtr) { if(firstByte<= 127) { change_case_UTF8(firstByte, outPtr, table); srcPtr++; @@ -583,7 +593,7 @@ const String::C Charset::transcodeFromUT (XMLByte *)src.str, src_length, dest_body, dest_length, tables)<0) - throw(0, 0, + throw Exception(0, 0, "Charset::transcodeFromUTF8 buffer overflow"); @@ -618,6 +628,28 @@ const String::C Charset::transcodeToChar static const Charset::Tables* tables[MAX_CHARSETS]; +#ifdef PA_PATCHED_LIBXML_BACKWARD + +#define declareXml256ioFuncs(i) \ + static int xml256CharEncodingInputFunc##i( \ + unsigned char *out, int *outlen, \ + const unsigned char *in, int *inlen, void*) { \ + return transcodeToUTF8( \ + in, *(size_t*)inlen, \ + out, *(size_t*)outlen, \ + *tables[i]); \ + } \ + static int xml256CharEncodingOutputFunc##i( \ + unsigned char *out, int *outlen, \ + const unsigned char *in, int *inlen, void*) { \ + return transcodeFromUTF8( \ + in, *(size_t*)inlen, \ + out, *(size_t*)outlen, \ + *tables[i]); \ + } + +#else + #define declareXml256ioFuncs(i) \ static int xml256CharEncodingInputFunc##i( \ unsigned char *out, int *outlen, \ @@ -636,6 +668,9 @@ static const Charset::Tables* tables[MAX *tables[i]); \ } +#endif + + declareXml256ioFuncs(0) declareXml256ioFuncs(1) declareXml256ioFuncs(2) declareXml256ioFuncs(3) declareXml256ioFuncs(4) declareXml256ioFuncs(5) @@ -665,7 +700,7 @@ void Charset::addEncoding(char *name_cst "already allocated %d handlers, no space for new encoding '%s'", MAX_CHARSETS, name_cstr); - xmlCharEncodingHandler* handler=new(PointerFreeGC) xmlCharEncodingHandler; + xmlCharEncodingHandler* handler=new(UseGC) xmlCharEncodingHandler; { handler->name=name_cstr; handler->input=inputFuncs[handlers_count]; @@ -696,7 +731,7 @@ String::C Charset::transcode_cstr(xmlCha return String::C("", 0); int inlen=strlen((const char*)s); - int outlen=inlen; // max + int outlen=inlen*6/*strlen("ÿ")*/; // max #ifndef NDEBUG int saved_outlen=outlen; #endif @@ -706,7 +741,11 @@ String::C Charset::transcode_cstr(xmlCha if(xmlCharEncodingOutputFunc output=transcoder(FNAME).output) { error=output( (unsigned char*)out, &outlen, - (const unsigned char*)s, &inlen); + (const unsigned char*)s, &inlen +#ifdef PA_PATCHED_LIBXML_BACKWARD + ,0 +#endif + ); } else { memcpy(out, s, outlen=inlen); error=0; @@ -741,14 +780,18 @@ xmlChar* Charset::transcode_buf2xchar(co int saved_outlen; #endif if(xmlCharEncodingInputFunc input=transcoder(FNAME).input) { - outlen=buf_size*6/*max*/; + outlen=buf_size*6/*max UTF8 bytes per char*/; #ifndef NDEBUG saved_outlen=outlen; #endif out=(xmlChar*)xmlMalloc(outlen+1); error=input( out, &outlen, - (const unsigned char*)buf, (int*)&buf_size); + (const unsigned char*)buf, (int*)&buf_size +#ifdef PA_PATCHED_LIBXML_BACKWARD + ,0 +#endif + ); } else { outlen=buf_size; #ifndef NDEBUG @@ -818,7 +861,7 @@ struct Transcode_pair_info { const Charset* dest_transcoder; }; #endif -static void transcode_pair(const String::Body akey, +static void transcode_pair(const String::Body /*akey*/, String::Body& avalue, Transcode_pair_info* info) { avalue=Charset::transcode(avalue,