Diff for /parser3/src/main/pa_string.C between versions 1.121 and 1.129

version 1.121, 2001/11/16 13:58:28 version 1.129, 2001/12/10 09:44:17
Line 27  String::String(Pool& apool, const char * Line 27  String::String(Pool& apool, const char *
         last_chunk=&head;          last_chunk=&head;
         head.count=CR_PREALLOCATED_COUNT;          head.count=CR_PREALLOCATED_COUNT;
         append_here=head.rows;          append_here=head.rows;
         head.preallocated_link=0;          head_link=0;
         link_row=&head.rows[head.count];          link_row=&head.rows[head.count];
   
         if(src)          if(src)
Line 66  String::String(const String& src) : Line 66  String::String(const String& src) :
                 last_chunk=static_cast<Chunk *>(                  last_chunk=static_cast<Chunk *>(
                         malloc(sizeof(uint)+sizeof(Chunk::Row)*curr_chunk_rows+sizeof(Chunk *), 9));                          malloc(sizeof(uint)+sizeof(Chunk::Row)*curr_chunk_rows+sizeof(Chunk *), 9));
                 last_chunk->count=curr_chunk_rows;                  last_chunk->count=curr_chunk_rows;
                 head.preallocated_link=last_chunk;                  head_link=last_chunk;
                 append_here=link_row=&last_chunk->rows[last_chunk->count];                  append_here=link_row=&last_chunk->rows[last_chunk->count];
   
                 Chunk *old_chunk=src.head.preallocated_link;                   Chunk *old_chunk=src.head_link; 
                 Chunk::Row *new_rows=last_chunk->rows;                  Chunk::Row *new_rows=last_chunk->rows;
                 uint rows_left_to_copy=last_chunk->count;                  uint rows_left_to_copy=last_chunk->count;
                 while(true) {                  while(true) {
Line 97  String::String(const String& src) : Line 97  String::String(const String& src) :
   
 size_t  String::size() const {  size_t  String::size() const {
         size_t result=0;          size_t result=0;
         const Chunk *chunk=&head;           STRING_FOREACH_ROW(
         do {  
                 const Chunk::Row *row=chunk->rows;  
                 for(uint i=0; i<chunk->count; i++, row++) {  
                         if(row==append_here)  
                                 goto break2;  
   
                         result+=row->item.size;                          result+=row->item.size;
                 }          );
                 chunk=row->link;  
         } while(chunk);  
   
 break2:  break2:
         return result;          return result;
 }  }
Line 116  break2: Line 107  break2:
 /// @todo not very optimal  /// @todo not very optimal
 uint String::used_rows() const {  uint String::used_rows() const {
         uint result=0;          uint result=0;
         const Chunk *chunk=&head;           STRING_FOREACH_ROW(
         do {                  result++;
                 const Chunk::Row *row=chunk->rows;          );
                 for(uint i=0; i<chunk->count; i++, row++) {  
                         if(row==append_here)  
                                 goto break2;  
   
                         result++;  
                 }  
                 chunk=row->link;  
         } while(chunk);  
   
 break2:  break2:
         return result;          return result;
 }  }
 void String::expand() {  void String::expand() {
         uint new_chunk_count=last_chunk->count+CR_GROW_COUNT;          uint new_chunk_count=last_chunk->count+CR_GROW_COUNT;
           if(new_chunk_count>MAX_USHORT)
                   new_chunk_count=MAX_USHORT;
   
         last_chunk=static_cast<Chunk *>(          last_chunk=static_cast<Chunk *>(
                 malloc(sizeof(uint)+sizeof(Chunk::Row)*new_chunk_count+sizeof(Chunk *), 10));                  malloc(sizeof(uint)+sizeof(Chunk::Row)*new_chunk_count+sizeof(Chunk *), 10));
         last_chunk->count=new_chunk_count;          last_chunk->count=new_chunk_count;
Line 142  void String::expand() { Line 127  void String::expand() {
         link_row->link=0;          link_row->link=0;
 }  }
   
 String& String::append(const String& src, Untaint_lang lang, bool forced) {  
         const Chunk *chunk=&src.head;   
         do {  
                 const Chunk::Row *row=chunk->rows;  
                 for(uint i=0; i<chunk->count; i++, row++) {  
                         if(row==src.append_here)  
                                 goto break2;  
                           
                         APPEND(row->item.ptr, row->item.size,   
                                 (lang!=UL_PASS_APPENDED && (row->item.lang==UL_TAINTED || forced))?lang:(Untaint_lang)row->item.lang,  
                                 row->item.origin.file, row->item.origin.line);  
                 }  
                 chunk=row->link;  
         } while(chunk);  
 break2:  
         return *this;  
 }  
   
 String& String::real_append(STRING_APPEND_PARAMS) {  String& String::real_append(STRING_APPEND_PARAMS) {
         if(!src)          if(!src)
                 return *this;                  return *this;
Line 168  String& String::real_append(STRING_APPEN Line 135  String& String::real_append(STRING_APPEN
         if(!size)          if(!size)
                 return *this;                  return *this;
   
           while(size>MAX_USHORT) {
                   if(chunk_is_full())
                           expand();
   
                   append_here->item.ptr=src;
                   append_here->item.size=MAX_USHORT;
                   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_USHORT;
                   size-=MAX_USHORT;
           }
   
         if(chunk_is_full())          if(chunk_is_full())
                 expand();                  expand();
   
Line 194  char String::first_char() const { Line 178  char String::first_char() const {
   
 uint String::hash_code() const {  uint String::hash_code() const {
         uint result=0;          uint result=0;
           STRING_FOREACH_ROW(
         const Chunk *chunk=&head;   
         do {  
                 const Chunk::Row *row=chunk->rows;  
                 for(uint i=0; i<chunk->count; i++) {  
                         if(row==append_here)  
                                 goto break2;  
   
                         result=Hash::generic_code(result, row->item.ptr, row->item.size);                          result=Hash::generic_code(result, row->item.ptr, row->item.size);
                         row++;          );
                 }  
                 chunk=row->link;  
         } while(chunk);  
 break2:  break2:
         return result;          return result;
 }  }
Line 215  break2: Line 189  break2:
 int String::cmp(int& partial, const String& src,   int String::cmp(int& partial, const String& src, 
                                 size_t this_offset, Untaint_lang lang) const {                                  size_t this_offset, Untaint_lang lang) const {
         partial=-1;          partial=-1;
         this_offset=min(this_offset, size()-1);          size_t a_size=size();
           this_offset=min(this_offset, a_size-1);
   
         const Chunk *a_chunk=&head;          const Chunk *a_chunk=&head;
         const Chunk *b_chunk=&src.head;          const Chunk *b_chunk=&src.head;
Line 230  int String::cmp(int& partial, const Stri Line 205  int String::cmp(int& partial, const Stri
         int result;          int result;
         size_t pos=0;           size_t pos=0; 
   
         bool a_break=size()==0;          bool a_break=a_size==0;
         bool b_break=src.size()==0;          bool b_break=src.size()==0;
         if(!(a_break || b_break)) while(true) {          if(!(a_break || b_break)) while(true) {
                 if(pos+a_row->item.size > this_offset) {                  if(pos+a_row->item.size > this_offset) {
Line 303  int String::cmp(int& partial, const Stri Line 278  int String::cmp(int& partial, const Stri
 int String::cmp(int& partial, const char* b_ptr, size_t src_size,   int String::cmp(int& partial, const char* b_ptr, size_t src_size, 
                                 size_t this_offset, Untaint_lang lang) const {                                  size_t this_offset, Untaint_lang lang) const {
         partial=-1;          partial=-1;
           size_t a_size=size();
         size_t b_size=src_size?src_size:b_ptr?strlen(b_ptr):0;          size_t b_size=src_size?src_size:b_ptr?strlen(b_ptr):0;
         this_offset=min(this_offset, size()-1);          this_offset=min(this_offset, a_size-1);
   
         const Chunk *a_chunk=&head;          const Chunk *a_chunk=&head;
         const Chunk::Row *a_row=a_chunk->rows;          const Chunk::Row *a_row=a_chunk->rows;
Line 314  int String::cmp(int& partial, const char Line 290  int String::cmp(int& partial, const char
         uint a_countdown=a_chunk->count;          uint a_countdown=a_chunk->count;
         size_t pos=0;          size_t pos=0;
   
         bool a_break=size()==0;          bool a_break=a_size==0;
         bool b_break=b_size==0;          bool b_break=b_size==0;
         if(!(a_break || b_break)) while(true) {          if(!(a_break || b_break)) while(true) {
                 if(pos+a_row->item.size > this_offset) {                  if(pos+a_row->item.size > this_offset) {
Line 397  String& String::mid(size_t start, size_t Line 373  String& String::mid(size_t start, size_t
                 return result;                  return result;
   
         size_t pos=0;          size_t pos=0;
         const Chunk *chunk=&head;           STRING_FOREACH_ROW(
         do {                  size_t item_finish=pos+row->item.size;
                 const Chunk::Row *row=chunk->rows;                  if(item_finish > start) { // started now or already?
                 for(uint i=0; i<chunk->count; pos+=row->item.size, i++, row++) {                          bool started=result.size()==0; // started now?
                         if(row==append_here)                          bool finished=finish <= item_finish; // finished now?
                           size_t offset=started?start-pos:0;
                           size_t size=finished?finish-pos:row->item.size;
                           result.APPEND(
                                   row->item.ptr+offset, size-offset, 
                                   row->item.lang,
                                   row->item.origin.file, row->item.origin.line);
                           if(finished)
                                 goto break2;                                  goto break2;
   
                         size_t item_finish=pos+row->item.size;  
                         if(item_finish > start) { // started now or already?  
                                 bool started=result.size()==0; // started now?  
                                 bool finished=finish <= item_finish; // finished now?  
                                 size_t offset=started?start-pos:0;  
                                 size_t size=finished?finish-pos:row->item.size;  
                                 result.APPEND(  
                                         row->item.ptr+offset, size-offset,   
                                         (Untaint_lang)row->item.lang,  
                                         row->item.origin.file, row->item.origin.line);  
                                 if(finished)  
                                         goto break2;  
                         }  
                 }                  }
                 chunk=row->link;                  pos+=row->item.size;
         } while(chunk);          );
 break2:  break2:
 //      SAPI::log(pool(), "piece of '%s' from %d to %d is '%s'",  //      SAPI::log(pool(), "piece of '%s' from %d to %d is '%s'",
                 //cstr(), start, finish, result.cstr());                  //cstr(), start, finish, result.cstr());
Line 428  break2: Line 397  break2:
   
 int String::pos(const String& substr,   int String::pos(const String& substr, 
                                 int result, Untaint_lang lang) const {                                  int result, Untaint_lang lang) const {
         for(; result<size(); result++) {          size_t self_size=size();
           for(; result<self_size; result++) {
                 int partial; cmp(partial, substr, result, lang);                  int partial; cmp(partial, substr, result, lang);
                 if(                  if(
                         partial==0 || // full match                          partial==0 || // full match
Line 441  int String::pos(const String& substr, Line 411  int String::pos(const String& substr,
   
 int String::pos(const char *substr, size_t substr_size,   int String::pos(const char *substr, size_t substr_size, 
                                 int result, Untaint_lang lang) const {                                  int result, Untaint_lang lang) const {
         for(; result<size(); result++) {          size_t self_size=size();
           for(; result<self_size; result++) {
                 int partial; cmp(partial, substr, substr_size, result, lang);                  int partial; cmp(partial, substr, substr_size, result, lang);
                 if(                  if(
                         partial==0 || // full match                          partial==0 || // full match
Line 456  void String::split(Array& result, Line 427  void String::split(Array& result,
                                    size_t* pos_after_ref,                                      size_t* pos_after_ref, 
                                    const char *delim, size_t delim_size,                                      const char *delim, size_t delim_size, 
                                    Untaint_lang lang, int limit) const {                                     Untaint_lang lang, int limit) const {
           size_t self_size=size();
         if(delim_size) {          if(delim_size) {
                 size_t pos_after=pos_after_ref?*pos_after_ref:0;                  size_t pos_after=pos_after_ref?*pos_after_ref:0;
                 int pos_before;                  int pos_before;
Line 465  void String::split(Array& result, Line 437  void String::split(Array& result,
                         pos_after=pos_before+delim_size;                          pos_after=pos_before+delim_size;
                 }                  }
                 // last piece                  // last piece
                 if(pos_after<size() && limit) {                  if(pos_after<self_size && limit) {
                         result+=&mid(pos_after, size());                          result+=&mid(pos_after, self_size);
                         pos_after=size();                          pos_after=self_size;
                 }                  }
                 if(pos_after_ref)                  if(pos_after_ref)
                         *pos_after_ref=pos_after;                          *pos_after_ref=pos_after;
         } else { // empty delim          } else { // empty delim
                 result+=this;                  result+=this;
                 if(pos_after_ref)                  if(pos_after_ref)
                         *pos_after_ref+=size();                          *pos_after_ref+=self_size;
         }          }
 }  }
   
Line 676  String& String::change_case(Pool& pool, Line 648  String& String::change_case(Pool& pool,
                         }                          }
                                                   
                         result.APPEND(new_cstr, row->item.size,                           result.APPEND(new_cstr, row->item.size, 
                                 (Untaint_lang)row->item.lang,                                  row->item.lang,
                                 row->item.origin.file, row->item.origin.line);                                  row->item.origin.file, row->item.origin.line);
                 }                  }
                 chunk=row->link;                  chunk=row->link;
Line 688  break2: Line 660  break2:
   
 void String::join_chain(Pool& pool,   void String::join_chain(Pool& pool, 
                                            uint& ai, const Chunk*& achunk, const Chunk::Row*& arow,                                             uint& ai, const Chunk*& achunk, const Chunk::Row*& arow,
                                            Untaint_lang& joined_lang, const char *& joined_ptr, size_t& joined_size) const {                                             uchar& joined_lang, const char *& joined_ptr, size_t& joined_size) const {
         joined_lang=(Untaint_lang)arow->item.lang;          joined_lang=arow->item.lang;
                   
         // calc size          // calc size
         joined_size=0;          joined_size=0;
Line 706  void String::join_chain(Pool& pool, Line 678  void String::join_chain(Pool& pool,
                                 if(row->item.lang==joined_lang)                                  if(row->item.lang==joined_lang)
                                         joined_size+=row->item.size;                                          joined_size+=row->item.size;
                                 else                                  else
                                         break;                                          goto break21;
                         }                          }
                         if(chunk=row->link) {                          if(chunk=row->link) {
                                 start_i=0;                                  start_i=0;
Line 742  break21:; Line 714  break21:;
                                         memcpy(ptr, row->item.ptr, row->item.size);                                          memcpy(ptr, row->item.ptr, row->item.size);
                                         ptr+=row->item.size;                                          ptr+=row->item.size;
                                 } else                                  } else
                                         break;                                          goto break22;
                         }                          }
                         if(chunk=row->link) {                          if(chunk=row->link) {
                                 start_i=0;                                  start_i=0;
Line 769  String& String::reconstruct(Pool& pool) Line 741  String& String::reconstruct(Pool& pool)
                         if(row==append_here)                          if(row==append_here)
                                 goto break2;                                  goto break2;
   
                         Untaint_lang joined_lang;                          uchar joined_lang;
                         const char *joined_ptr;                          const char *joined_ptr;
                         size_t joined_size;                          size_t joined_size;
                         join_chain(pool, i, chunk, row,                          join_chain(pool, i, chunk, row,
Line 790  break2: Line 762  break2:
 String& String::replace_in_reconstructed(Pool& pool, Dictionary& dict) const {  String& String::replace_in_reconstructed(Pool& pool, Dictionary& dict) const {
         //_asm int 3;          //_asm int 3;
         String& result=*new(pool) String(pool);          String& result=*new(pool) String(pool);
         const Chunk *chunk=&head;           STRING_FOREACH_ROW(
         do {                  const char *src=row->item.ptr; 
                 const Chunk::Row *row=chunk->rows;                  size_t src_size=row->item.size;
                 for(uint i=0; i<chunk->count; i++, row++) {                  char *new_cstr=(char *)pool.malloc((size_t)ceil(src_size*dict.max_ratio()), 14);
                         if(row==append_here)                  char *dest=new_cstr;
                                 goto break2;                  while(src_size) {
                           // there is a row where first column starts 'src'
                         const char *src=row->item.ptr;                           if(Table::Item *item=dict.first_that_starts(src, src_size)) {
                         size_t src_size=row->item.size;                                  // get a=>b values
                         char *new_cstr=(char *)pool.malloc((size_t)ceil(src_size*dict.max_ratio()), 14);                                  const String& a=*static_cast<Array *>(item)->get_string(0);
                         char *dest=new_cstr;                                  const String& b=*static_cast<Array *>(item)->get_string(1);
                         while(src_size) {                                  // skip 'a' in 'src' && reduce work size
                                 // there is a row where first column starts 'src'                                  src+=a.size();  src_size-=a.size();
                                 if(Table::Item *item=dict.first_that_starts(src, src_size)) {                                  // write 'b' to 'dest' && skip 'b' in 'dest'
                                         // get a=>b values                                  b.store_to(dest);  dest+=b.size();
                                         const String& a=*static_cast<Array *>(item)->get_string(0);                          } else {
                                         const String& b=*static_cast<Array *>(item)->get_string(1);                                  // write a char to b && reduce work size
                                         // skip 'a' in 'src' && reduce work size                                  *dest++=*src++;  src_size--;
                                         src+=a.size();  src_size-=a.size();  
                                         // write 'b' to 'dest' && skip 'b' in 'dest'  
                                         b.store_to(dest);  dest+=b.size();  
                                 } else {  
                                         // write a char to b && reduce work size  
                                         *dest++=*src++;  src_size--;  
                                 }  
                         }                          }
   
                         result.APPEND(new_cstr, dest-new_cstr,   
                                 (Untaint_lang)row->item.lang,  
                                 row->item.origin.file, row->item.origin.line);  
                 }                  }
                 chunk=row->link;  
         } while(chunk);  
   
                   result.APPEND(new_cstr, dest-new_cstr, 
                           row->item.lang,
                           row->item.origin.file, row->item.origin.line);
           );
 break2:  break2:
         return result;          return result;
 }  }
Line 889  int String::as_int() const { Line 852  int String::as_int() const {
         return result;          return result;
 }  }
   
   inline void ushort2uchars(ushort word, uchar& byte1, uchar& byte2) {
           byte1=word&0xFF;
           byte2=word>>8;
   }
   inline ushort uchars2ushort(uchar byte1, uchar byte2) {
           return (byte2<<8) | byte1;
   }
 /* @todo maybe network order worth spending some effort?  /* @todo maybe network order worth spending some effort?
         don't bothering myself with network byte order,          don't bothering myself with network byte order,
         am not planning to be able to move resulting file across platforms          am not planning to be able to move resulting file across platforms
Line 897  int String::as_int() const { Line 867  int String::as_int() const {
 void String::serialize(size_t prolog_size, void *& buf, size_t& buf_size) const {  void String::serialize(size_t prolog_size, void *& buf, size_t& buf_size) const {
         buf_size=          buf_size=
                 prolog_size                  prolog_size
                 +used_rows()*(sizeof(Untaint_lang)+sizeof(size_t))                  +used_rows()*(sizeof(uchar)+sizeof(ushort))
                 +size();                  +size();
         buf=malloc(buf_size,15);          buf=malloc(buf_size,15);
         char *cur=(char *)buf+prolog_size;          char *cur=(char *)buf+prolog_size;
   
         const Chunk *chunk=&head;           STRING_FOREACH_ROW(
         do {                  // lang
                 const Chunk::Row *row=chunk->rows;                  memcpy(cur, &row->item.lang, sizeof(uchar));
                 for(uint i=0; i<chunk->count; i++) {                  cur+=sizeof(uchar);
                         if(row==append_here)                  // size
                                 goto break2;                  uchar byte1; uchar byte2;
                   ushort2uchars(row->item.size, byte1, byte2);
                         // lang                  memcpy(cur, &byte1, sizeof(uchar)); cur+=sizeof(uchar);
                         memcpy(cur, &row->item.lang, sizeof(Untaint_lang));                  memcpy(cur, &byte2, sizeof(uchar)); cur+=sizeof(uchar);
                         cur+=sizeof(Untaint_lang);                  // bytes
                         // size                  memcpy(cur, row->item.ptr, row->item.size);
                         memcpy(cur, &row->item.size, sizeof(size_t));                  cur+=row->item.size;
                         cur+=sizeof(size_t);          );
                         // bytes  
                         memcpy(cur, row->item.ptr, row->item.size);  
                         cur+=row->item.size;  
   
                         row++;  
                 }  
                 chunk=row->link;  
         } while(chunk);  
 break2:  break2:
         ;          ;
 }  }
   
 /* @todo maybe network order worth spending some effort?  
         don't bothering myself with network byte order,  
         am not planning to be able to move resulting file across platforms  
         for now  
 */  
 #ifndef DOXYGEN  
 struct Serialized_piece {  
         String::Untaint_lang lang;  
         size_t size;  
         char ptr[1];  
 };  
 #endif  
   
 void String::deserialize(size_t prolog_size, void *buf, size_t buf_size, const char *file) {  void String::deserialize(size_t prolog_size, void *buf, size_t buf_size, const char *file) {
         char *cur=((char *)buf)+prolog_size;          char *cur=(char *)buf+prolog_size;
         buf_size-=prolog_size;          buf_size-=prolog_size;
   
         while(buf_size) {          while(buf_size) {
                 Serialized_piece& p=*(Serialized_piece *)cur;                  uchar lang=*(uchar *)(cur);
                 APPEND(p.ptr, p.size, p.lang, file, 0);                  
                   ushort size=uchars2ushort(
                           *(uchar*)(cur+sizeof(uchar)*1),
                           *(uchar*)(cur+sizeof(uchar)*2)
                   );
   
                   const char *ptr=(const char*)(cur+sizeof(uchar)*3); 
                   APPEND(ptr, size, lang, file, 0);
   
                 size_t piece_size=sizeof(p.lang)+sizeof(p.size)+p.size;                  size_t piece_size=sizeof(uchar)+sizeof(ushort)+size;
                 cur+=piece_size;                  cur+=piece_size;
                 buf_size-=piece_size;                  buf_size-=piece_size;
         }          }
 }  }
   

Removed from v.1.121  
changed lines
  Added in v.1.129


E-mail: