Diff for /parser3/src/main/pa_string.C between versions 1.62 and 1.74

version 1.62, 2001/04/03 09:58:10 version 1.74, 2001/04/06 13:41:32
Line 10 Line 10
   
 #include "pa_config_includes.h"  #include "pa_config_includes.h"
   
 #include <locale.h>  #include "pcre.h"
   
 #include "pa_pool.h"  #include "pa_pool.h"
 #include "pa_string.h"  #include "pa_string.h"
Line 22 Line 22
 #include "pa_table.h"  #include "pa_table.h"
 #include "pa_threads.h"  #include "pa_threads.h"
   
 #include "pcre.h"  
   
 //#include "pa_sapi.h"  //#include "pa_sapi.h"
   
 // consts  
   
 const int MAX_MATCH_COLUMNS=20;  
   
 // String  // String
   
 String::String(Pool& apool, const char *src, bool tasize_ted) :  String::String(Pool& apool, const char *src, bool tasize_ted) :
Line 203  int String::cmp(int& partial, const Stri Line 197  int String::cmp(int& partial, const Stri
                         break;                          break;
   
                 if(pos+a_row->item.size > this_offset) {                  if(pos+a_row->item.size > this_offset) {
                         if(lang!=UL_UNKNOWN && a_row->item.lang!=lang)                           if(lang!=UL_UNSPECIFIED && a_row->item.lang!=lang) 
                                 return -1; // wrong lang -- bail out                                  return -1; // wrong lang -- bail out
   
                         int size_diff=                          int size_diff=
Line 283  int String::cmp(int& partial, const char Line 277  int String::cmp(int& partial, const char
                         break;                          break;
   
                 if(pos+a_row->item.size > this_offset) {                  if(pos+a_row->item.size > this_offset) {
                         if(lang!=UL_UNKNOWN && a_row->item.lang!=lang)                           if(lang!=UL_UNSPECIFIED && a_row->item.lang!=lang) 
                                 return -1; // wrong lang -- bail out                                  return -1; // wrong lang -- bail out
   
                         int size_diff=                          int size_diff=
Line 346  const Origin& String::origin() const { Line 340  const Origin& String::origin() const {
 }  }
 #endif  #endif
   
 String& String::piece(size_t start, size_t finish) const {  String& String::mid(size_t start, size_t finish) const {
         start=max(0, start);          start=max(0, start);
         finish=min(size(), finish);          finish=min(size(), finish);
         if(start==finish)          if(start==finish)
Line 419  void String::split(Array& result, Line 413  void String::split(Array& result,
                 int pos_before;                  int pos_before;
                 // while we have 'delim'...                  // while we have 'delim'...
                 for(; (pos_before=pos(delim, delim_size, pos_after, lang))>=0 && limit; limit--) {                  for(; (pos_before=pos(delim, delim_size, pos_after, lang))>=0 && limit; limit--) {
                         result+=&piece(pos_after, pos_before);                          result+=&mid(pos_after, pos_before);
                         pos_after=pos_before+delim_size;                          pos_after=pos_before+delim_size;
                 }                  }
                 // last piece                  // last piece
                 if(pos_after<size() && limit) {                  if(pos_after<size() && limit) {
                         result+=&piece(pos_after, size());                          result+=&mid(pos_after, size());
                         pos_after=size();                          pos_after=size();
                 }                  }
                 if(pos_after_ref)                  if(pos_after_ref)
Line 445  void String::split(Array& result, Line 439  void String::split(Array& result,
                 int pos_before;                  int pos_before;
                 // while we have 'delim'...                  // while we have 'delim'...
                 for(; (pos_before=pos(delim, pos_after, lang))>=0 && limit; limit--) {                  for(; (pos_before=pos(delim, pos_after, lang))>=0 && limit; limit--) {
                         result+=&piece(pos_after, pos_before);                          result+=&mid(pos_after, pos_before);
                         pos_after=pos_before+delim.size();                          pos_after=pos_before+delim.size();
                 }                  }
                 // last piece                  // last piece
                 if(pos_after<size() && limit) {                  if(pos_after<size() && limit) {
                         result+=&piece(pos_after, size());                          result+=&mid(pos_after, size());
                         pos_after=size();                          pos_after=size();
                 }                  }
                 if(pos_after_ref)                  if(pos_after_ref)
Line 462  void String::split(Array& result, Line 456  void String::split(Array& result,
         }          }
 }  }
   
 /// @test setlocale param to auto.p  @test pcre_malloc & pcre_free substs  /// @test really @b test: s x m [tested: i & g ]
   static void regex_options(char *options, int *result){
       struct Regex_option {
                   char key;
                   int clear, set;
                   int *result;
       } regex_option[]={
                   {'i', 0, PCRE_CASELESS, result}, // a=A
                   {'s', 0, PCRE_DOTALL, result}, // \n\n$
                   {'x', 0, PCRE_EXTENDED, result}, // whitespace in regex ignored
                   {'m', PCRE_DOTALL, PCRE_MULTILINE, result}, // ^aaa\n$^bbb\n$
                   {'g', 0, true, result+1}, // many rows
                   {0},
       };
           result[0]=PCRE_EXTRA | PCRE_DOTALL;
           result[1]=0;
   
       if(options) 
                   for(Regex_option *o=regex_option; o->key; o++) 
                           if(
                                   strchr(options, o->key) || 
                                   strchr(options, toupper(o->key))) {
                                   *(o->result)&=~o->clear;
                                   *(o->result)|=o->set;
                           }
   }
   
   /**
           returns true if fills table.
           table format is defined and fixed[can be used by others]: 
           @verbatim
                   pre-match/match/post-match/1/2/3/...
           @endverbatim
   */
 bool String::match(const String *aorigin,  bool String::match(const String *aorigin,
                                    const String& regexp,                                      const String& regexp, 
                                    const String& options,                                     const String *options,
                                    Table **table) const {                                      Table **table,
         SYNCHRONIZED(true);                                     Row_action row_action, void *info) const { 
         static const unsigned char *tables=0;  
         if(!tables) {          if(!regexp.size())
                 setlocale(LC_CTYPE, "ru");                  THROW(0, 0,
                 tables = pcre_maketables();                          aorigin,
         }                          "regexp is empty");
         const char *pattern=regexp.cstr();          const char *pattern=regexp.cstr(UL_AS_IS);
         const char *errptr;          const char *errptr;
         int erroffset;          int erroffset;
         pcre *code=pcre_compile(pattern, 0,       int option_bits[2];  regex_options(options?options->cstr():0, option_bits);
           pcre *code=pcre_compile(pattern, option_bits[0], 
                 &errptr, &erroffset,                  &errptr, &erroffset,
                 tables);                  pcre_tables);
   
         if(!code)          if(!code)
                 THROW(0, 0,                  THROW(0, 0,
                         &regexp.piece(erroffset, regexp.size()),                          &regexp.mid(erroffset, regexp.size()),
                         errptr);                          "regular expression syntax error - %s", errptr);
                   
         int ovecsize;          int info_substrings=pcre_info(code, 0, 0);
         int *ovector=(int *)malloc(sizeof(int)*(ovecsize=(1/*.match*/+MAX_MATCH_COLUMNS)*3));          if(info_substrings<0) {
         const char *subject=cstr();                  (*pcre_free)(code);
         int length=strlen(subject);                  THROW(0, 0,
         int exec_result=pcre_exec(code, 0,                          aorigin,
           subject, length, 0/*startoffset*/,                          "pcre_info error #%d", 
           0/*options*/, ovector, ovecsize);                                  info_substrings);
   
         if(exec_result==PCRE_ERROR_NOMATCH) {  
                 *table=0;  
                 return false;  
         }          }
   
         if(exec_result<0)          int startoffset=0;
                 THROW(0, 0,          const char *subject=cstr(UL_AS_IS);
                         0,          int length=strlen(subject);
                         "pcre_exec failed");          int ovecsize;
           int *ovector=(int *)malloc(sizeof(int)*
                   (ovecsize=(1/*match*/+info_substrings)*3));
   
         if(exec_result==0)          { // create table
                 THROW(0, 0,                  Array& columns=*NEW Array(pool());
                         aorigin,                  columns+=string_pre_match_name;
                         "produced more substrings than maximum handled by Parser, which is %d",                  columns+=string_match_name;
                                 MAX_MATCH_COLUMNS);                  columns+=string_post_match_name;
                   for(int i=1; i<=info_substrings; i++) {
                           char *column=(char *)malloc(MAX_NUMBER);
                           snprintf(column, MAX_NUMBER, "%d", i);
                           columns+=NEW String(pool(), column); // .i column name
                   }
                   *table=NEW Table(pool(), aorigin, &columns);
           }
   
         Array& columns=*NEW Array(pool());          int exec_option_bits=0;
         columns+=string_match_name; // .match column name          while(true) {
         Array& row=*NEW Array(pool());                  int exec_substrings=pcre_exec(code, 0,
         row+=&piece(ovector[0], ovector[1]); // match column value                          subject, length, startoffset,
                                   exec_option_bits, ovector, ovecsize);
         for(int i=1; i<exec_result; i++) {                  
                 char *column=(char *)malloc(MAX_NUMBER);                  if(exec_substrings==PCRE_ERROR_NOMATCH) {
                 snprintf(column, MAX_NUMBER, "%d", i);                          (*pcre_free)(code);
                 columns+=NEW String(pool(), column); // .i column name                          (*row_action)(**table, 0/*last time, no row*/, 0, 0, info);
                 row+=&piece(ovector[i*2+0], ovector[i*2+1]); // .i column value                          return option_bits[1]!=0; // global=true+table, not global=false
                   }
   
                   if(exec_substrings<0) {
                           (*pcre_free)(code);
                           THROW(0, 0,
                                   aorigin,
                                   "regular expression execute error #%d", 
                                           exec_substrings);
                   }
   
                   Array& row=*NEW Array(pool());
                   row+=&mid(0, ovector[0]); // .pre-match column value
                   row+=&mid(ovector[0], ovector[1]); // .match
                   row+=&mid(ovector[1], size()); // .post-match
                   
                   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
                   }
                   
                   (*row_action)(**table, &row, startoffset, ovector[0], info);
   
                   if(!option_bits[1] || !(startoffset=ovector[1])) { // not global | going to hang
                           (*pcre_free)(code);
                           (*row_action)(**table, 0/*last time, no row*/, 0, 0, info);
                           return true;
                   }
   
   /*
                   if(option_bits[0] & PCRE_MULTILINE)
                           exec_option_bits|=PCRE_NOTBOL; // start of subject+startoffset not BOL
   */
         }          }
           
         *table=NEW Table(pool(), aorigin, &columns);  
         (**table)+=&row;  
         return true;  
 }  }

Removed from v.1.62  
changed lines
  Added in v.1.74


E-mail: