|
|
| version 1.25, 2001/02/14 15:19:02 | version 1.31, 2001/02/22 12:43:55 |
|---|---|
| Line 13 | Line 13 |
| String::String(Pool& apool) : | String::String(Pool& apool) : |
| Pooled(apool) { | Pooled(apool) { |
| head.count=curr_chunk_rows=CR_PREALLOCATED_COUNT; | last_chunk=&head; |
| head.count=CR_PREALLOCATED_COUNT; | |
| append_here=head.rows; | append_here=head.rows; |
| head.preallocated_link=0; | head.preallocated_link=0; |
| link_row=&head.rows[curr_chunk_rows]; | link_row=&head.rows[head.count]; |
| fused_rows=fsize=0; | fused_rows=fsize=0; |
| } | } |
| void String::expand() { | void String::expand() { |
| curr_chunk_rows+=curr_chunk_rows*CR_GROW_PERCENT/100; | int new_chunk_count=last_chunk->count+last_chunk->count*CR_GROW_PERCENT/100; |
| Chunk *chunk=static_cast<Chunk *>( | last_chunk=static_cast<Chunk *>( |
| pool.malloc(sizeof(int)+sizeof(Chunk::Row)*curr_chunk_rows+sizeof(Chunk *))); | malloc(sizeof(int)+sizeof(Chunk::Row)*new_chunk_count+sizeof(Chunk *))); |
| chunk->count=curr_chunk_rows; | last_chunk->count=new_chunk_count; |
| link_row->link=chunk; | link_row->link=last_chunk; |
| append_here=chunk->rows; | append_here=last_chunk->rows; |
| link_row=&chunk->rows[curr_chunk_rows]; | link_row=&last_chunk->rows[last_chunk->count]; |
| link_row->link=0; | link_row->link=0; |
| } | } |
| String::String(const String& src) : | String::String(const String& src) : |
| Pooled(src.pool) { | Pooled(src.pool()) { |
| head.count=CR_PREALLOCATED_COUNT; | head.count=CR_PREALLOCATED_COUNT; |
| int src_used_rows=src.used_rows(); | int src_used_rows=src.used_rows(); |
| if(src_used_rows<=head.count) { | if(src_used_rows<=head.count) { |
| // all new rows fit into preallocated area | // all new rows fit into preallocated area |
| curr_chunk_rows=head.count; | int curr_chunk_rows=head.count; |
| memcpy(head.rows, src.head.rows, sizeof(Chunk::Row)*src_used_rows); | memcpy(head.rows, src.head.rows, sizeof(Chunk::Row)*src_used_rows); |
| append_here=&head.rows[src_used_rows]; | append_here=&head.rows[src_used_rows]; |
| link_row=&head.rows[curr_chunk_rows]; | link_row=&head.rows[curr_chunk_rows]; |
| Line 55 String::String(const String& src) : | Line 56 String::String(const String& src) : |
| // preallocated chunk src to constructing head | // preallocated chunk src to constructing head |
| memcpy(head.rows, src.head.rows, sizeof(Chunk::Row)*head.count); | memcpy(head.rows, src.head.rows, sizeof(Chunk::Row)*head.count); |
| // remaining rows into new_chunk | // remaining rows into new_chunk |
| curr_chunk_rows=src_used_rows-head.count; | int curr_chunk_rows=src_used_rows-head.count; |
| Chunk *new_chunk=static_cast<Chunk *>( | Chunk *new_chunk=static_cast<Chunk *>( |
| pool.malloc(sizeof(int)+sizeof(Chunk::Row)*curr_chunk_rows+sizeof(Chunk *))); | malloc(sizeof(int)+sizeof(Chunk::Row)*curr_chunk_rows+sizeof(Chunk *))); |
| new_chunk->count=curr_chunk_rows; | new_chunk->count=curr_chunk_rows; |
| head.preallocated_link=new_chunk; | head.preallocated_link=new_chunk; |
| append_here=link_row=&new_chunk->rows[curr_chunk_rows]; | append_here=link_row=&new_chunk->rows[new_chunk->count]; |
| Chunk *old_chunk=src.head.preallocated_link; | Chunk *old_chunk=src.head.preallocated_link; |
| Chunk::Row *new_rows=new_chunk->rows; | Chunk::Row *new_rows=new_chunk->rows; |
| int rows_left_to_copy=curr_chunk_rows; | int rows_left_to_copy=new_chunk->count; |
| while(true) { | while(true) { |
| int old_count=old_chunk->count; | int old_count=old_chunk->count; |
| Chunk *next_chunk=old_chunk->rows[old_count].link; | Chunk *next_chunk=old_chunk->rows[old_count].link; |
| Line 88 String::String(const String& src) : | Line 89 String::String(const String& src) : |
| fused_rows=src_used_rows; | fused_rows=src_used_rows; |
| fsize=src.fsize; | fsize=src.fsize; |
| } | } |
| /* | |
| String(const String_iterator& begin, const String_iterator& end) { | String& String::operator += (const String& src) { |
| ;//TODO | int src_used_rows=src.used_rows(); |
| int dst_free_rows=link_row-append_here; | |
| if(src_used_rows<=dst_free_rows) { | |
| // all new rows fit into last chunk | |
| memcpy(append_here, src.head.rows, sizeof(Chunk::Row)*src_used_rows); | |
| append_here+=src_used_rows; | |
| } else { | |
| // not all new rows fit into last chunk: shrinking it to used part, | |
| int used_rows=last_chunk->count-dst_free_rows; | |
| //int *countp=append_here | |
| link_row=&last_chunk->rows[last_chunk->count=used_rows]; | |
| // allocating only enough mem to fit src string rows | |
| // next append would allocate a new chunk | |
| last_chunk=static_cast<Chunk *>( | |
| malloc(sizeof(int)+sizeof(Chunk::Row)*src_used_rows+sizeof(Chunk *))); | |
| last_chunk->count=src_used_rows; | |
| link_row->link=last_chunk; | |
| append_here=link_row=&last_chunk->rows[src_used_rows]; | |
| const Chunk *old_chunk=&src.head; | |
| Chunk::Row *new_rows=last_chunk->rows; | |
| int rows_left_to_copy=src_used_rows; | |
| while(true) { | |
| int old_count=old_chunk->count; | |
| Chunk *next_chunk=old_chunk->rows[old_count].link; | |
| if(next_chunk) { | |
| // not last source chunk | |
| // taking it all | |
| memcpy(new_rows, old_chunk->rows, sizeof(Chunk::Row)*old_count); | |
| new_rows+=old_count; | |
| rows_left_to_copy-=old_count; | |
| old_chunk=next_chunk; | |
| } else { | |
| // the last source chunk | |
| // taking only those rows of chunk that _left_to_copy | |
| memcpy(new_rows, old_chunk->rows, sizeof(Chunk::Row)*rows_left_to_copy); | |
| break; | |
| } | |
| } | |
| link_row->link=0; | |
| } | |
| fused_rows+=src_used_rows; | |
| fsize+=src.fsize; | |
| return *this; | |
| } | } |
| */ | |
| String& String::real_append(STRING_APPEND_PARAMS) { | String& String::real_append(STRING_APPEND_PARAMS) { |
| if(!src) | if(!src) |
| return *this; | return *this; |
| int len=strlen(src); | if(!size) |
| if(!len) | size=strlen(src); |
| if(!size) | |
| return *this; | return *this; |
| if(chunk_is_full()) | if(chunk_is_full()) |
| expand(); | expand(); |
| append_here->item.ptr=src; | append_here->item.ptr=src; |
| fsize+=append_here->item.size=len; | fsize+=append_here->item.size=size; |
| #ifndef NO_STRING_ORIGIN | #ifndef NO_STRING_ORIGIN |
| append_here->item.origin.file=file; | append_here->item.origin.file=file; |
| append_here->item.origin.line=line; | append_here->item.origin.line=line; |
| Line 116 String& String::real_append(STRING_APPEN | Line 163 String& String::real_append(STRING_APPEN |
| } | } |
| char *String::cstr() const { | char *String::cstr() const { |
| char *result=static_cast<char *>(pool.malloc(size()+1)); | char *result=static_cast<char *>(malloc(size()+1)); |
| char *copy_here=result; | char *copy_here=result; |
| const Chunk *chunk=&head; | const Chunk *chunk=&head; |
| Line 213 bool String::operator == (const String& | Line 260 bool String::operator == (const String& |
| return a_break==b_break; | return a_break==b_break; |
| } | } |
| String& String::append(const String_iterator& begin, const String_iterator& end) { | bool String::operator == (char* b_ptr) const { |
| //TODO | size_t b_size=b_ptr?strlen(b_ptr):0; |
| return *this; | if(size() != b_size) |
| } | |
| // Char_types | |
| Char_types::Char_types() { | |
| memset(types, 0, sizeof(types)); | |
| } | |
| void Char_types::set(char from, char to, int type) { | |
| memset(&types[static_cast<unsigned int>(from)], type, to-from+1); | |
| } | |
| // String_iterator | |
| String_iterator::String_iterator(String& astring) : string(astring) { | |
| read_here=string.head.rows; | |
| position=string.size()==0?0:read_here->item.ptr; | |
| link_row=reinterpret_cast<String::Chunk::Row*>(string.head.preallocated_link); | |
| } | |
| String_iterator::String_iterator(String_iterator& asi) { | |
| //TODO | |
| } | |
| char String_iterator::operator()() const { | |
| return position?*position:0; | |
| } | |
| void String_iterator::skip() { | |
| if(!position) | |
| return; | |
| if(++position== | |
| read_here->item.ptr+ | |
| read_here->item.size) { | |
| // next row | |
| if(++read_here==string.append_here) { | |
| position=0; | |
| return; | |
| } | |
| if(read_here==link_row) { | |
| String::Chunk *chunk=link_row->link; | |
| if(!chunk) | |
| string.pool.exception().raise(0, 0, | |
| &string, | |
| "String_iterator::skip() missed " | |
| "read_here==string.append_here check"); | |
| read_here=chunk->rows; | |
| link_row=&chunk->rows[chunk->count]; | |
| } | |
| position=read_here->item.ptr; | |
| } | |
| } | |
| bool String_iterator::skip_to(char c) { | |
| if(!position) | |
| return false; | return false; |
| const Chunk *a_chunk=&head; | |
| const Chunk::Row *a_row=a_chunk->rows; | |
| int a_offset=0; | |
| int b_offset=0; | |
| Chunk::Row *a_end=append_here; | |
| int a_countdown=a_chunk->count; | |
| bool a_break=false; | |
| bool b_break=false; | |
| while(true) { | while(true) { |
| if(char *found=static_cast<char *>( | int size_diff= |
| memchr(position, c, read_here->item.size-(position-read_here->item.ptr)))) { | (a_row->item.size-a_offset)- |
| position=found; | (b_size-b_offset); |
| return true; | |
| } | |
| // next row | |
| if(++read_here==string.append_here) { | |
| position=0; | |
| return false; | |
| } | |
| if(read_here==link_row) { | |
| String::Chunk *chunk=link_row->link; | |
| if(!chunk) | |
| string.pool.exception().raise(0, 0, | |
| &string, | |
| "String_iterator::skip_to(char) missed " | |
| "read_here==string.append_here check"); | |
| read_here=chunk->rows; | if(size_diff==0) { // a has same size as b |
| link_row=&chunk->rows[chunk->count]; | if(memcmp(a_row->item.ptr+a_offset, b_ptr+b_offset, a_row->item.size-a_offset)!=0) |
| return false; | |
| a_row++; a_countdown--; a_offset=0; | |
| b_break=true; | |
| } else if (size_diff>0) { // a longer | |
| if(memcmp(a_row->item.ptr+a_offset, b_ptr+b_offset, b_size-b_offset)!=0) | |
| return false; | |
| a_offset+=b_size-b_offset; | |
| b_break=true; | |
| } else { // b longer | |
| if(memcmp(a_row->item.ptr+a_offset, b_ptr+b_offset, a_row->item.size-a_offset)!=0) | |
| return false; | |
| b_offset+=a_row->item.size-a_offset; | |
| a_row++; a_countdown--; a_offset=0; | |
| } | } |
| position=read_here->item.ptr; | |
| } | |
| } | |
| int String_iterator::skip_to(Char_types& types) { | |
| if(!position) | |
| return false; | |
| while(true) { | a_break=a_row==a_end; |
| int countdown=read_here->item.size-(position-read_here->item.ptr); | if(a_break || b_break) |
| for(; countdown--; position++) | break; |
| if(int type=types.get(*position)) | |
| return type; | |
| // next row | |
| if(++read_here==string.append_here) { | |
| position=0; | |
| return -1; | |
| } | |
| if(read_here==link_row) { | |
| String::Chunk *chunk=link_row->link; | |
| if(!chunk) | |
| string.pool.exception().raise(0, 0, | |
| &string, | |
| "String_iterator::skip_to(Char_type) missed " | |
| "read_here==string.append_here check"); | |
| read_here=chunk->rows; | if(!a_countdown) { |
| link_row=&chunk->rows[chunk->count]; | a_chunk=a_row->link; |
| a_row=a_chunk->rows; | |
| a_countdown=a_chunk->count; | |
| } | } |
| position=read_here->item.ptr; | |
| } | } |
| return a_break==b_break; | |
| } | } |