Diff for /parser3/src/main/pa_string.C between versions 1.169 and 1.172.2.2

version 1.169, 2002/08/21 10:52:49 version 1.172.2.2, 2003/01/23 15:38:06
Line 1 Line 1
 /** @file  /** @file
         Parser: string class. @see untasize_t.C.          Parser: string class. @see untasize_t.C.
   
         Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com)          Copyright (c) 2001, 2003 ArtLebedev Group (http://www.artlebedev.com)
         Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)          Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
 */  */
   
Line 11  static const char* IDENT_STRING_C="$Date Line 11  static const char* IDENT_STRING_C="$Date
   
 #include "pa_pool.h"  #include "pa_pool.h"
 #include "pa_string.h"  #include "pa_string.h"
 #include "pa_hash.h"  //#include "pa_hash.h"
 #include "pa_exception.h"  #include "pa_exception.h"
 #include "pa_common.h"  //#include "pa_common.h"
 #include "pa_array.h"  #include "pa_array.h"
 #include "pa_globals.h"  //#include "pa_globals.h"
 #include "pa_table.h"  #include "pa_table.h"
 #include "pa_dictionary.h"  #include "pa_dictionary.h"
 #include "pa_charset.h"  #include "pa_charset.h"
   
 #define DEBUG_STRING_APPENDS_VS_EXPANDS  // helpers
   
   /// String::match uses this as replace & global search table columns
   const int MAX_STRING_MATCH_TABLE_COLUMNS=100;
   
 #ifdef DEBUG_STRING_APPENDS_VS_EXPANDS  class String_match_table_template_columns: public Array<smart_ptr<String>> {
 ulong string_piece_appends=0;          char cn_cstr[MAX_STRING_MATCH_TABLE_COLUMNS][3/*strlen("100")*/+1/*terminating 0*/];
 #endif          String cn[MAX_STRING_MATCH_TABLE_COLUMNS];
   public:
           string_match_table_template_columns_class() {
                   *this+=smart_ptr<String>(new String("prematch"));
                   *this+=smart_ptr<String>(new String("match"));
                   *this+=smart_ptr<String>(new String("postmatch"));
                   for(int i=0; i<MAX_STRING_MATCH_TABLE_COLUMNS; i++) {
                           sprintf(cn_cstr[i], "%d", 1+i);
                           cn[i].APPEND_CLEAN(cn_cstr[i]);
                           *this+=cn[i];
                   }
           }
   } string_match_table_template_columns;
   
 String& String::OnPool(Pool& apool, const char *local_src, size_t src_size, bool tainted) {  Table string_match_table_template(0, string_match_table_template_columns);
         if(local_src && *local_src) {  
                 if(src_size==0)  // methods
                         src_size=strlen(local_src);  
                   
                 char *pooled_src=(char *)apool.malloc(src_size);  
                 memcpy(pooled_src, local_src, src_size);  
                 return *new(apool) String(apool, pooled_src, src_size, tainted);  
         } else  
                 return *new(apool) String(apool);  
 }  
 String::String(Pool& apool, const char *src, size_t src_size, bool tainted) :  
         Pooled(apool) {  
         last_chunk=&head.chunk;  
         head.chunk.count=CR_PREALLOCATED_COUNT;  
         append_here=head.chunk.rows;  
   
   String::String(const char *src, size_t src_size, bool tainted): Array(1), fsize(0) {
         if(src)          if(src)
                 if(tainted)                  if(tainted)
                         APPEND_TAINTED(src, src_size, 0, 0);                          APPEND_TAINTED(src, src_size, 0, 0);
Line 51  String::String(Pool& apool, const char * Line 53  String::String(Pool& apool, const char *
                         APPEND_CLEAN(src, src_size, 0, 0);                          APPEND_CLEAN(src, src_size, 0, 0);
 }  }
   
 String::String(const String& src) :       String::String(const String& src): Array(src.count()) {
         Pooled(src.pool()) {  
         last_chunk=&head.chunk;  
         head.chunk.count=CR_PREALLOCATED_COUNT;  
         append_here=head.chunk.rows;  
   
         append(src, UL_PASS_APPENDED);          append(src, UL_PASS_APPENDED);
 }  }
   
 size_t  String::size() const {  
         size_t result=0;  
         STRING_FOREACH_ROW(  
                         result+=row->item.size;  
         );  
         return result;  
 }  
   
 /// @todo not very optimal  
 uint String::used_rows() const {  
         uint result=0;  
         STRING_FOREACH_ROW(  
                 result++;  
         );  
         return result;  
 }  
 void String::expand() {  
         uint new_chunk_count=last_chunk->count+CR_GROW_COUNT;  
         if(new_chunk_count>max_integral(Chunk::count_type))  
                 new_chunk_count=max_integral(Chunk::count_type);  
   
         Chunk *new_chunk=static_cast<Chunk *>(malloc(  
                         sizeof(Chunk)// count+interpadding(?)+rows[CR_PREALLOCATED_COUNT]+tailpadding(??)  
                         -sizeof(Chunk::rows_type) // PREALLOCATED rows  
                         +sizeof(Chunk::Row)*new_chunk_count // neaded rows  
                         +sizeof(Chunk *) // link size  
                 , 10));  
         new_chunk->rows[new_chunk->count=new_chunk_count].link=0;  
         last_chunk->rows[last_chunk->count].link=new_chunk;  
           
         last_chunk=new_chunk;  
         append_here=last_chunk->rows;  
 }  
   
 String& String::real_append(STRING_APPEND_PARAMS) {  String& String::real_append(STRING_APPEND_PARAMS) {
         if(!last_chunk) // growth stopped [we're appended as string to somebody]  
                 throw Exception(0,  
                         this,  
                         "string growth stopped (append cstr)");  
   
         if(!src)          if(!src)
                 return *this;                  return *this;
         if(!size)          if(!size)
Line 107  String& String::real_append(STRING_APPEN Line 65  String& String::real_append(STRING_APPEN
         if(!size)          if(!size)
                 return *this;                  return *this;
   
 #ifdef DEBUG_STRING_APPENDS_VS_EXPANDS          if(is_full())
         string_piece_appends++;                  expand(fdelta);
 #endif  
   
         // manually unrolled to avoid extra check  
         while(size>max_integral(Chunk::Row::item_size_type)) {  
                 if(chunk_is_full())  
                         expand();  
   
                 append_here->item.ptr=src;  
                 append_here->item.size=max_integral(Chunk::Row::item_size_type);  
                 append_here->item.lang=lang;  
 #ifndef NO_STRING_ORIGIN  
                 append_here->item.origin.file=file;  
                 append_here->item.origin.line=line;  
 #endif  
                 append_here++;  
   
                 src+=max_integral(Chunk::Row::item_size_type);  
                 size-=max_integral(Chunk::Row::item_size_type);  
         }  
   
         if(chunk_is_full())  
                 expand();  
   
         append_here->item.ptr=src;          String_fragment *fragment=felements[fused++];
         append_here->item.size=size;          fragment->item.ptr=src;
         append_here->item.lang=lang;          fragment->item.size=size;
           fragment->item.lang=lang;
 #ifndef NO_STRING_ORIGIN  #ifndef NO_STRING_ORIGIN
         append_here->item.origin.file=file;          fragment->item.origin.file=file;
         append_here->item.origin.line=line;          fragment->item.origin.line=line;
 #endif  #endif
         append_here++;  
   
         return *this;          return *this;
 }  }
Line 332  const Origin& String::origin() const { Line 268  const Origin& String::origin() const {
 #endif  #endif
   
 String& String::mid(size_t start, size_t finish) const {  String& String::mid(size_t start, size_t finish) const {
         String& result=*NEW String(pool());          String& result=*new String();
   
         start=min(start, size());          start=min(start, size());
         finish=max(start, finish);          finish=max(start, finish);
Line 459  static void regex_options(const String * Line 395  static void regex_options(const String *
                 {"'", 0, 0, 0, 0, &need_pre_post_match},                  {"'", 0, 0, 0, 0, &need_pre_post_match},
                 {0}                  {0}
     };      };
         result[0]=PCRE_EXTRA | PCRE_DOTALL;          result[0]=PCRE_EXTRA | PCRE_DOTALL | PCRE_DOLLAR_ENDONLY;
         result[1]=0;          result[1]=0;
   
     if(options)       if(options) 
Line 476  static void regex_options(const String * Line 412  static void regex_options(const String *
 }  }
   
 /// @todo make replacement Table stacked  /// @todo make replacement Table stacked
 bool String::match(  bool String::match(Charset& source_charset,
                                    const String *aorigin,                                     const String *aorigin,
                                    const String& regexp,                                      const String& regexp, 
                                    const String *options,                                     const String *options,
Line 498  bool String::match( Line 434  bool String::match(
                 *was_global=option_bits[1]!=0;                  *was_global=option_bits[1]!=0;
         pcre *code=pcre_compile(pattern, option_bits[0],           pcre *code=pcre_compile(pattern, option_bits[0], 
                 &errptr, &erroffset,                  &errptr, &erroffset,
                 pool().get_source_charset().pcre_tables);                  source_charset.pcre_tables);
   
         if(!code)          if(!code)
                 throw Exception(0,                  throw Exception(0,
Line 520  bool String::match( Line 456  bool String::match(
         int ovector[ovecsize];          int ovector[ovecsize];
   
         // create table          // create table
         *table=NEW Table(pool(), *string_match_table_template);          *table=new Table(*string_match_table_template);
   
         int exec_option_bits=0;          int exec_option_bits=0;
         int prestart=0;          int prestart=0;
Line 547  bool String::match( Line 483  bool String::match(
   
                 int prefinish=ovector[0];                  int prefinish=ovector[0];
                 poststart=ovector[1];                  poststart=ovector[1];
                 Array& row=*NEW Array(pool());                  Array& row=*new Array();
                 row+=need_pre_post_match?&mid(0, prefinish):0; // .prematch column value                  row+=need_pre_post_match?&mid(0, prefinish):0; // .prematch column value
                 row+=need_pre_post_match?&mid(prefinish, poststart):0; // .match                  row+=need_pre_post_match?&mid(prefinish, poststart):0; // .match
                 row+=need_pre_post_match?&mid(poststart, postfinish):0; // .postmatch                  row+=need_pre_post_match?&mid(poststart, postfinish):0; // .postmatch
Line 573  bool String::match( Line 509  bool String::match(
         }          }
 }  }
   
 String& String::change_case(Pool& pool,   String& String::change_case(Charset& source_charset, Change_case_kind kind) const {
                                                         Change_case_kind kind) const {          const unsigned char *tables=source_charset.pcre_tables;
         const unsigned char *tables=pool.get_source_charset().pcre_tables;          String& result=*new String();
         String& result=*new(pool) String(pool);  
   
         const unsigned char *a;          const unsigned char *a;
         const unsigned char *b;          const unsigned char *b;
Line 599  String& String::change_case(Pool& pool, Line 534  String& String::change_case(Pool& pool,
         }                 }       
   
         STRING_FOREACH_ROW(          STRING_FOREACH_ROW(
                 char *new_cstr=(char *)pool.malloc(row->item.size, 12);                  char *new_cstr=(char *)pa_malloc(row->item.size);
                 char *dest=new_cstr;                  char *dest=new_cstr;
                 const char *src=row->item.ptr;                   const char *src=row->item.ptr; 
                 for(int size=row->item.size; size--; src++) {                  for(int size=row->item.size; size--; src++) {
Line 619  String& String::change_case(Pool& pool, Line 554  String& String::change_case(Pool& pool,
 }  }
   
 /// @test if in some piece were found no dict words, append it, not it's duplicate  /// @test if in some piece were found no dict words, append it, not it's duplicate
 String& String::replace(Pool& pool, Dictionary& dict) const {  String& String::replace(Dictionary& dict) const {
 //      return reconstruct(pool).replace_in_reconstructed(pool, dict);          char *lcstr=cstr();
         String& result=*new(pool) String(pool);          const char *current=lcstr;
   
           String& result=*new String();
         STRING_FOREACH_ROW(          STRING_FOREACH_ROW(
                 const char *src=row->item.ptr;   IFNDEF_NO_STRING_ORIGIN(
                 size_t src_size=row->item.size;                  const char *joined_origin_file=row->item.origin.file;
                 char *new_cstr=(char *)pool.malloc((size_t)ceil(src_size*dict.max_ratio()), 14);                  const size_t joined_origin_line=row->item.origin.line;
   );
                   uchar joined_lang=row->item.lang;
                   const char *joined_ptr=current;
                   // calc size
                   size_t joined_size=0;
                   STRING_PREPARED_FOREACH_ROW(*this, 
                           if(row->item.lang==joined_lang)
                                   joined_size+=row->item.size;
                           else
                                   break; // before non-ours
                   );
                   current+=joined_size;
   
                   // pointers are after joined piece
                   // & one step back, see STRING_FOREACH_ROW
                   --row;  ++countdown;
                   
                   char *new_cstr=(char *)pa_malloc((size_t)ceil(joined_size*dict.max_ratio()));
                 char *dest=new_cstr;                  char *dest=new_cstr;
                 while(src_size) {                  while(joined_size) {
                         // there is a row where first column starts 'src'                          // there is a row where first column starts 'joined_ptr'
                         if(Table::Item *item=dict.first_that_starts(src, src_size)) {                          if(Table::Item *item=dict.first_that_starts(joined_ptr, joined_size)) {
                                 // get a=>b values                                  // get a=>b values
                                 const String& a=*static_cast<Array *>(item)->get_string(0);                                  const String& a=*static_cast<Array *>(item)->get_string(0);
                                 const String& b=*static_cast<Array *>(item)->get_string(1);                                  const String& b=*static_cast<Array *>(item)->get_string(1);
                                 // skip 'a' in 'src' && reduce work size                                  // skip 'a' in 'joined_ptr' && reduce work size
                                 src+=a.size();  src_size-=a.size();                                  joined_ptr+=a.size();  joined_size-=a.size();
                                 // write 'b' to 'dest' && skip 'b' in 'dest'                                  // write 'b' to 'dest' && skip 'b' in 'dest'
                                 b.store_to(dest);  dest+=b.size();                                  b.store_to(dest);  dest+=b.size();
                         } else {                          } else {
                                 // write a char to b && reduce work size                                  // write a char to b && reduce work size
                                 *dest++=*src++;  src_size--;                                  *dest++=*joined_ptr++;  joined_size--;
                         }                          }
                 }                  }
   
                 result.APPEND(new_cstr, dest-new_cstr, row->item.lang,                  result.APPEND(new_cstr, dest-new_cstr, joined_lang,
                         row->item.origin.file, row->item.origin.line);                          joined_origin_file, joined_origin_line);
         );          );
   
         return result;          return result;
 }  }
   
 String& String::join_chains(Pool& pool, char** acstr) const {  String& String::join_chains(char** acstr) const {
         char *lcstr=cstr();          char *lcstr=cstr();
         const char *current=lcstr;          const char *current=lcstr;
   
         String& result=*new(pool) String(pool);          String& result=*new String();
         STRING_FOREACH_ROW(          STRING_FOREACH_ROW(
 IFNDEF_NO_STRING_ORIGIN(  IFNDEF_NO_STRING_ORIGIN(
                 const char *joined_origin_file=row->item.origin.file;                  const char *joined_origin_file=row->item.origin.file;
Line 771  void String::serialize(size_t prolog_siz Line 726  void String::serialize(size_t prolog_siz
                 prolog_size                  prolog_size
                 +used_rows()*(sizeof(uchar)+sizeof(ushort))                  +used_rows()*(sizeof(uchar)+sizeof(ushort))
                 +size();                  +size();
         buf=malloc(buf_size,15);          buf=pa_malloc(buf_size);
         char *cur=(char *)buf+prolog_size;          char *cur=(char *)buf+prolog_size;
   
         STRING_FOREACH_ROW(          STRING_FOREACH_ROW(

Removed from v.1.169  
changed lines
  Added in v.1.172.2.2


E-mail: