Diff for /parser3/src/main/pa_charset.C between versions 1.56 and 1.74

version 1.56, 2007/04/23 10:30:31 version 1.74, 2009/05/13 08:36:30
Line 1 Line 1
 /** @file  /** @file
         Parser: Charset connection implementation.          Parser: Charset connection implementation.
   
         Copyright(c) 2001-2005 ArtLebedev Group (http://www.artlebedev.com)          Copyright(c) 2001-2009 ArtLebedev Group (http://www.artlebedev.com)
         Author: Alexander Petrosyan<paf@design.ru>(http://paf.design.ru)          Author: Alexander Petrosyan<paf@design.ru>(http://paf.design.ru)
 */  */
   
Line 16  static const char * const IDENT_CHARSET_ Line 16  static const char * const IDENT_CHARSET_
   
 //#define PA_PATCHED_LIBXML_BACKWARD  //#define PA_PATCHED_LIBXML_BACKWARD
   
   // reduce memory usage by pre-calculation utf-8 string length
   #define PRECALCULATE_DEST_LENGTH
   
 // globals  // globals
   
 Charset::UTF8CaseTable::Rec UTF8CaseToUpperRecords[]={  Charset::UTF8CaseTable::Rec UTF8CaseToUpperRecords[]={
Line 85  static void element2case(unsigned char f Line 88  static void element2case(unsigned char f
   
 // methods  // methods
   
 extern "C" unsigned char pcre_default_tables[]; // pcre/chartables.c  
 Charset::Charset(Request_charsets* charsets, const String::Body ANAME, const String* afile_spec):   Charset::Charset(Request_charsets* charsets, const String::Body ANAME, const String* afile_spec): 
         FNAME(ANAME),          FNAME(ANAME),
         FNAME_CSTR(ANAME.cstrm()) {          FNAME_CSTR(ANAME.cstrm()) {
Line 99  Charset::Charset(Request_charsets* chars Line 101  Charset::Charset(Request_charsets* chars
         } else {          } else {
                 fisUTF8=true;                  fisUTF8=true;
                 // grab default onces [for UTF-8 so to be able to make a-z =>A-Z                  // grab default onces [for UTF-8 so to be able to make a-z =>A-Z
                 memcpy(pcre_tables, pcre_default_tables, sizeof(pcre_tables));                  memcpy(pcre_tables, _pcre_default_tables, sizeof(pcre_tables));
         }          }
   
 #ifdef XML  #ifdef XML
Line 187  void Charset::sort_ToTable() { Line 189  void Charset::sort_ToTable() {
         //fclose(f);          //fclose(f);
 }  }
   
   // @todo: precache for spedup searching
 static XMLByte xlatOneTo(const XMLCh toXlat,  static XMLByte xlatOneTo(const XMLCh toXlat,
                          const Charset::Tables& tables,                           const Charset::Tables& tables,
                          XMLByte not_found) {                           XMLByte not_found) {
Line 267  static const XMLByte gFirstByteMark[7] = Line 270  static const XMLByte gFirstByteMark[7] =
     0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC      0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
 };  };
   
 static int transcodeToUTF8(const XMLByte* srcData, size_t& srcLen,  static int transcodeToUTF8(const XMLByte* srcData, int& srcLen,
                            XMLByte *toFill, size_t& toFillLen,                                  XMLByte *toFill, int& toFillLen,
                            const Charset::Tables& tables) {                                  const Charset::Tables& tables) {
         const XMLByte* srcPtr=srcData;          const XMLByte* srcPtr=srcData;
         const XMLByte* srcEnd=srcData+srcLen;          const XMLByte* srcEnd=srcData+srcLen;
         XMLByte* outPtr=toFill;          XMLByte* outPtr=toFill;
Line 316  static int transcodeToUTF8(const XMLByte Line 319  static int transcodeToUTF8(const XMLByte
                 //  here, so bump up the output pointer and work down as we go.                  //  here, so bump up the output pointer and work down as we go.
                 outPtr+= encodedBytes;                  outPtr+= encodedBytes;
                 switch(encodedBytes) {                  switch(encodedBytes) {
                 case 6: *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);                          case 6: *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
                         curVal>>= 6;                                  curVal>>= 6;
                 case 5: *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);                          case 5: *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
                         curVal>>= 6;                                  curVal>>= 6;
                 case 4: *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);                          case 4: *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
                         curVal>>= 6;                                  curVal>>= 6;
                 case 3: *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);                          case 3: *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
                         curVal>>= 6;                                  curVal>>= 6;
                 case 2: *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);                          case 2: *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
                         curVal>>= 6;                                  curVal>>= 6;
                 case 1: *--outPtr = XMLByte(curVal | gFirstByteMark[encodedBytes]);                          case 1: *--outPtr = XMLByte(curVal | gFirstByteMark[encodedBytes]);
                 }                  }
                                   
                 // Add the encoded bytes back in again to indicate we've eaten them                  // Add the encoded bytes back in again to indicate we've eaten them
Line 350  of ocetes consumed. Line 353  of ocetes consumed.
         return 0;          return 0;
 }  }
 /// @todo digital entites only when xml/html output [at output in html/xml mode, in html part of a letter]  /// @todo digital entites only when xml/html output [at output in html/xml mode, in html part of a letter]
 static int transcodeFromUTF8(const XMLByte* srcData, size_t& srcLen,  static int transcodeFromUTF8(const XMLByte* srcData, int& srcLen,
                              XMLByte* toFill, size_t& toFillLen,                                  XMLByte* toFill, int& toFillLen,
                              const Charset::Tables& tables) {                                  const Charset::Tables& tables) {
         const XMLByte* srcPtr=srcData;          const XMLByte* srcPtr=srcData;
         const XMLByte* srcEnd=srcData+srcLen;          const XMLByte* srcEnd=srcData+srcLen;
         XMLByte* outPtr=toFill;          XMLByte* outPtr=toFill;
Line 364  static int transcodeFromUTF8(const XMLBy Line 367  static int transcodeFromUTF8(const XMLBy
                 const XMLByte firstByte =* srcPtr;                  const XMLByte firstByte =* srcPtr;
                                   
                 // Special-case ASCII, which is a leading byte value of<= 127                  // Special-case ASCII, which is a leading byte value of<= 127
                 if(firstByte<= 127) {                  if(firstByte<=127) {
                         *outPtr++= firstByte;                          *outPtr++= firstByte;
                         srcPtr++;                          srcPtr++;
                         continue;                          continue;
Line 430  of ocetes consumed. Line 433  of ocetes consumed.
         return 0;          return 0;
 }  }
   
 /// @todo not so memory-hungry with prescan  static bool isEscaped(XMLByte c){
 const String::C Charset::transcodeToUTF8(const String::C src) const {          return
                   !(
                           (c<=127)
                           && (
                                   ((c>='0') && (c<='9'))
                                   || ((c>='A') && (c<='Z'))
                                   || ((c>='a') && (c<='z'))
                                   || strchr("*@-_+./", c)!=0
                           )
                   );
   }
   
   // read one UTF8 char and return length of this char (in bytes)
   static unsigned int readUTF8Char(const XMLByte*& srcPtr, const XMLByte* srcEnd, XMLByte& firstByte, XMLCh& UTF8Char){
           if(!srcPtr || !*srcPtr || srcPtr>=srcEnd)
                   return 0;
   
           firstByte=*srcPtr;
   
           if(firstByte<=127){
                   UTF8Char=firstByte;
                   srcPtr++;
                   return 1;
           }
   
           unsigned int trailingBytes=gUTFBytes[firstByte];
   
           if(srcPtr+trailingBytes>=srcEnd){
                   return 0; // not enough bytes in source string for reading
           }
   
           uint tmpVal=0;
           switch(trailingBytes){
                   case 5: tmpVal+=*srcPtr++; tmpVal<<=6;
                   case 4: tmpVal+=*srcPtr++; tmpVal<<=6;
                   case 3: tmpVal+=*srcPtr++; tmpVal<<=6;
                   case 2: tmpVal+=*srcPtr++; tmpVal<<=6;
                   case 1: tmpVal+=*srcPtr++; tmpVal<<=6;
                   case 0: tmpVal+=*srcPtr++;
           }
   
           tmpVal-=gUTFOffsets[trailingBytes];
           UTF8Char=tmpVal;
   
           return trailingBytes+1;
   }
   
   // skip UTF8 char and return length of this char (in bytes)
   static unsigned int skipUTF8Char(const XMLByte*& srcPtr, const XMLByte* srcEnd){
           if(!srcPtr || !*srcPtr || srcPtr>=srcEnd)
                   return 0;
   
           unsigned int trailingBytes=gUTFBytes[*srcPtr]+1;
           srcPtr+=trailingBytes;
   
           return trailingBytes;
   }
   
   // read non-UTF8 char, and return number of bytes needed for store this char in UTF8
   static unsigned int readChar(const XMLByte*& srcPtr, const XMLByte* srcEnd, XMLByte& firstByte, XMLCh& UTF8Char, const Charset::Tables& tables){
           if(!srcPtr || !*srcPtr || srcPtr>=srcEnd)
                   return 0;
   
           firstByte=*srcPtr++;
           UTF8Char=tables.fromTable[firstByte];
   
           if(UTF8Char<0x80)
                   return 1;
           else if(UTF8Char<0x800)
                   return 2;
           else if(UTF8Char<0x10000)
                   return 3;
           else if(UTF8Char<0x200000)
                   return 4;
           else if(UTF8Char<0x4000000)
                   return 5;
           else if(UTF8Char<= 0x7FFFFFFF)
                   return 6;
   
           // will use the replacement character '?'
           firstByte=0;
           return 1;
   }
   
   static int escapeUTF8(const XMLByte* srcData, size_t& srcLen,
                                XMLByte* toFill, size_t& toFillLen) {
           const XMLByte* srcPtr=srcData;
           const XMLByte* srcEnd=srcData+srcLen;
           XMLByte* outPtr=toFill;
           XMLByte* outEnd=toFill+toFillLen;
           XMLByte firstByte;
           XMLCh UTF8Char;
           uint charSize;
   
           // loop until we either run out of input data, or room to store
           while((outPtr < outEnd) && (charSize=readUTF8Char(srcPtr, srcEnd, firstByte, UTF8Char))){
                   if(charSize==1){
                           if(isEscaped(firstByte)) // %XX
                                   outPtr+=sprintf((char*)outPtr, "%%%02X", firstByte);
                           else
                                   *outPtr++=firstByte;
                   } else
                           outPtr+=sprintf((char*)outPtr, "%%u%04X", UTF8Char); // %uXXXX
           }
           
           // Update the bytes eaten
           srcLen=srcPtr-srcData;
           
           // Return the characters read
           toFillLen=outPtr-toFill;
   
           return 0;
   }
   
   static int escape(const XMLByte* srcData, size_t& srcLen,
                              XMLByte *toFill, size_t& toFillLen,
                              const Charset::Tables& tables) {
           const XMLByte* srcPtr=srcData;
           const XMLByte* srcEnd=srcData+srcLen;
           XMLByte* outPtr=toFill;
           XMLByte firstByte;
           XMLCh UTF8Char;
           uint charSize;
   
           while(charSize=readChar(srcPtr, srcEnd, firstByte, UTF8Char, tables)){
                   if(charSize==1){
                           if(firstByte){
                                   if(isEscaped(firstByte)) // %XX
                                           outPtr+=sprintf((char*)outPtr, "%%%02X", firstByte);
                                   else
                                           *outPtr++=firstByte;
                           } else // add replacement char '?'
                                   *outPtr++='?';
                   } else
                           outPtr+=sprintf((char*)outPtr, "%%u%04X", UTF8Char); // %uXXXX
           }
   
           // Update the bytes eaten
           srcLen = srcPtr - srcData;
           
           // Return the characters read
           toFillLen = outPtr - toFill;
           
           return 0;
   }
   
   
   String::C Charset::escape(const String::C src, const Charset& source_charset){
         size_t src_length=src.length;          size_t src_length=src.length;
         size_t dest_length=src.length*6/*so that surly enough, max utf8 seq len=6*/;          if(!src_length)
                   return String::C("", 0);
   
   #ifdef PRECALCULATE_DEST_LENGTH
           size_t dest_length=0;
           const XMLByte* srcPtr=(XMLByte*)src.str;
           const XMLByte* srcEnd=srcPtr+src_length;
           XMLByte firstByte;
           XMLCh UTF8Char;
   
           if(source_charset.isUTF8()){
                   while(uint charSize=readUTF8Char(srcPtr, srcEnd, firstByte, UTF8Char)){
                           if(charSize==1)
                                   dest_length+=!isEscaped(firstByte)?1:3/*%XX*/;
                           else
                                   dest_length+=6; // '%uXXXX'
                   }
           } else {
                   while(uint charSize=readChar(srcPtr, srcEnd, firstByte, UTF8Char, source_charset.tables)){
                           if(charSize==1)
                                   dest_length+=(!firstByte/*replacement char '?'*/ || !isEscaped(firstByte))?1:3/*'%XX'*/;
                           else
                                   dest_length+=6; // '%uXXXX'
                   }
           }
   #else
           size_t dest_length=src_length*6; // enough for %uXXXX but too memory-hungry
   #endif
   
           //throw Exception(0,0,"%u",dest_length);
   
 #ifndef NDEBUG  #ifndef NDEBUG
         size_t saved_dest_length=dest_length;          size_t saved_dest_length=dest_length;
 #endif  #endif
         XMLByte *dest_body=new(PointerFreeGC) XMLByte[dest_length+1/*for terminator*/];          XMLByte *dest_body=new(PointerFreeGC) XMLByte[dest_length+1/*for terminator*/];
   
           int status;
           if(source_charset.isUTF8()){
                   status=::escapeUTF8((XMLByte *)src.str, src_length, dest_body, dest_length);
           } else {
                   status=::escape((XMLByte *)src.str, src_length, dest_body, dest_length, source_charset.tables);
           }
   
           if(status<0)
                   throw Exception(0,
                           0,
                           "Charset::escape buffer overflow");
   
           assert(dest_length<=saved_dest_length);
           dest_body[dest_length]=0; // terminator
           return String::C((char*)dest_body, dest_length);
   }
           
   String::Body Charset::escape(const String::Body src, const Charset& source_charset) {
           const char *src_ptr=src.cstr();
           size_t src_size=strlen(src_ptr);
   
           String::C dest=Charset::escape(String::C(src_ptr, src_size), source_charset);
   
           return String::Body(dest.str);
   }
   
   String& Charset::escape(const String& src, const Charset& source_charset) {
           if(src.is_empty())
                   return *new String();
   
           return *new String(escape((String::Body)src, source_charset), String::L_CLEAN);
   }
   
   const String::C Charset::transcodeToUTF8(const String::C src) const {
           int src_length=src.length;
   
   #ifdef PRECALCULATE_DEST_LENGTH
           int dest_length=0;
           const XMLByte* srcPtr=(XMLByte*)src.str;
           const XMLByte* srcEnd=srcPtr+src_length;
           XMLByte firstByte;
           XMLCh UTF8Char;
           while(uint charSize=readChar(srcPtr, srcEnd, firstByte, UTF8Char, tables))
                   dest_length+=charSize;
   #else
           int dest_length=src_length*6; // so that surly enough (max utf8 seq len=6) but too memory-hyngry
   #endif
   
           //throw Exception(0,0,"%u",dest_length);
   
   #ifndef NDEBUG
           int saved_dest_length=dest_length;
   #endif
           XMLByte *dest_body=new(PointerFreeGC) XMLByte[dest_length+1/*for terminator*/];
   
         if(::transcodeToUTF8(          if(::transcodeToUTF8(
                 (XMLByte *)src.str, src_length,                  (XMLByte *)src.str, src_length,
                 dest_body, dest_length,                  dest_body, dest_length,
Line 447  const String::C Charset::transcodeToUTF8 Line 682  const String::C Charset::transcodeToUTF8
                         0,                          0,
                         "Charset::transcodeToUTF8 buffer overflow");                          "Charset::transcodeToUTF8 buffer overflow");
   
         assert(dest_length<=saved_dest_length); dest_body[dest_length]=0; // terminator          assert(dest_length<=saved_dest_length);
           dest_body[dest_length]=0; // terminator
         return String::C((char*)dest_body, dest_length);          return String::C((char*)dest_body, dest_length);
 }  }
   
Line 471  static XMLCh change_case_UTF8(const XMLC Line 707  static XMLCh change_case_UTF8(const XMLC
         return src;          return src;
 }  }
   
 static void store_UTF8(XMLCh src, XMLByte*& outPtr ) {  static void store_UTF8(XMLCh src, XMLByte*& outPtr){
         if(!src) {          if(!src) {
                 // use the replacement character                  // use the replacement character
                 *outPtr++= '?';                  *outPtr++= '?';
Line 536  void change_case_UTF8(const XMLByte* src Line 772  void change_case_UTF8(const XMLByte* src
                 // Get the next leading byte out                  // Get the next leading byte out
                 const XMLByte firstByte =* srcPtr;                  const XMLByte firstByte =* srcPtr;
   
                 if(firstByte<= 127) {                  if(firstByte<=127) {
                         change_case_UTF8(firstByte, outPtr, table);                          change_case_UTF8(firstByte, outPtr, table);
                         srcPtr++;                          srcPtr++;
                         continue;                          continue;
Line 580  void change_case_UTF8(const XMLByte* src Line 816  void change_case_UTF8(const XMLByte* src
                         "change_case_UTF8 error: end pointers do not match");                          "change_case_UTF8 error: end pointers do not match");
 }  }
   
   static size_t getDecNumLength(XMLCh UTF8Char){
           return
                   (UTF8Char < 100)
                           ?2
                           :(UTF8Char < 1000)
                                   ?3
                                   :(UTF8Char < 10000)
                                           ?4
                                           :5;
   }
   
 const String::C Charset::transcodeFromUTF8(const String::C src) const {  const String::C Charset::transcodeFromUTF8(const String::C src) const {
         size_t src_length=src.length;          int src_length=src.length;
         size_t dest_length=src.length*6/*so that surly enough, "&#255;" has max ratio */;  
   #ifdef PRECALCULATE_DEST_LENGTH
           int dest_length=0;
           const XMLByte* srcPtr=(XMLByte*)src.str;
           const XMLByte* srcEnd=srcPtr+src_length;
           XMLByte firstByte;
           XMLCh UTF8Char;
           while(uint charSize=readUTF8Char(srcPtr, srcEnd, firstByte, UTF8Char)){
                   if(charSize==1)
                           dest_length++;
                   else
                           dest_length+=(UTF8Char & 0xFFFF0000)
                                                           ?charSize*3     // '%XX' for each byte
                                                           :(xlatOneTo(UTF8Char, tables, 0)!=0)
                                                                   ?1              // can convert it to single char
                                                                   :getDecNumLength(UTF8Char)+3;           // &#XX; - &#XXXXX;
           }
   #else
           // so that surly enough, "&#XXX;" has max ratio (huh? 8 bytes needed for '&#XXXXX;')
           int dest_length=src_length*6;
   #endif
   
 #ifndef NDEBUG  #ifndef NDEBUG
         size_t saved_dest_length=dest_length;          int saved_dest_length=dest_length;
 #endif  #endif
         XMLByte *dest_body=new(PointerFreeGC) XMLByte[dest_length+1/*for terminator*/];          XMLByte *dest_body=new(PointerFreeGC) XMLByte[dest_length+1/*for terminator*/];
   
Line 597  const String::C Charset::transcodeFromUT Line 864  const String::C Charset::transcodeFromUT
                         0,                          0,
                         "Charset::transcodeFromUTF8 buffer overflow");                          "Charset::transcodeFromUTF8 buffer overflow");
   
         assert(dest_length<=saved_dest_length); dest_body[dest_length]=0; // terminator          assert(dest_length<=saved_dest_length);
           dest_body[dest_length]=0; // terminator
         return String::C((char*)dest_body, dest_length);          return String::C((char*)dest_body, dest_length);
 }  }
   
Line 624  const String::C Charset::transcodeToChar Line 892  const String::C Charset::transcodeToChar
         }          }
 }                         }                       
   
   void Charset::store_Char(XMLByte*& outPtr, XMLCh src, XMLByte not_found){
           if(isUTF8())
                   store_UTF8(src, outPtr);
           else if(char ch=xlatOneTo(src, tables, not_found))
                           *outPtr++=ch;
   }
   
 #ifdef XML  #ifdef XML
   
 static const Charset::Tables* tables[MAX_CHARSETS];  static const Charset::Tables* tables[MAX_CHARSETS];
Line 635  static const Charset::Tables* tables[MAX Line 910  static const Charset::Tables* tables[MAX
                 unsigned char *out, int *outlen, \                  unsigned char *out, int *outlen, \
                 const unsigned char *in, int *inlen, void*) { \                  const unsigned char *in, int *inlen, void*) { \
                 return transcodeToUTF8( \                  return transcodeToUTF8( \
                         in, *(size_t*)inlen, \                          in, *inlen, \
                         out, *(size_t*)outlen, \                          out, *outlen, \
                         *tables[i]); \                          *tables[i]); \
         } \          } \
         static int xml256CharEncodingOutputFunc##i( \          static int xml256CharEncodingOutputFunc##i( \
                 unsigned char *out, int *outlen, \                  unsigned char *out, int *outlen, \
                 const unsigned char *in, int *inlen, void*) { \                  const unsigned char *in, int *inlen, void*) { \
                 return transcodeFromUTF8( \                  return transcodeFromUTF8( \
                         in, *(size_t*)inlen, \                          in, *inlen, \
                         out, *(size_t*)outlen, \                          out, *outlen, \
                         *tables[i]); \                          *tables[i]); \
         }          }
   
Line 655  static const Charset::Tables* tables[MAX Line 930  static const Charset::Tables* tables[MAX
                 unsigned char *out, int *outlen, \                  unsigned char *out, int *outlen, \
                 const unsigned char *in, int *inlen) { \                  const unsigned char *in, int *inlen) { \
                 return transcodeToUTF8( \                  return transcodeToUTF8( \
                         in, *(size_t*)inlen, \                          in, *inlen, \
                         out, *(size_t*)outlen, \                          out, *outlen, \
                         *tables[i]); \                          *tables[i]); \
         } \          } \
         static int xml256CharEncodingOutputFunc##i( \          static int xml256CharEncodingOutputFunc##i( \
                 unsigned char *out, int *outlen, \                  unsigned char *out, int *outlen, \
                 const unsigned char *in, int *inlen) { \                  const unsigned char *in, int *inlen) { \
                 return transcodeFromUTF8( \                  return transcodeFromUTF8( \
                         in, *(size_t*)inlen, \                          in, *inlen, \
                         out, *(size_t*)outlen, \                          out, *outlen, \
                         *tables[i]); \                          *tables[i]); \
         }          }
   
Line 760  String::C Charset::transcode_cstr(const Line 1035  String::C Charset::transcode_cstr(const
 }  }
 const String& Charset::transcode(const xmlChar* s) {   const String& Charset::transcode(const xmlChar* s) { 
         String::C cstr=transcode_cstr(s);          String::C cstr=transcode_cstr(s);
         return *new String(cstr.str, cstr.length, true);          return *new String(cstr.str, true/*tainted*/);
 }  }
   
 /// @test less memory using -maybe- xmlParserInputBufferCreateMem  /// @test less memory using -maybe- xmlParserInputBufferCreateMem
Line 825  String::Body Charset::transcode(const St Line 1100  String::Body Charset::transcode(const St
                 source_transcoder,                  source_transcoder,
                 dest_transcoder);                  dest_transcoder);
   
         return String::Body(dest.str, dest.length);          return String::Body(dest.str);
 }  }
   
 String& Charset::transcode(const String& src,   String& Charset::transcode(const String& src, 
         const Charset& source_transcoder,           const Charset& source_transcoder, 
         const Charset& dest_transcoder) {          const Charset& dest_transcoder) {
         if(!src.length())          if(src.is_empty())
                 return *new String("", 0, false);                  return *new String();
   
         return *new String(transcode((String::Body)src, source_transcoder, dest_transcoder), String::L_CLEAN);          return *new String(transcode((String::Body)src, source_transcoder, dest_transcoder), String::L_CLEAN);
 }  }
Line 857  static void transcode_pair(const String: Line 1132  static void transcode_pair(const String:
                 *info->source_transcoder,                   *info->source_transcoder, 
                 *info->dest_transcoder);                  *info->dest_transcoder);
 }  }
   
 void Charset::transcode(HashStringString& src,  void Charset::transcode(HashStringString& src,
         const Charset& source_transcoder,           const Charset& source_transcoder, 
         const Charset& dest_transcoder) {          const Charset& dest_transcoder) {
         Transcode_pair_info info={&source_transcoder, &dest_transcoder};          Transcode_pair_info info={&source_transcoder, &dest_transcoder};
         src.for_each_ref<Transcode_pair_info*>(transcode_pair, &info);          src.for_each_ref<Transcode_pair_info*>(transcode_pair, &info);
 }  }
   
   size_t getUTF8BytePos(const XMLByte* srcBegin, const XMLByte* srcEnd, size_t charPos){
           const XMLByte* ptr=srcBegin;
           while(charPos-- && skipUTF8Char(ptr, srcEnd));
   
           return ptr-srcBegin;
   }
   
   size_t getUTF8CharPos(const XMLByte* srcBegin, const XMLByte* srcEnd, size_t bytePos){
           size_t charPos=0;
           const XMLByte* ptr=srcBegin;
           const XMLByte* ptrEnd=srcBegin+bytePos;
           while(skipUTF8Char(ptr, srcEnd)){
                   if(ptr>ptrEnd)
                           return charPos;
                   charPos++;
           }
   
           // scan till end but position in bytes still too low
           throw Exception(0,
                                           0,
                                           "Error convertion byte pos to char pos");
   }
   
   size_t lengthUTF8(const XMLByte* srcBegin, const XMLByte* srcEnd){
           size_t size=0;
           while(skipUTF8Char(srcBegin, srcEnd))
                   size++;
   
           return size;
   }

Removed from v.1.56  
changed lines
  Added in v.1.74


E-mail: