Diff for /parser3/src/main/pa_charset.C between versions 1.83 and 1.87

version 1.83, 2009/10/15 01:07:54 version 1.87, 2010/09/21 21:45:20
Line 171  void Charset::load_definition(Request_ch Line 171  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 433  of ocetes consumed. Line 442  of ocetes consumed.
         return 0;          return 0;
 }  }
   
 static bool isEscaped(XMLByte c){  static bool need_escape(XMLByte c){
         return          return
                 !(                  !(
                         (c<=127)                          (c<=127)
Line 492  static unsigned int skipUTF8Char(const X Line 501  static unsigned int skipUTF8Char(const X
         return trailingBytes;          return trailingBytes;
 }  }
   
 // read non-UTF8 char, and return number of bytes needed for store this char in UTF8  // read non-UTF8 char, and return number of bytes needed for storing this char in UTF8
 static unsigned int readChar(const XMLByte*& srcPtr, const XMLByte* srcEnd, XMLByte& firstByte, XMLCh& UTF8Char, const Charset::Tables& tables){  static unsigned int readChar(const XMLByte*& srcPtr, const XMLByte* srcEnd, XMLByte& firstByte, XMLCh& UTF8Char, const Charset::Tables& tables){
         if(!srcPtr || !*srcPtr || srcPtr>=srcEnd)          if(!srcPtr || !*srcPtr || srcPtr>=srcEnd)
                 return 0;                  return 0;
Line 518  static unsigned int readChar(const XMLBy Line 527  static unsigned int readChar(const XMLBy
         return 1;          return 1;
 }  }
   
 static int escapeUTF8(const XMLByte* srcData, size_t& srcLen,  size_t Charset::calc_escaped_length_UTF8(XMLByte* src, size_t src_length){
                                 XMLByte* toFill, size_t& toFillLen) {          size_t dest_length=0;
         const XMLByte* srcPtr=srcData;  
         XMLByte* outPtr=toFill;          for(UTF8_string_iterator i(src, src_length); i.has_next(); ){
         XMLByte* outEnd=toFill+toFillLen;                  if(i.getCharSize()==1)
         // loop until we either run out of input data, or room to store                          dest_length+=!need_escape(i.getFirstByte())?1/*as-is*/:3/*%XX*/;
         for(UTF8_string_iterator i((XMLByte *)srcPtr, srcLen); (outPtr < outEnd) && i.has_next(); ){                  else
                 if(i.getCharSize()==1){                          dest_length+=6; // %uXXXX
                         if(isEscaped(i.getFirstByte())) // %XX  
                                 outPtr+=sprintf((char*)outPtr, "%%%02X", i.getFirstByte());  
                         else  
                                 *outPtr++=i.getFirstByte();  
                 } else  
                         outPtr+=sprintf((char*)outPtr, "%%u%04X", i.next()); // %uXXXX  
         }          }
         // Update the bytes eaten  
         srcLen=srcPtr-srcData;  
           
         // Return the characters read  
         toFillLen=outPtr-toFill;  
   
         return 0;          return dest_length;
 }  }
   
 static int escape(const XMLByte* srcData, size_t& srcLen,  size_t Charset::calc_escaped_length(const XMLByte* src, size_t src_length, const Charset::Tables& tables){
                            XMLByte *toFill, size_t& toFillLen,          const XMLByte* src_end=src+src_length;
                            const Charset::Tables& tables) {          XMLByte first_byte;
         const XMLByte* srcPtr=srcData;          XMLCh UTF8_char;
         const XMLByte* srcEnd=srcData+srcLen;          size_t dest_length=0;
         XMLByte* outPtr=toFill;  
         XMLByte firstByte;          while(uint char_size=readChar(src, src_end, first_byte, UTF8_char, tables)){
         XMLCh UTF8Char;                  if(char_size==1)
         uint charSize;                          dest_length+=(!first_byte/*replacement char '?'*/ || !need_escape(first_byte))?1:3/*'%XX'*/;
                   else
         while(charSize=readChar(srcPtr, srcEnd, firstByte, UTF8Char, tables)){                          dest_length+=6; // %uXXXX
                 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          return dest_length;
         srcLen = srcPtr - srcData;  }
           
         // Return the characters read  size_t Charset::calc_escaped_length(const String::C src, const Charset& source_charset){
         toFillLen = outPtr - toFill;          if(!src.length)
                   return 0;
   
   #ifdef PRECALCULATE_DEST_LENGTH
           if(source_charset.isUTF8())
                   return calc_escaped_length_UTF8((XMLByte *)src.str, src.length);
           else
                   return calc_escaped_length((XMLByte *)src.str, src.length, source_charset.tables);
   #else
           return src_length*6; // enough for %uXXXX but too memory-hungry
   #endif
   }
   
   #define escape_char(dest_ptr, char_size, first_byte, UTF8_char) \
           if(char_size==1) \
                   if(first_byte){ \
                           if(need_escape(first_byte)) \
                                   dest_ptr+=sprintf((char*)dest_ptr, "%%%02X", first_byte); /* %XX */ \
                           else \
                                   *dest_ptr++=first_byte; /*as is*/ \
                   } else \
                           *dest_ptr++='?'; /* replacement char '?' */ \
           else \
                   dest_ptr+=sprintf((char*)dest_ptr, "%%u%04X", UTF8_char); // %uXXXX
   
   
   size_t Charset::escape_UTF8(const XMLByte* src, size_t src_length, XMLByte* dest) {
           XMLByte* dest_ptr=dest;
   
           // loop until we either run out of input data
           for(UTF8_string_iterator i((XMLByte *)src, src_length); i.has_next(); )
                   escape_char(dest_ptr, i.getCharSize(), i.getFirstByte(), i.next())
                   
         return 0;          return dest_ptr - dest;
 }  }
   
   size_t Charset::escape(const XMLByte* src, size_t src_length, XMLByte* dest, const Charset::Tables& tables) {
           const XMLByte* src_end=src+src_length;
           XMLByte* dest_ptr=dest;
   
           XMLByte first_byte;
           XMLCh UTF8_char;
           uint char_size;
   
           while(char_size=readChar(src, src_end, first_byte, UTF8_char, tables))
                   escape_char(dest_ptr, char_size, first_byte, UTF8_char)
   
           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);
   
 #ifdef PRECALCULATE_DEST_LENGTH          size_t dest_calculated_length=calc_escaped_length(src, source_charset);
           XMLByte *dest_body=new(PointerFreeGC) XMLByte[dest_calculated_length+1/*terminator*/];
   
           size_t dest_length;
           if(source_charset.isUTF8())
                   dest_length=escape_UTF8((XMLByte *)src.str, src.length, dest_body);
           else
                   dest_length=escape((XMLByte *)src.str, src.length, dest_body, source_charset.tables);
   
           if(dest_length>dest_calculated_length)
                   throw Exception(0, 0, "Charset::escape buffer overflow");
   
           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) {
           String::C dest=Charset::escape(String::C(src.cstr(), src.length()), source_charset);
           return String::Body(dest.length ? dest.str:0);
   }
   
   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);
   }
   
   inline bool need_json_escape(unsigned char c){
           return strchr("\n\"\\/\t\r\b\f", c)!=0;
   }
   
   size_t Charset::calc_JSON_escaped_length_UTF8(XMLByte* src, size_t src_length){
         size_t dest_length=0;          size_t dest_length=0;
   
         if(source_charset.isUTF8()){          for(UTF8_string_iterator i(src, src_length); i.has_next(); ){
                 for(UTF8_string_iterator i((XMLByte *)src.str, src_length); i.has_next(); ){                  if(i.getCharSize()==1)
                         if(i.getCharSize()==1)                          dest_length+=need_json_escape(i.getFirstByte()) ? 2 : 1;
                                 dest_length+=!isEscaped(i.getFirstByte())?1/*as-is*/:3/*%XX*/;                  else
                         else                          dest_length+=6; // \uXXXX
                                 dest_length+=6/*%uXXXX*/;          }
                 }  
         } else {          return dest_length;
                 const XMLByte* srcPtr=(XMLByte*)src.str;  }
                 const XMLByte* srcEnd=srcPtr+src_length;  
                 XMLByte firstByte;  size_t Charset::calc_JSON_escaped_length(const XMLByte* src, size_t src_length, const Charset::Tables& tables){
                 XMLCh UTF8Char;          const XMLByte* src_end=src+src_length;
                 while(uint charSize=readChar(srcPtr, srcEnd, firstByte, UTF8Char, source_charset.tables)){          XMLByte first_byte;
                         if(charSize==1)          XMLCh UTF8_char;
                                 dest_length+=(!firstByte/*replacement char '?'*/ || !isEscaped(firstByte))?1:3/*'%XX'*/;          size_t dest_length=0;
                         else  
                                 dest_length+=6; // '%uXXXX'          while(uint char_size=readChar(src, src_end, first_byte, UTF8_char, tables)){
                 }                  if(char_size==1)
                           dest_length+=(!first_byte/*replacement char '?'*/ || !need_json_escape(first_byte))? 1 : 2;
                   else
                           dest_length+=6; // \uXXXX
         }          }
   
           return dest_length;
   }
   
   size_t Charset::calc_JSON_escaped_length(const String::C src, const Charset& source_charset){
           if(!src.length)
                   return 0;
   
   #ifdef PRECALCULATE_DEST_LENGTH
           if(source_charset.isUTF8())
                   return calc_JSON_escaped_length_UTF8((XMLByte *)src.str, src.length);
           else
                   return calc_JSON_escaped_length((XMLByte *)src.str, src.length, source_charset.tables);
 #else  #else
         size_t dest_length=src_length*6; // enough for %uXXXX but too memory-hungry          return src_length*6; // enough for \uXXXX but too memory-hungry
 #endif  #endif
   }
   
         //throw Exception(0,0,"%u",dest_length);  #define escape_char_JSON(dest_ptr, char_size, first_byte, UTF8_char) \
           if(char_size==1) \
                   switch(first_byte){ \
                           case '\n': *dest_ptr++='\\'; *dest_ptr++='n';  break; \
                           case '"' : *dest_ptr++='\\'; *dest_ptr++='"';  break; \
                           case '\\': *dest_ptr++='\\'; *dest_ptr++='\\'; break; \
                           case '/' : *dest_ptr++='\\'; *dest_ptr++='/';  break; \
                           case '\t': *dest_ptr++='\\'; *dest_ptr++='t';  break; \
                           case '\r': *dest_ptr++='\\'; *dest_ptr++='r';  break; \
                           case '\b': *dest_ptr++='\\'; *dest_ptr++='b';  break; \
                           case '\f': *dest_ptr++='\\'; *dest_ptr++='f';  break; \
                           case   0 : *dest_ptr++='?'; break; /*replacement char*/ \
                           default  : *dest_ptr++=first_byte; \
                   } \
           else \
                   dest_ptr+=sprintf((char*)dest_ptr, "\\u%04X", UTF8_char); // \uXXXX
   
 #ifndef NDEBUG  
         size_t saved_dest_length=dest_length;  
 #endif  
         XMLByte *dest_body=new(PointerFreeGC) XMLByte[dest_length+1/*for terminator*/];  
   
         int status;  size_t Charset::escape_JSON_UTF8(const XMLByte* src, size_t src_length, XMLByte* dest) {
         if(source_charset.isUTF8()){          XMLByte* dest_ptr=dest;
                 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)          // loop until we either run out of input data
                 throw Exception(0,          for(UTF8_string_iterator i((XMLByte *)src, src_length); i.has_next(); )
                         0,                  escape_char_JSON(dest_ptr, i.getCharSize(), i.getFirstByte(), i.next())
                         "Charset::escape buffer overflow");  
           return dest_ptr - dest;
   }
   
   size_t Charset::escape_JSON(const XMLByte* src, size_t src_length, XMLByte* dest, const Charset::Tables& tables) {
           const XMLByte* src_end=src+src_length;
           XMLByte* dest_ptr=dest;
   
           XMLByte first_byte;
           XMLCh UTF8_char;
           uint char_size;
   
           while(char_size=readChar(src, src_end, first_byte, UTF8_char, tables))
                   escape_char_JSON(dest_ptr, char_size, first_byte, UTF8_char)
   
           return dest_ptr - dest;
   }
   
   String::C Charset::escape_JSON(const String::C src, const Charset& source_charset){
           if(!src.length)
                   return String::C("", 0);
   
           size_t dest_calculated_length=calc_JSON_escaped_length(src, source_charset);
           XMLByte *dest_body=new(PointerFreeGC) XMLByte[dest_calculated_length+1/*terminator*/];
   
           size_t dest_length;
           if(source_charset.isUTF8())
                   dest_length=escape_JSON_UTF8((XMLByte *)src.str, src.length, dest_body);
           else
                   dest_length=escape_JSON((XMLByte *)src.str, src.length, dest_body, source_charset.tables);
   
           if(dest_length>dest_calculated_length)
                   throw Exception(0, 0, "Charset::escape_JSON buffer overflow");
   
         assert(dest_length<=saved_dest_length);  
         dest_body[dest_length]=0; // terminator          dest_body[dest_length]=0; // terminator
         return String::C((char*)dest_body, dest_length);          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=src.length();  
   
         String::C dest=Charset::escape(String::C(src_ptr, src_size), source_charset);  
   
   String::Body Charset::escape_JSON(const String::Body src, const Charset& source_charset) {
           String::C dest=Charset::escape_JSON(String::C(src.cstr(), src.length()), source_charset);
         return String::Body(dest.length ? dest.str:0);          return String::Body(dest.length ? dest.str:0);
 }  }
   
 String& Charset::escape(const String& src, const Charset& source_charset) {  String& Charset::escape_JSON(const String& src, const Charset& source_charset) {
         if(src.is_empty())          if(src.is_empty())
                 return *new String();                  return *new String();
   
         return *new String(escape((String::Body)src, source_charset), String::L_CLEAN);          return *new String(escape_JSON((String::Body)src, source_charset), String::L_CLEAN);
 }  }
   
 const String::C Charset::transcodeToUTF8(const String::C src) const {  const String::C Charset::transcodeToUTF8(const String::C src) const {
Line 658  const String::C Charset::transcodeToUTF8 Line 772  const String::C Charset::transcodeToUTF8
         while(uint charSize=readChar(srcPtr, srcEnd, firstByte, UTF8Char, tables))          while(uint charSize=readChar(srcPtr, srcEnd, firstByte, UTF8Char, tables))
                 dest_length+=charSize;                  dest_length+=charSize;
 #else  #else
         int dest_length=src_length*6; // so that surly enough (max utf8 seq len=6) but too memory-hyngry          int dest_length=src_length*6; // so that surly enough (max utf8 seq len=6) but too memory-hungry
 #endif  #endif
   
         //throw Exception(0,0,"%u",dest_length);  
   
 #ifndef NDEBUG  #ifndef NDEBUG
         int saved_dest_length=dest_length;          int saved_dest_length=dest_length;
 #endif  #endif
Line 1157  size_t lengthUTF8(const XMLByte* srcBegi Line 1269  size_t lengthUTF8(const XMLByte* srcBegi
         return size;          return size;
 }  }
   
   unsigned int lengthUTF8Char(const XMLByte c){
           return gUTFBytes[c]+1;
   }
   
 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.83  
changed lines
  Added in v.1.87


E-mail: