--- parser3/src/main/pa_string.C 2002/08/01 11:26:51 1.164 +++ parser3/src/main/pa_string.C 2003/01/23 15:38:06 1.172.2.2 @@ -1,49 +1,51 @@ /** @file 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 (http://paf.design.ru) */ -static const char* IDENT_STRING_C="$Id: pa_string.C,v 1.164 2002/08/01 11:26:51 paf Exp $"; +static const char* IDENT_STRING_C="$Date: 2003/01/23 15:38:06 $"; #include "pcre.h" #include "pa_pool.h" #include "pa_string.h" -#include "pa_hash.h" +//#include "pa_hash.h" #include "pa_exception.h" -#include "pa_common.h" +//#include "pa_common.h" #include "pa_array.h" -#include "pa_globals.h" +//#include "pa_globals.h" #include "pa_table.h" #include "pa_dictionary.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 -ulong string_piece_appends=0; -#endif +class String_match_table_template_columns: public Array> { + char cn_cstr[MAX_STRING_MATCH_TABLE_COLUMNS][3/*strlen("100")*/+1/*terminating 0*/]; + String cn[MAX_STRING_MATCH_TABLE_COLUMNS]; +public: + string_match_table_template_columns_class() { + *this+=smart_ptr(new String("prematch")); + *this+=smart_ptr(new String("match")); + *this+=smart_ptr(new String("postmatch")); + for(int i=0; iitem.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(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(const String& src): Array(src.count()) { + append(src, UL_PASS_APPENDED); } 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) return *this; if(!size) @@ -107,52 +65,21 @@ String& String::real_append(STRING_APPEN if(!size) return *this; -#ifdef DEBUG_STRING_APPENDS_VS_EXPANDS - string_piece_appends++; -#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(); + if(is_full()) + expand(fdelta); - append_here->item.ptr=src; - append_here->item.size=size; - append_here->item.lang=lang; + String_fragment *fragment=felements[fused++]; + fragment->item.ptr=src; + fragment->item.size=size; + fragment->item.lang=lang; #ifndef NO_STRING_ORIGIN - append_here->item.origin.file=file; - append_here->item.origin.line=line; + fragment->item.origin.file=file; + fragment->item.origin.line=line; #endif - append_here++; return *this; } -char String::first_char() const { - if(is_empty()) - throw Exception(0, - this, - "getting first char of empty string"); - - return *head.chunk.rows[0].item.ptr; -} - uint String::hash_code() const { uint result=0; STRING_FOREACH_ROW( @@ -341,10 +268,10 @@ const Origin& String::origin() const { #endif String& String::mid(size_t start, size_t finish) const { - String& result=*NEW String(pool()); + String& result=*new String(); - start=max(size_t(0), start); - finish=min(size(), finish); + start=min(start, size()); + finish=max(start, finish); if(start==finish) return result; @@ -468,7 +395,7 @@ static void regex_options(const String * {"'", 0, 0, 0, 0, &need_pre_post_match}, {0} }; - result[0]=PCRE_EXTRA | PCRE_DOTALL; + result[0]=PCRE_EXTRA | PCRE_DOTALL | PCRE_DOLLAR_ENDONLY; result[1]=0; if(options) @@ -485,7 +412,7 @@ static void regex_options(const String * } /// @todo make replacement Table stacked -bool String::match( +bool String::match(Charset& source_charset, const String *aorigin, const String& regexp, const String *options, @@ -507,7 +434,7 @@ bool String::match( *was_global=option_bits[1]!=0; pcre *code=pcre_compile(pattern, option_bits[0], &errptr, &erroffset, - pool().get_source_charset().pcre_tables); + source_charset.pcre_tables); if(!code) throw Exception(0, @@ -529,7 +456,7 @@ bool String::match( int ovector[ovecsize]; // create table - *table=NEW Table(pool(), *string_match_table_template); + *table=new Table(*string_match_table_template); int exec_option_bits=0; int prestart=0; @@ -556,7 +483,7 @@ bool String::match( int prefinish=ovector[0]; 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(prefinish, poststart):0; // .match row+=need_pre_post_match?&mid(poststart, postfinish):0; // .postmatch @@ -582,10 +509,9 @@ bool String::match( } } -String& String::change_case(Pool& pool, - Change_case_kind kind) const { - const unsigned char *tables=pool.get_source_charset().pcre_tables; - String& result=*new(pool) String(pool); +String& String::change_case(Charset& source_charset, Change_case_kind kind) const { + const unsigned char *tables=source_charset.pcre_tables; + String& result=*new String(); const unsigned char *a; const unsigned char *b; @@ -608,7 +534,7 @@ String& String::change_case(Pool& pool, } 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; const char *src=row->item.ptr; for(int size=row->item.size; size--; src++) { @@ -628,42 +554,62 @@ String& String::change_case(Pool& pool, } /// @test if in some piece were found no dict words, append it, not it's duplicate -String& String::replace(Pool& pool, Dictionary& dict) const { -// return reconstruct(pool).replace_in_reconstructed(pool, dict); - String& result=*new(pool) String(pool); +String& String::replace(Dictionary& dict) const { + char *lcstr=cstr(); + const char *current=lcstr; + String& result=*new String(); STRING_FOREACH_ROW( - const char *src=row->item.ptr; - size_t src_size=row->item.size; - char *new_cstr=(char *)pool.malloc((size_t)ceil(src_size*dict.max_ratio()), 14); +IFNDEF_NO_STRING_ORIGIN( + const char *joined_origin_file=row->item.origin.file; + 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; - while(src_size) { - // there is a row where first column starts 'src' - if(Table::Item *item=dict.first_that_starts(src, src_size)) { + while(joined_size) { + // there is a row where first column starts 'joined_ptr' + if(Table::Item *item=dict.first_that_starts(joined_ptr, joined_size)) { // get a=>b values const String& a=*static_cast(item)->get_string(0); const String& b=*static_cast(item)->get_string(1); - // skip 'a' in 'src' && reduce work size - src+=a.size(); src_size-=a.size(); + // skip 'a' in 'joined_ptr' && reduce work size + joined_ptr+=a.size(); joined_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--; + *dest++=*joined_ptr++; joined_size--; } } - result.APPEND(new_cstr, dest-new_cstr, row->item.lang, - row->item.origin.file, row->item.origin.line); + result.APPEND(new_cstr, dest-new_cstr, joined_lang, + joined_origin_file, joined_origin_line); ); + return result; } -String& String::join_chains(Pool& pool, char** acstr) const { +String& String::join_chains(char** acstr) const { char *lcstr=cstr(); const char *current=lcstr; - String& result=*new(pool) String(pool); + String& result=*new String(); STRING_FOREACH_ROW( IFNDEF_NO_STRING_ORIGIN( const char *joined_origin_file=row->item.origin.file; @@ -780,7 +726,7 @@ void String::serialize(size_t prolog_siz prolog_size +used_rows()*(sizeof(uchar)+sizeof(ushort)) +size(); - buf=malloc(buf_size,15); + buf=pa_malloc(buf_size); char *cur=(char *)buf+prolog_size; STRING_FOREACH_ROW(