Logo Search packages:      
Sourcecode: parser version File versions  Download package

Table * String::match ( Charset source_charset,
const String regexp,
const String options,
Row_action  row_action,
void *  info,
int &  matches_count 
) const

Returns:
table of found items, if any. table format is defined and fixed[can be used by others]:
			prematch/match/postmatch/1/2/3/...
		

Definition at line 480 of file pa_string.C.

References cstr(), is_empty(), Charset::isUTF8(), L_UNSPECIFIED, length(), mid(), and Charset::pcre_tables.

Referenced by _match().

                                           { 
      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())
            option_bits[0]=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,
                  &regexp.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,
                  &regexp,
                  "pcre_info error (%d)", 
                        subpatterns);
      }

      const char* subject=cstr();
      size_t subject_length=strlen(subject);
      const int oveclength=(1/*match*/+MAX_MATCH_GROUPS)*3;
      int ovector[oveclength];

      // 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);
                  // if(global || subpatterns)
                  //    return &table; // global or with subpatterns=true+result
                  // else {
                  //    just_matched=false; return 0; // not global=no result
                  // }
                  return just_count_matches ? 0 : &table;
            }

            if(exec_substrings<0) {
                  pcre_free(code);
                  throw Exception(PCRE_EXCEPTION_TYPE,
                        &regexp,
                        print_pcre_exec_error_text(exec_substrings),
                              exec_substrings);
            }

            int prefinish=ovector[0];
            poststart=ovector[1];
            ArrayString* row=new ArrayString;
            if(need_pre_post_match) {
                  *row+=&mid(0, prefinish); // .prematch column value
                  *row+=&mid(prefinish, poststart); // .match
                  *row+=&mid(poststart, postfinish); // .postmatch
            } else {
                  *row+=&Empty; // .prematch column value
                  *row+=&Empty; // .match
                  *row+=&Empty; // .postmatch
            }
            
            for(int i=1; i<exec_substrings; i++) {
                  // -1:-1 case handled peacefully by mid() itself
                  *row+=&mid(ovector[i*2+0], ovector[i*2+1]); // .i column value
            }
            
            matches_count++;
            row_action(table, row, prestart, prefinish, poststart, postfinish, info);

            if(!global || prestart==poststart) { // not global | going to hang
                  pcre_free(code);
                  row_action(table, 0/*last time, no row*/, 0, 0, poststart, postfinish, info);
                  return just_count_matches ? 0 : &table;
                  // return &table;
            }
            prestart=poststart;

/*
            if(option_bits[0] & PCRE_MULTILINE)
                  exec_option_bits|=PCRE_NOTBOL; // start of subject+startoffset not BOL
*/
      }
}


Generated by  Doxygen 1.6.0   Back to index