--- parser3/src/main/pa_string.C 2008/07/17 09:11:25 1.211 +++ parser3/src/main/pa_string.C 2008/08/21 15:58:12 1.217 @@ -5,9 +5,7 @@ Author: Alexandr Petrosian (http://paf.design.ru) */ -static const char * const IDENT_STRING_C="$Date: 2008/07/17 09:11:25 $"; - -#include "pcre.h" +static const char * const IDENT_STRING_C="$Date: 2008/08/21 15:58:12 $"; #include "pa_string.h" #include "pa_exception.h" @@ -15,6 +13,8 @@ static const char * const IDENT_STRING_C #include "pa_dictionary.h" #include "pa_charset.h" +#include "pcre.h" + const String String::Empty; int pa_atoi(const char* str, const String* problem_source) { @@ -328,7 +328,7 @@ String& String::mid(Charset& charset, si const XMLByte* srcPtr=(const XMLByte*)cstrm(); const XMLByte* srcEnd=srcPtr+body.length(); - // convert from and substr_length from 'characters' to 'bytes' + // convert 'from' and 'substr_length' from 'characters' to 'bytes' from=getUTF8BytePos(srcPtr, srcEnd, from); substr_length=getUTF8BytePos(srcPtr+from, srcEnd, substr_length); if(!substr_length) @@ -367,13 +367,24 @@ size_t String::pos(const String& substr, size_t String::pos(Charset& charset, const String& substr, size_t this_offset, Language lang) const { - size_t result=pos(substr.body, this_offset, lang); - if(result==CORD_NOT_FOUND) - return STRING_NOT_FOUND; - + size_t result; if(charset.isUTF8()){ const XMLByte* srcPtr=(const XMLByte*)cstrm(); - result=getUTF8CharPos(srcPtr, srcPtr+body.length(), result); + const XMLByte* srcEnd=srcPtr+body.length(); + + // convert 'this_offset' from 'characters' to 'bytes' + this_offset=getUTF8BytePos(srcPtr, srcEnd, this_offset); + + result=pos(substr.body, this_offset, lang); + if(result==CORD_NOT_FOUND) + return STRING_NOT_FOUND; + + // convert 'result' from 'bytes' to 'characters' + result=getUTF8CharPos(srcPtr, srcEnd, result); + } else { + result=pos(substr.body, this_offset, lang); + if(result==CORD_NOT_FOUND) + return STRING_NOT_FOUND; } return result; @@ -431,30 +442,31 @@ enum Match_feature { static void regex_options(const String* options, int* result, int* match_features){ struct Regex_option { - const char* keyL; - const char* keyU; + 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] - {"x", "U", 0, PCRE_EXTENDED, result, 0}, // whitespace in regex ignored + {"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", "N", 0, 0, 0, MF_JUST_COUNT_MATCHES}, + {"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->keyL; o++) + for(Regex_option *o=regex_option; o->key; o++) if( - options->pos(o->keyL)!=STRING_NOT_FOUND - || (o->keyU && options->pos(o->keyU)!=STRING_NOT_FOUND) + options->pos(o->key)!=STRING_NOT_FOUND + || (o->keyAlt && options->pos(o->keyAlt)!=STRING_NOT_FOUND) ){ if(o->flag){ (*match_features) |= o->flag; @@ -484,6 +496,10 @@ Table* String::match(Charset& source_cha 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()) + option_bits[0]=option_bits[0] | PCRE_UTF8; + pcre *code=pcre_compile(pattern, option_bits[0], &errptr, &erroffset, source_charset.pcre_tables); @@ -535,7 +551,7 @@ Table* String::match(Charset& source_cha pcre_free(code); throw Exception(0, ®exp, - "regular expression execute error (%d)", + print_pcre_exec_error_text(exec_substrings), exec_substrings); } @@ -581,8 +597,9 @@ String& String::change_case(Charset& sou return result; char* new_cstr=cstrm(); - size_t new_cstr_len=length(); + if(source_charset.isUTF8()) { + size_t new_cstr_len=length(); switch(kind) { case CC_UPPER: change_case_UTF8((const XMLByte*)new_cstr, new_cstr_len, (XMLByte*)new_cstr, new_cstr_len, UTF8CaseToUpper); @@ -631,6 +648,13 @@ String& String::change_case(Charset& sou return result; } +const String& String::escape(Charset& source_charset) const { + if(is_empty()) + return *this; + + return Charset::escape(*this, source_charset); +} + const String& String::replace(const Dictionary& dict) const { String& result=*new String(); const char* old_cstr=cstr();