Diff for /parser3/src/main/pa_charset.C between versions 1.85 and 1.102

version 1.85, 2010/08/27 02:53:24 version 1.102, 2015/10/26 01:21:58
Line 1 Line 1
 /** @file  /** @file
         Parser: Charset connection implementation.          Parser: Charset connection implementation.
   
         Copyright(c) 2001-2009 ArtLebedev Group (http://www.artlebedev.com)          Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com)
         Author: Alexander Petrosyan<paf@design.ru>(http://paf.design.ru)          Author: Alexander Petrosyan<paf@design.ru>(http://paf.design.ru)
 */  */
   
 static const char * const IDENT_CHARSET_C="$Date$";  
   
 #include "pa_charset.h"  #include "pa_charset.h"
 #include "pa_charsets.h"  #include "pa_charsets.h"
   
   // we are using some pcre_internal.h stuff as well
   #include "../lib/pcre/pa_pcre_internal.h"
   
   volatile const char * IDENT_PA_CHARSET_C="$Id$" IDENT_PA_CHARSET_H;
   
 #ifdef XML  #ifdef XML
 #include "libxml/encoding.h"  #include "libxml/encoding.h"
 #endif  #endif
Line 43  inline void prepare_case_tables(unsigned Line 46  inline void prepare_case_tables(unsigned
         for(int i=0; i<0x100; i++)          for(int i=0; i<0x100; i++)
                 lcc_table[i]=fcc_table[i]=(unsigned char)i;                  lcc_table[i]=fcc_table[i]=(unsigned char)i;
 }  }
 inline void cstr2ctypes(unsigned char *tables, const unsigned char *cstr,   inline void cstr2ctypes(unsigned char *tables, const unsigned char *cstr, unsigned char bit) {
                                                 unsigned char bit) {  
         unsigned char *ctypes_table=tables+ctypes_offset;          unsigned char *ctypes_table=tables+ctypes_offset;
         ctypes_table[0]=bit;          ctypes_table[0]=bit;
         for(; *cstr; cstr++) {          for(; *cstr; cstr++) {
Line 58  inline unsigned int to_wchar_code(const Line 60  inline unsigned int to_wchar_code(const
         if(cstr[1]==0)          if(cstr[1]==0)
                 return(unsigned int)(unsigned char)cstr[0];                  return(unsigned int)(unsigned char)cstr[0];
   
         char *error_pos;          return pa_atoui(cstr,0);
         return(unsigned int)strtol(cstr, &error_pos, 0);  
 }  }
 inline bool to_bool(const char* cstr) {  inline bool to_bool(const char* cstr) {
         return cstr && *cstr!=0;          return cstr && *cstr!=0;
 }  }
 static void element2ctypes(unsigned char c, bool belongs,  static void element2ctypes(unsigned char c, bool belongs, unsigned char *tables, unsigned char bit, int group_offset=-1) {
                                                    unsigned char *tables,  unsigned char bit, int group_offset=-1) {  
         if(!belongs)          if(!belongs)
                 return;                  return;
   
Line 75  static void element2ctypes(unsigned char Line 75  static void element2ctypes(unsigned char
         if(group_offset>=0)          if(group_offset>=0)
                 tables[cbits_offset+group_offset+c/8] |= 1<<(c%8);                  tables[cbits_offset+group_offset+c/8] |= 1<<(c%8);
 }  }
 static void element2case(unsigned char from, unsigned char to,  static void element2case(unsigned char from, unsigned char to, unsigned char *tables) {
                                                  unsigned char *tables) {  
         if(!to)           if(!to) 
                 return;                  return;
   
Line 86  static void element2case(unsigned char f Line 85  static void element2case(unsigned char f
         fcc_table[from]=to; fcc_table[to]=from;          fcc_table[from]=to; fcc_table[to]=from;
 }  }
   
   inline XMLByte *append_hex_8(XMLByte *dest, unsigned char c, const char* prefix=0) {
       if(prefix) {
           strcpy((char *)dest, prefix);
           dest+=strlen(prefix);
       }
       *dest++=hex_digits[c >> 4];
       *dest++=hex_digits[c & 0x0F];
       return dest;
   }
   
   inline XMLByte *append_hex_16(XMLByte *dest, unsigned int c, const char* prefix=0) {
       if(prefix) {
           strcpy((char *)dest, prefix);
           dest+=strlen(prefix);
       }
       *dest++=hex_digits[(c >> 12) & 0x0F];
       *dest++=hex_digits[(c >> 8) & 0x0F];
       *dest++=hex_digits[(c >> 4) & 0x0F];
       *dest++=hex_digits[(c) & 0x0F];
       return dest;
   }
   
 // methods  // methods
   
 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): 
Line 101  Charset::Charset(Request_charsets* chars Line 122  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, pa_pcre_default_tables, sizeof(pcre_tables));
         }          }
   
 #ifdef XML  #ifdef XML
Line 152  void Charset::load_definition(Request_ch Line 173  void Charset::load_definition(Request_ch
                         case 8:                          case 8:
                                 // charset                                  // charset
                                 if(tables.toTableSize>MAX_CHARSET_UNI_CODES)                                  if(tables.toTableSize>MAX_CHARSET_UNI_CODES)
                                         throw Exception(PARSER_RUNTIME,                                          throw Exception(PARSER_RUNTIME, &afile_spec, "charset must contain not more then %d unicode values", MAX_CHARSET_UNI_CODES);
                                                 &afile_spec,  
                                                 "charset must contain not more then %d unicode values", MAX_CHARSET_UNI_CODES);  
   
                                 XMLCh unicode=(XMLCh)to_wchar_code(cell);                                  XMLCh unicode=(XMLCh)to_wchar_code(cell);
                                 if(!unicode && column==7/*unicode1 column*/)                                  if(!unicode && column==7/*unicode1 column*/)
Line 171  void Charset::load_definition(Request_ch Line 190  void Charset::load_definition(Request_ch
                 }                  }
         };          };
   
           // parser charset tables declare only white-space before 0x20, thus adding the missing chars
           for(uint i=0; i<0x20; i++)
                   if(!tables.fromTable[i]){
                           tables.fromTable[i]=i;
                           tables.toTable[tables.toTableSize].intCh=i;
                           tables.toTable[tables.toTableSize].extCh=(XMLByte)i;
                           tables.toTableSize++;
                   }
   
         // sort by the Unicode code point          // sort by the Unicode code point
         sort_ToTable();          sort_ToTable();
 }  }
Line 182  static int sort_cmp_Trans_rec_intCh(cons Line 210  static int sort_cmp_Trans_rec_intCh(cons
 }  }
   
 void Charset::sort_ToTable() {  void Charset::sort_ToTable() {
         _qsort(tables.toTable, tables.toTableSize, sizeof(*tables.toTable),           qsort(tables.toTable, tables.toTableSize, sizeof(*tables.toTable), sort_cmp_Trans_rec_intCh);
                 sort_cmp_Trans_rec_intCh);  
         //FILE *f=fopen("c:\\temp\\a", "wb");          //FILE *f=fopen("c:\\temp\\a", "wb");
         //fwrite(tables.toTable, tables.toTableSize, sizeof(*tables.toTable), f);          //fwrite(tables.toTable, tables.toTableSize, sizeof(*tables.toTable), f);
         //fclose(f);          //fclose(f);
 }  }
   
 // @todo: precache for spedup searching  // @todo: precache for spedup searching
 static XMLByte xlatOneTo(const XMLCh toXlat,  static XMLByte xlatOneTo(const XMLCh toXlat, const Charset::Tables& tables, XMLByte not_found) {
                          const Charset::Tables& tables,  
                          XMLByte not_found) {  
         int lo = 0;          int lo = 0;
         int hi = tables.toTableSize - 1;          int hi = tables.toTableSize - 1;
         while(lo<=hi) {          while(lo<=hi) {
Line 211  static XMLByte xlatOneTo(const XMLCh toX Line 236  static XMLByte xlatOneTo(const XMLCh toX
         return not_found;          return not_found;
 }  }
   
 String::C Charset::transcode(const String::C src,  String::C Charset::transcode(const String::C src, const Charset& source_charset, const Charset& dest_charset) {
         const Charset& source_charset,   
         const Charset& dest_charset) {  
         if(!src.length)          if(!src.length)
                 return String::C("", 0);                  return String::C("", 0);
   
Line 270  static const XMLByte gFirstByteMark[7] = Line 293  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, int& srcLen,  static int transcodeToUTF8(const XMLByte* srcData, int& srcLen, XMLByte *toFill, int& toFillLen, const Charset::Tables& tables) {
                                 XMLByte *toFill, int& toFillLen,  
                                 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 353  of ocetes consumed. Line 374  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, int& srcLen,  static int transcodeFromUTF8(const XMLByte* srcData, int& srcLen, XMLByte* toFill, int& toFillLen, const Charset::Tables& tables) {
                                 XMLByte* toFill, int& toFillLen,  
                                 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 394  static int transcodeFromUTF8(const XMLBy Line 413  static int transcodeFromUTF8(const XMLBy
                         break;                          break;
                                                   
                 default:                  default:
                         throw Exception(0,                          throw Exception(0, 0, "transcodeFromUTF8 error: wrong trailingBytes value(%d)", trailingBytes); // never
                                 0,  
                                 "transcodeFromUTF8 error: wrong trailingBytes value(%d)", trailingBytes); // never  
                 }                  }
                 tmpVal-=gUTFOffsets[trailingBytes];                  tmpVal-=gUTFOffsets[trailingBytes];
                                   
Line 438  static bool need_escape(XMLByte c){ Line 455  static bool need_escape(XMLByte c){
                 !(                  !(
                         (c<=127)                          (c<=127)
                         && (                          && (
                                 ((c>='0') && (c<='9'))                                  pa_isalnum((unsigned char)c)
                                 || ((c>='A') && (c<='Z'))  
                                 || ((c>='a') && (c<='z'))  
                                 || strchr("*@-_+./", c)!=0                                  || strchr("*@-_+./", c)!=0
                         )                          )
                 );                  );
Line 531  size_t Charset::calc_escaped_length_UTF8 Line 546  size_t Charset::calc_escaped_length_UTF8
         return dest_length;          return dest_length;
 }  }
   
 size_t Charset::calc_escaped_length(XMLByte* src, size_t src_length, const Charset::Tables& tables){  size_t Charset::calc_escaped_length(const XMLByte* src, size_t src_length, const Charset::Tables& tables){
         size_t dest_length=0;          const XMLByte* src_end=src+src_length;
   
         const XMLByte* src_ptr=src;  
         const XMLByte* src_end=src_ptr+src_length;  
         XMLByte first_byte;          XMLByte first_byte;
         XMLCh UTF8_char;          XMLCh UTF8_char;
         while(uint char_size=readChar(src_ptr, src_end, first_byte, UTF8_char, tables)){          size_t dest_length=0;
   
           while(uint char_size=readChar(src, src_end, first_byte, UTF8_char, tables)){
                 if(char_size==1)                  if(char_size==1)
                         dest_length+=(!first_byte/*replacement char '?'*/ || !need_escape(first_byte))?1:3/*'%XX'*/;                          dest_length+=(!first_byte/*replacement char '?'*/ || !need_escape(first_byte))?1:3/*'%XX'*/;
                 else                  else
Line 549  size_t Charset::calc_escaped_length(XMLB Line 563  size_t Charset::calc_escaped_length(XMLB
 }  }
   
 size_t Charset::calc_escaped_length(const String::C src, const Charset& source_charset){  size_t Charset::calc_escaped_length(const String::C src, const Charset& source_charset){
         size_t src_length=src.length;          if(!src.length)
         if(!src_length)  
                 return 0;                  return 0;
   
 #ifdef PRECALCULATE_DEST_LENGTH  #ifdef PRECALCULATE_DEST_LENGTH
         if(source_charset.isUTF8())          if(source_charset.isUTF8())
                 return calc_escaped_length_UTF8((XMLByte *)src.str, src_length);                  return calc_escaped_length_UTF8((XMLByte *)src.str, src.length);
         else          else
                 return calc_escaped_length((XMLByte *)src.str, src_length, source_charset.tables);                  return calc_escaped_length((XMLByte *)src.str, src.length, source_charset.tables);
 #else  #else
         return src_length*6; // enough for %uXXXX but too memory-hungry          return src_length*6; // enough for %uXXXX but too memory-hungry
 #endif  #endif
Line 567  size_t Charset::calc_escaped_length(cons Line 580  size_t Charset::calc_escaped_length(cons
         if(char_size==1) \          if(char_size==1) \
                 if(first_byte){ \                  if(first_byte){ \
                         if(need_escape(first_byte)) \                          if(need_escape(first_byte)) \
                                 dest_ptr+=sprintf((char*)dest_ptr, "%%%02X", first_byte); /* %XX */ \                                  dest_ptr=append_hex_8(dest_ptr, first_byte, "%");  /* %XX */ \
                         else \                          else \
                                 *dest_ptr++=first_byte; /*as is*/ \                                  *dest_ptr++=first_byte; /*as is*/ \
                 } else \                  } else \
                         *dest_ptr++='?'; /* replacement char '?' */ \                          *dest_ptr++='?'; /* replacement char '?' */ \
         else \          else \
                 dest_ptr+=sprintf((char*)dest_ptr, "%%u%04X", UTF8_char); // %uXXXX                  dest_ptr=append_hex_16(dest_ptr, UTF8_char, "%u"); /* %uXXXX */
   
   
 size_t Charset::escape_UTF8(const XMLByte* src, size_t src_length, XMLByte* dest) {  size_t Charset::escape_UTF8(const XMLByte* src, size_t src_length, XMLByte* dest) {
Line 587  size_t Charset::escape_UTF8(const XMLByt Line 600  size_t Charset::escape_UTF8(const XMLByt
 }  }
   
 size_t Charset::escape(const XMLByte* src, size_t src_length, XMLByte* dest, const Charset::Tables& tables) {  size_t Charset::escape(const XMLByte* src, size_t src_length, XMLByte* dest, const Charset::Tables& tables) {
         const XMLByte* src_ptr=src;  
         const XMLByte* src_end=src+src_length;          const XMLByte* src_end=src+src_length;
         XMLByte* dest_ptr=dest;          XMLByte* dest_ptr=dest;
   
Line 595  size_t Charset::escape(const XMLByte* sr Line 607  size_t Charset::escape(const XMLByte* sr
         XMLCh UTF8_char;          XMLCh UTF8_char;
         uint char_size;          uint char_size;
   
         while(char_size=readChar(src_ptr, src_end, first_byte, UTF8_char, tables))          while(char_size=readChar(src, src_end, first_byte, UTF8_char, tables))
                 escape_char(dest_ptr, char_size, first_byte, UTF8_char)                  escape_char(dest_ptr, char_size, first_byte, UTF8_char)
   
         return dest_ptr - dest;          return dest_ptr - dest;
 }  }
   
 String::C Charset::escape(const String::C src, const Charset& source_charset){  String::C Charset::escape(const String::C src, const Charset& source_charset){
         size_t src_length=src.length;          if(!src.length)
         if(!src_length)  
                 return String::C("", 0);                  return String::C("", 0);
   
         size_t dest_calculated_length=calc_escaped_length(src, source_charset);          size_t dest_calculated_length=calc_escaped_length(src, source_charset);
Line 611  String::C Charset::escape(const String:: Line 622  String::C Charset::escape(const String::
   
         size_t dest_length;          size_t dest_length;
         if(source_charset.isUTF8())          if(source_charset.isUTF8())
                 dest_length=escape_UTF8((XMLByte *)src.str, src_length, dest_body);                  dest_length=escape_UTF8((XMLByte *)src.str, src.length, dest_body);
         else          else
                 dest_length=escape((XMLByte *)src.str, src_length, dest_body, source_charset.tables);                  dest_length=escape((XMLByte *)src.str, src.length, dest_body, source_charset.tables);
   
         if(dest_length>dest_calculated_length)          if(dest_length>dest_calculated_length)
                 throw Exception(0, 0, "Charset::escape buffer overflow");                  throw Exception(0, 0, "Charset::escape buffer overflow");
Line 623  String::C Charset::escape(const String:: Line 634  String::C Charset::escape(const String::
 }  }
   
 String::Body Charset::escape(const String::Body src, const Charset& source_charset) {  String::Body Charset::escape(const String::Body src, const Charset& source_charset) {
         const char *src_ptr=src.cstr();          String::C dest=Charset::escape(String::C(src.cstr(), src.length()), source_charset);
         size_t src_size=src.length();  
   
         String::C dest=Charset::escape(String::C(src_ptr, src_size), source_charset);  
   
         return String::Body(dest.length ? dest.str:0);          return String::Body(dest.length ? dest.str:0);
 }  }
   
Line 646  size_t Charset::calc_JSON_escaped_length Line 653  size_t Charset::calc_JSON_escaped_length
         size_t dest_length=0;          size_t dest_length=0;
   
         for(UTF8_string_iterator i(src, src_length); i.has_next(); ){          for(UTF8_string_iterator i(src, src_length); i.has_next(); ){
                 if(i.getCharSize()==1)                  if(i.getCharSize()==1){
                         dest_length+=need_json_escape(i.getFirstByte()) ? 2 : 1;                          XMLByte first_byte=i.getFirstByte();
                 else                          dest_length+=need_json_escape(first_byte) ? 2 : (first_byte < 0x20 && first_byte /* 0 replacement char is '?' */) ? 6 : 1;
                   } else
                         dest_length+=6; // \uXXXX                          dest_length+=6; // \uXXXX
         }          }
   
         return dest_length;          return dest_length;
 }  }
   
 size_t Charset::calc_JSON_escaped_length(XMLByte* src, size_t src_length, const Charset::Tables& tables){  size_t Charset::calc_JSON_escaped_length(const XMLByte* src, size_t src_length, const Charset::Tables& tables){
         const XMLByte* src_ptr=src;          const XMLByte* src_end=src+src_length;
         const XMLByte* src_end=src_ptr+src_length;  
         XMLByte first_byte;          XMLByte first_byte;
         XMLCh UTF8_char;          XMLCh UTF8_char;
         size_t dest_length=0;          size_t dest_length=0;
   
         while(uint char_size=readChar(src_ptr, src_end, first_byte, UTF8_char, tables)){          while(uint char_size=readChar(src, src_end, first_byte, UTF8_char, tables)){
                 if(char_size==1)                  if(char_size==1)
                         dest_length+=(!first_byte/*replacement char '?'*/ || !need_json_escape(first_byte))? 1 : 2;                          dest_length+=need_json_escape(first_byte) ? 2 : (first_byte < 0x20 && first_byte /* 0 replacement char is '?' */) ? 6 : 1;
                 else                  else
                         dest_length+=6; // \uXXXX                          dest_length+=6; // \uXXXX
         }          }
Line 673  size_t Charset::calc_JSON_escaped_length Line 680  size_t Charset::calc_JSON_escaped_length
 }  }
   
 size_t Charset::calc_JSON_escaped_length(const String::C src, const Charset& source_charset){  size_t Charset::calc_JSON_escaped_length(const String::C src, const Charset& source_charset){
         size_t src_length=src.length;          if(!src.length)
         if(!src_length)  
                 return 0;                  return 0;
   
 #ifdef PRECALCULATE_DEST_LENGTH  #ifdef PRECALCULATE_DEST_LENGTH
         if(source_charset.isUTF8())          if(source_charset.isUTF8())
                 return calc_JSON_escaped_length_UTF8((XMLByte *)src.str, src_length);                  return calc_JSON_escaped_length_UTF8((XMLByte *)src.str, src.length);
         else          else
                 return calc_JSON_escaped_length((XMLByte *)src.str, src_length, source_charset.tables);                  return calc_JSON_escaped_length((XMLByte *)src.str, src.length, source_charset.tables);
 #else  #else
         return src_length*6; // enough for \uXXXX but too memory-hungry          return src_length*6; // enough for \uXXXX but too memory-hungry
 #endif  #endif
Line 699  size_t Charset::calc_JSON_escaped_length Line 705  size_t Charset::calc_JSON_escaped_length
                         case '\b': *dest_ptr++='\\'; *dest_ptr++='b';  break; \                          case '\b': *dest_ptr++='\\'; *dest_ptr++='b';  break; \
                         case '\f': *dest_ptr++='\\'; *dest_ptr++='f';  break; \                          case '\f': *dest_ptr++='\\'; *dest_ptr++='f';  break; \
                         case   0 : *dest_ptr++='?'; break; /*replacement char*/ \                          case   0 : *dest_ptr++='?'; break; /*replacement char*/ \
                         default  : *dest_ptr++=first_byte; \                          default  : if(first_byte < 0x20) dest_ptr=append_hex_16(dest_ptr, UTF8_char, "\\u"); \
                                                   else *dest_ptr++=first_byte; \
                 } \                  } \
         else \          else \
                 dest_ptr+=sprintf((char*)dest_ptr, "\\u%04X", UTF8_char); // \uXXXX                  dest_ptr=append_hex_16(dest_ptr, UTF8_char, "\\u"); // \uXXXX
   
   
 size_t Charset::escape_JSON_UTF8(const XMLByte* src, size_t src_length, XMLByte* dest) {  size_t Charset::escape_JSON_UTF8(const XMLByte* src, size_t src_length, XMLByte* dest) {
Line 716  size_t Charset::escape_JSON_UTF8(const X Line 723  size_t Charset::escape_JSON_UTF8(const X
 }  }
   
 size_t Charset::escape_JSON(const XMLByte* src, size_t src_length, XMLByte* dest, const Charset::Tables& tables) {  size_t Charset::escape_JSON(const XMLByte* src, size_t src_length, XMLByte* dest, const Charset::Tables& tables) {
         const XMLByte* src_ptr=src;  
         const XMLByte* src_end=src+src_length;          const XMLByte* src_end=src+src_length;
         XMLByte* dest_ptr=dest;          XMLByte* dest_ptr=dest;
   
Line 724  size_t Charset::escape_JSON(const XMLByt Line 730  size_t Charset::escape_JSON(const XMLByt
         XMLCh UTF8_char;          XMLCh UTF8_char;
         uint char_size;          uint char_size;
   
         while(char_size=readChar(src_ptr, src_end, first_byte, UTF8_char, tables))          while(char_size=readChar(src, src_end, first_byte, UTF8_char, tables))
                 escape_char_JSON(dest_ptr, char_size, first_byte, UTF8_char)                  escape_char_JSON(dest_ptr, char_size, first_byte, UTF8_char)
   
         return dest_ptr - dest;          return dest_ptr - dest;
 }  }
   
 String::C Charset::escape_JSON(const String::C src, const Charset& source_charset){  String::C Charset::escape_JSON(const String::C src, const Charset& source_charset){
         size_t src_length=src.length;          if(!src.length)
         if(!src_length)  
                 return String::C("", 0);                  return String::C("", 0);
   
   
         size_t dest_calculated_length=calc_JSON_escaped_length(src, source_charset);          size_t dest_calculated_length=calc_JSON_escaped_length(src, source_charset);
         XMLByte *dest_body=new(PointerFreeGC) XMLByte[dest_calculated_length+1/*terminator*/];          XMLByte *dest_body=new(PointerFreeGC) XMLByte[dest_calculated_length+1/*terminator*/];
   
         size_t dest_length;          size_t dest_length;
         if(source_charset.isUTF8())          if(source_charset.isUTF8())
                 dest_length=escape_JSON_UTF8((XMLByte *)src.str, src_length, dest_body);                  dest_length=escape_JSON_UTF8((XMLByte *)src.str, src.length, dest_body);
         else          else
                 dest_length=escape_JSON((XMLByte *)src.str, src_length, dest_body, source_charset.tables);                  dest_length=escape_JSON((XMLByte *)src.str, src.length, dest_body, source_charset.tables);
   
         if(dest_length>dest_calculated_length)          if(dest_length>dest_calculated_length)
                 throw Exception(0, 0, "Charset::escape_JSON buffer overflow");                  throw Exception(0, 0, "Charset::escape_JSON buffer overflow");
Line 753  String::C Charset::escape_JSON(const Str Line 757  String::C Charset::escape_JSON(const Str
 }  }
   
 String::Body Charset::escape_JSON(const String::Body src, const Charset& source_charset) {  String::Body Charset::escape_JSON(const String::Body src, const Charset& source_charset) {
         const char *src_ptr=src.cstr();          String::C dest=Charset::escape_JSON(String::C(src.cstr(), src.length()), source_charset);
         size_t src_size=src.length();  
   
         String::C dest=Charset::escape_JSON(String::C(src_ptr, src_size), source_charset);  
   
         return String::Body(dest.length ? dest.str:0);          return String::Body(dest.length ? dest.str:0);
 }  }
   
Line 792  const String::C Charset::transcodeToUTF8 Line 792  const String::C Charset::transcodeToUTF8
                 (XMLByte *)src.str, src_length,                  (XMLByte *)src.str, src_length,
                 dest_body, dest_length,                  dest_body, dest_length,
                 tables)<0)                  tables)<0)
                 throw Exception(0,                  throw Exception(0, 0, "Charset::transcodeToUTF8 buffer overflow");
                         0,  
                         "Charset::transcodeToUTF8 buffer overflow");  
   
         assert(dest_length<=saved_dest_length);          assert(dest_length<=saved_dest_length);
         dest_body[dest_length]=0; // terminator          dest_body[dest_length]=0; // terminator
Line 869  static void store_UTF8(XMLCh src, XMLByt Line 867  static void store_UTF8(XMLCh src, XMLByt
         outPtr+= encodedBytes;          outPtr+= encodedBytes;
 }  }
   
 static void change_case_UTF8(XMLCh src, XMLByte*& outPtr,   static void change_case_UTF8(XMLCh src, XMLByte*& outPtr, const Charset::UTF8CaseTable& table) {
                                                 const Charset::UTF8CaseTable& table) {  
         store_UTF8(change_case_UTF8(src, table), outPtr);          store_UTF8(change_case_UTF8(src, table), outPtr);
 };  }
 void change_case_UTF8(const XMLByte* srcData, size_t srcLen,  
                                           XMLByte* toFill, size_t toFillLen,  void change_case_UTF8(const XMLByte* srcData, size_t srcLen, XMLByte* toFill, size_t toFillLen, const Charset::UTF8CaseTable& table) {
                                           const Charset::UTF8CaseTable& table) {  
         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 907  void change_case_UTF8(const XMLByte* src Line 903  void change_case_UTF8(const XMLByte* src
                         break;                          break;
                                                   
                 default:                  default:
                         throw Exception(0,                          throw Exception(0, 0, "change_case_UTF8 error: wrong trailingBytes value(%d)", trailingBytes);
                                 0,  
                                 "change_case_UTF8 error: wrong trailingBytes value(%d)", trailingBytes);  
                 }                  }
                 tmpVal-=gUTFOffsets[trailingBytes];                  tmpVal-=gUTFOffsets[trailingBytes];
                                   
Line 919  void change_case_UTF8(const XMLByte* src Line 913  void change_case_UTF8(const XMLByte* src
                 if(!(tmpVal & 0xFFFF0000))                  if(!(tmpVal & 0xFFFF0000))
                         change_case_UTF8(tmpVal, outPtr, table);                          change_case_UTF8(tmpVal, outPtr, table);
                 else                  else
                         throw Exception(0,                          throw Exception(0, 0, "change_case_UTF8 error: too big tmpVal(0x%08X)", tmpVal);
                                 0,  
                                 "change_case_UTF8 error: too big tmpVal(0x%08X)", tmpVal);  
         }          }
                   
         if(srcPtr!=outPtr)          if(srcPtr!=outPtr)
                 throw Exception(0,                    throw Exception(0, 0, "change_case_UTF8 error: end pointers do not match");
                         0,  
                         "change_case_UTF8 error: end pointers do not match");  
 }  }
   
 static size_t getDecNumLength(XMLCh UTF8Char){  static size_t getDecNumLength(XMLCh UTF8Char){
Line 946  const String::C Charset::transcodeFromUT Line 936  const String::C Charset::transcodeFromUT
 #ifdef PRECALCULATE_DEST_LENGTH  #ifdef PRECALCULATE_DEST_LENGTH
         int dest_length=0;          int dest_length=0;
         for(UTF8_string_iterator i((XMLByte *)src.str, src_length); i.has_next(); ){          for(UTF8_string_iterator i((XMLByte *)src.str, src_length); i.has_next(); ){
                 if(i.getCharSize()==1)                  dest_length += ( i.next() & 0xFFFF0000 )
                         dest_length++;                                                  ? 3*i.getCharSize()                                             // %XX for each byte
                 else                                                  : ( xlatOneTo(i.next(), tables, 0) != 0 )
                         dest_length+=(i.next() & 0xFFFF0000)                                                          ? 1                                                                     // can convert it to a single char
                                                         ?i.getCharSize()*3      // '%XX' for each byte                                                          : 3+getDecNumLength( i.next() );        // print char as &#XX;, &#XXX;, &#XXXX; or &#XXXXX;
                                                         :(xlatOneTo(i.next(), tables, 0)!=0)  
                                                                 ?1              // can convert it to single char  
                                                                 :getDecNumLength(i.next())+3;           // &#XX; - &#XXXXX;  
         }          }
 #else  #else
         // so that surly enough, "&#XXX;" has max ratio (huh? 8 bytes needed for '&#XXXXX;')          // so that surly enough, "&#XXX;" has max ratio (huh? 8 bytes needed for '&#XXXXX;')
Line 969  const String::C Charset::transcodeFromUT Line 956  const String::C Charset::transcodeFromUT
                 (XMLByte *)src.str, src_length,                  (XMLByte *)src.str, src_length,
                 dest_body, dest_length,                  dest_body, dest_length,
                 tables)<0)                  tables)<0)
                 throw Exception(0,                   throw Exception(0, 0, "Charset::transcodeFromUTF8 buffer overflow");
                         0,  
                         "Charset::transcodeFromUTF8 buffer overflow");  
   
         assert(dest_length<=saved_dest_length);          assert(dest_length<=saved_dest_length);
         dest_body[dest_length]=0; // terminator          dest_body[dest_length]=0; // terminator
Line 979  const String::C Charset::transcodeFromUT Line 964  const String::C Charset::transcodeFromUT
 }  }
   
 /// transcode using both charsets  /// transcode using both charsets
 const String::C Charset::transcodeToCharset(const String::C src,   const String::C Charset::transcodeToCharset(const String::C src, const Charset& dest_charset) const {
                                                 const Charset& dest_charset) const {  
         if(&dest_charset==this)           if(&dest_charset==this) 
                 return src;                  return src;
         else {          else {
Line 1079  static size_t handlers_count=0; Line 1063  static size_t handlers_count=0;
   
 void Charset::addEncoding(char *name_cstr) {  void Charset::addEncoding(char *name_cstr) {
         if(handlers_count==MAX_CHARSETS)          if(handlers_count==MAX_CHARSETS)
                 throw Exception(0,                  throw Exception(0, 0, "already allocated %d handlers, no space for new encoding '%s'", MAX_CHARSETS, name_cstr);
                         0,  
                         "already allocated %d handlers, no space for new encoding '%s'",  
                                 MAX_CHARSETS, name_cstr);  
   
         xmlCharEncodingHandler* handler=new(UseGC) xmlCharEncodingHandler;          xmlCharEncodingHandler* handler=new xmlCharEncodingHandler;
         {          {
                 handler->name=name_cstr;                  handler->name=name_cstr;
                 handler->input=inputFuncs[handlers_count];                   handler->input=inputFuncs[handlers_count]; 
Line 1104  void Charset::initTranscoder(const Strin Line 1085  void Charset::initTranscoder(const Strin
   
 xmlCharEncodingHandler& Charset::transcoder(const String::Body NAME) {  xmlCharEncodingHandler& Charset::transcoder(const String::Body NAME) {
         if(!ftranscoder)          if(!ftranscoder)
                 throw Exception(PARSER_RUNTIME,                  throw Exception(PARSER_RUNTIME, new String(NAME, String::L_TAINTED), "unsupported encoding");
                         new String(NAME, String::L_TAINTED),  
                         "unsupported encoding");  
         return *ftranscoder;          return *ftranscoder;
 }  }
   
Line 1135  String::C Charset::transcode_cstr(const Line 1114  String::C Charset::transcode_cstr(const
                 error=0;                  error=0;
         }          }
         if(error<0)          if(error<0)
                 throw Exception(0,                  throw Exception(0, 0, "transcode_cstr failed (%d)", error);
                         0,  
                         "transcode_cstr failed (%d)", error);  
   
         assert(outlen<=saved_outlen); out[outlen]=0;          assert(outlen<=saved_outlen); out[outlen]=0;
         return String::C(out, outlen);          return String::C(out, outlen);
Line 1179  xmlChar* Charset::transcode_buf2xchar(co Line 1156  xmlChar* Charset::transcode_buf2xchar(co
         }          }
                   
         if(error<0)          if(error<0)
                 throw Exception(0,                  throw Exception(0, 0, "transcode_buf failed (%d)", error);
                         0,  
                         "transcode_buf failed (%d)", error);  
   
         assert(outlen<=saved_outlen); out[outlen]=0;          assert(outlen<=saved_outlen); out[outlen]=0;
         return out;          return out;
Line 1197  xmlChar* Charset::transcode(const String Line 1172  xmlChar* Charset::transcode(const String
 }  }
 #endif  #endif
   
 String::Body Charset::transcode(const String::Body src,   String::Body Charset::transcode(const String::Body src, const Charset& source_transcoder, const Charset& dest_transcoder) {
         const Charset& source_transcoder,           return String::Body(Charset::transcode(String::C(src.cstr(), src.length()), source_transcoder, dest_transcoder));
         const Charset& dest_transcoder) {  
   
         const char *src_ptr=src.cstr();  
         size_t src_size=src.length();  
   
         String::C dest=Charset::transcode(String::C(src_ptr, src_size), source_transcoder, dest_transcoder);  
   
         return String::Body(dest.length ? dest.str:0);  
 }  }
   
 String& Charset::transcode(const String& src,   String& Charset::transcode(const String& src, const Charset& source_transcoder, const Charset& dest_transcoder) {
         const Charset& source_transcoder,   
         const Charset& dest_transcoder) {  
         if(src.is_empty())          if(src.is_empty())
                 return *new String();                  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);
 }  }
   
 void Charset::transcode(ArrayString& src,  void Charset::transcode(ArrayString& src, const Charset& source_transcoder, const Charset& dest_transcoder) {
         const Charset& source_transcoder,   
         const Charset& dest_transcoder) {  
         for(size_t i=0; i<src.count(); i++)          for(size_t i=0; i<src.count(); i++)
                 src.put(i, &transcode(*src[i], source_transcoder, dest_transcoder));                  src.put(i, &transcode(*src[i], source_transcoder, dest_transcoder));
 }  }
Line 1231  struct Transcode_pair_info { Line 1194  struct Transcode_pair_info {
         const Charset* dest_transcoder;          const Charset* dest_transcoder;
 };  };
 #endif  #endif
 static void transcode_pair(HashStringValue::key_type /*akey*/,   static void transcode_pair(HashStringValue::key_type /*akey*/, String::Body& avalue, Transcode_pair_info* info) {
                          String::Body& avalue,           avalue=Charset::transcode(avalue, *info->source_transcoder, *info->dest_transcoder);
                          Transcode_pair_info* info) {  
         avalue=Charset::transcode(avalue,  
                 *info->source_transcoder,   
                 *info->dest_transcoder);  
 }  }
   
 void Charset::transcode(HashStringString& src,  void Charset::transcode(HashStringString& src, const Charset& source_transcoder, const Charset& dest_transcoder) {
         const Charset& source_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);
 }  }
Line 1264  size_t getUTF8CharPos(const XMLByte* src Line 1221  size_t getUTF8CharPos(const XMLByte* src
         }          }
   
         // scan till end but position in bytes still too low          // scan till end but position in bytes still too low
         throw Exception(0,          throw Exception(0, 0, "Error convertion byte pos to char pos");
                                         0,  
                                         "Error convertion byte pos to char pos");  
 }  }
   
 size_t lengthUTF8(const XMLByte* srcBegin, const XMLByte* srcEnd){  size_t lengthUTF8(const XMLByte* srcBegin, const XMLByte* srcEnd){
Line 1281  unsigned int lengthUTF8Char(const XMLByt Line 1236  unsigned int lengthUTF8Char(const XMLByt
         return gUTFBytes[c]+1;          return gUTFBytes[c]+1;
 }  }
   
   const char *fixUTF8(const char *src){
           if(src && *src){
                   size_t length=strlen(src);
   
                   int error_offset;
                   if(pa_pcre_valid_utf((unsigned char *)src, length, &error_offset)){
   
                           char *result=(char *)pa_malloc_atomic(length+1);
                           char *dst=result;
   
                           do {
   
                                   if(error_offset){
                                           strncpy(dst, src, error_offset);
                                           dst+=error_offset;
   
                                           src+=error_offset;
                                           length-=error_offset;
   
                                   }
   
                                   *dst++='?';
                                   src++;
                                   length--;
   
                           } while (length && pa_pcre_valid_utf((unsigned char *)src, length, &error_offset));
   
                           if(length){
                                   strcpy(dst, src);
                           } else {
                                   *dst='\0';
                           }
   
                           return result;
                   }
           }
           return src;
   }
   
 bool UTF8_string_iterator::has_next(){  bool UTF8_string_iterator::has_next(){
         fcharSize=readUTF8Char(fsrcPtr, fsrcEnd, ffirstByte, fUTF8Char);          fcharSize=readUTF8Char(fsrcPtr, fsrcEnd, ffirstByte, fUTF8Char);
         return fcharSize!=0;          return fcharSize!=0;

Removed from v.1.85  
changed lines
  Added in v.1.102


E-mail: