--- parser3/src/main/pa_string.C 2009/04/10 11:33:16 1.219 +++ parser3/src/main/pa_string.C 2009/04/22 04:38:17 1.222 @@ -5,15 +5,14 @@ Author: Alexandr Petrosian (http://paf.design.ru) */ -static const char * const IDENT_STRING_C="$Date: 2009/04/10 11:33:16 $"; +static const char * const IDENT_STRING_C="$Date: 2009/04/22 04:38:17 $"; #include "pa_string.h" #include "pa_exception.h" #include "pa_table.h" #include "pa_dictionary.h" #include "pa_charset.h" - -#include "pcre.h" +#include "pa_vregex.h" const String String::Empty; @@ -229,9 +228,13 @@ static int CORD_batched_iter_fn_generic_ }; uint String::Body::hash_code() const { uint result=0; - CORD_iter5(body, 0, - CORD_batched_iter_fn_generic_hash_code, - CORD_batched_iter_fn_generic_hash_code, &result); + if (body && CORD_IS_STRING(body)){ + generic_hash_code(result, body); + } else { + CORD_iter5(body, 0, + CORD_batched_iter_fn_generic_hash_code, + CORD_batched_iter_fn_generic_hash_code, &result); + } return result; } @@ -279,10 +282,22 @@ String& String::append_strdup(const char return *this; } +int CORD_batched_len(const char* s, size_t* len){ + (*len) += lengthUTF8( (const XMLByte *)s, (const XMLByte *)s+strlen(s)); + return 0; +} + +// can be called only for IS_FUNCTION(CORD) which are used only in Lang +int CORD_batched_len(const char, size_t *len){ + (*len)++; + return 0; +} + size_t String::length(Charset& charset) const { if(charset.isUTF8()){ - const XMLByte* srcPtr=(const XMLByte*)cstrm(); - return lengthUTF8(srcPtr, srcPtr+body.length()); + size_t len=0; + body.for_each(CORD_batched_len, CORD_batched_len, &len); + return len; } else return body.length(); } @@ -435,122 +450,31 @@ void String::split(ArrayString& result, } } -enum Match_feature { - MF_NEED_PRE_POST_MATCH = 0x01, - MF_JUST_COUNT_MATCHES = 0x02 -}; +Table* String::match(VRegex* vregex, + Row_action row_action, void *info, + int& matches_count) const { -static void regex_options(const String* options, int* result, int* match_features){ - struct Regex_option { - const char* key; - const char* keyAlt; - int clear; - int set; - int *result; - int flag; - } regex_option[]={ - {"i", "I", 0, PCRE_CASELESS, result, 0}, // a=A - {"s", "S", 0, PCRE_DOTALL, result, 0}, // ^\n\n$ [default] - {"m", "M", PCRE_DOTALL, PCRE_MULTILINE, result, 0}, // ^aaa\n$^bbb\n$ - {"x", 0, 0, PCRE_EXTENDED, result, 0}, // whitespace in regex ignored - {"U", 0, 0, PCRE_UNGREEDY, result, 0}, // ungreedy patterns (greedy by default) - {"g", "G", 0, 1, result+1, 0}, // many rows - {"'", 0, 0, 0, 0, MF_NEED_PRE_POST_MATCH}, - {"n", 0, 0, 0, 0, MF_JUST_COUNT_MATCHES}, - {0, 0, 0, 0, 0, 0} - }; - result[0]=PCRE_EXTRA | PCRE_DOTALL | PCRE_DOLLAR_ENDONLY; - result[1]=0; - - if(options && !options->is_empty()) - for(Regex_option *o=regex_option; o->key; o++) - if( - options->pos(o->key)!=STRING_NOT_FOUND - || (o->keyAlt && options->pos(o->keyAlt)!=STRING_NOT_FOUND) - ){ - if(o->flag){ - (*match_features) |= o->flag; - } else { - *o->result &= ~o->clear; - *o->result |= o->set; - } - } -} - -Table* String::match(Charset& source_charset, - const String& regexp, - const String* options, - Row_action row_action, void *info, - int& matches_count) const { - if(regexp.is_empty()) - throw Exception(PARSER_RUNTIME, - 0, - "regexp is empty"); - - const char* pattern=regexp.cstr(String::L_UNSPECIFIED); // fix any tainted with L_REGEX - const char* errptr; - int erroffset; - int option_bits[2]={0}; - int match_features=0; - regex_options(options, option_bits, &match_features); - bool need_pre_post_match=(match_features & MF_NEED_PRE_POST_MATCH) != 0; - bool just_count_matches=(match_features & MF_JUST_COUNT_MATCHES) != 0; - bool global=option_bits[1]!=0; - - if(source_charset.isUTF8()){ - // @todo (for UTF-8): check string & pattern and use PCRE_NO_UTF8_CHECK option - option_bits[0]|=PCRE_UTF8; - } - - pcre *code=pcre_compile(pattern, option_bits[0], - &errptr, &erroffset, - source_charset.pcre_tables); - - if(!code) - throw Exception(PCRE_EXCEPTION_TYPE, - ®exp.mid(erroffset, regexp.length()), - "regular expression syntax error - %s", errptr); - - int subpatterns=pcre_info(code, 0, 0); - if(subpatterns<0) { - pcre_free(code); - throw Exception(PCRE_EXCEPTION_TYPE, - ®exp, - "pcre_info error (%d)", - subpatterns); - } + // vregex->info(); // I have no idea what does it for? + + bool need_pre_post_match=vregex->is_pre_post_match_needed(); + bool global=vregex->is_global_search(); const char* subject=cstr(); size_t subject_length=strlen(subject); - const int oveclength=(1/*match*/+MAX_MATCH_GROUPS)*3; - int ovector[oveclength]; + const int ovector_size=(1/*match*/+MAX_MATCH_GROUPS)*3; + int ovector[ovector_size]; - // create table Table::Action_options table_options; Table& table=*new Table(string_match_table_template, table_options); - int exec_option_bits=0; int prestart=0; int poststart=0; int postfinish=length(); while(true) { - int exec_substrings=pcre_exec(code, 0, - subject, subject_length, prestart, - exec_option_bits, ovector, oveclength); - - if(exec_substrings==PCRE_ERROR_NOMATCH) { - pcre_free(code); - row_action(table, 0/*last time, no raw*/, 0, 0, poststart, postfinish, info); - return just_count_matches ? 0 : &table; - } + int exec_result=vregex->exec(subject, subject_length, ovector, ovector_size, prestart); - if(exec_substrings<0) { - pcre_free(code); - throw Exception(PCRE_EXCEPTION_TYPE, - ®exp, - print_pcre_exec_error_text(exec_substrings), - exec_substrings); - } + if(exec_result<0) // only PCRE_ERROR_NOMATCH might be here, other negative results cause an exception + break; int prefinish=ovector[0]; poststart=ovector[1]; @@ -565,7 +489,7 @@ Table* String::match(Charset& source_cha *row+=&Empty; // .postmatch } - for(int i=1; iis_just_count() ? 0 : &table; } String& String::change_case(Charset& source_charset, Change_case_kind kind) const {