/[pcre]/code/tags/pcre-8.01/pcrecpp.cc
ViewVC logotype

Diff of /code/tags/pcre-8.01/pcrecpp.cc

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 81 by nigel, Sat Feb 24 21:40:59 2007 UTC revision 93 by nigel, Sat Feb 24 21:41:42 2007 UTC
# Line 61  static const string empty_string; Line 61  static const string empty_string;
61  // If the user doesn't ask for any options, we just use this one  // If the user doesn't ask for any options, we just use this one
62  static RE_Options default_options;  static RE_Options default_options;
63    
64  void RE::Init(const char* pat, const RE_Options* options) {  void RE::Init(const string& pat, const RE_Options* options) {
65    pattern_ = pat;    pattern_ = pat;
66    if (options == NULL) {    if (options == NULL) {
67      options_ = default_options;      options_ = default_options;
# Line 78  void RE::Init(const char* pat, const RE_ Line 78  void RE::Init(const char* pat, const RE_
78      // conservative in that it may treat some "simple" patterns      // conservative in that it may treat some "simple" patterns
79      // as "complex" (e.g., if the vertical bar is in a character      // as "complex" (e.g., if the vertical bar is in a character
80      // class or is escaped).  But it seems good enough.      // class or is escaped).  But it seems good enough.
81      if (strchr(pat, '|') == NULL) {      if (strchr(pat.c_str(), '|') == NULL) {
82        // Simple pattern: we can use position-based checks to perform        // Simple pattern: we can use position-based checks to perform
83        // fully anchored matches        // fully anchored matches
84        re_full_ = re_partial_;        re_full_ = re_partial_;
# Line 89  void RE::Init(const char* pat, const RE_ Line 89  void RE::Init(const char* pat, const RE_
89    }    }
90  }  }
91    
92  RE::~RE() {  void RE::Cleanup() {
93    if (re_full_ != NULL && re_full_ != re_partial_) (*pcre_free)(re_full_);    if (re_full_ != NULL && re_full_ != re_partial_) (*pcre_free)(re_full_);
94    if (re_partial_ != NULL)                         (*pcre_free)(re_partial_);    if (re_partial_ != NULL)                         (*pcre_free)(re_partial_);
95    if (error_ != &empty_string)                     delete error_;    if (error_ != &empty_string)                     delete error_;
96  }  }
97    
98    
99    RE::~RE() {
100      Cleanup();
101    }
102    
103    
104  pcre* RE::Compile(Anchor anchor) {  pcre* RE::Compile(Anchor anchor) {
105    // First, convert RE_Options into pcre options    // First, convert RE_Options into pcre options
106    int pcre_options = 0;    int pcre_options = 0;
# Line 332  bool RE::Replace(const StringPiece& rewr Line 338  bool RE::Replace(const StringPiece& rewr
338    return true;    return true;
339  }  }
340    
341    // Returns PCRE_NEWLINE_CRLF, PCRE_NEWLINE_CR, or PCRE_NEWLINE_LF.
342    // Note that PCRE_NEWLINE_CRLF is defined to be P_N_CR | P_N_LF.
343    static int NewlineMode(int pcre_options) {
344      // TODO: if we can make it threadsafe, cache this var
345      int newline_mode = 0;
346      /* if (newline_mode) return newline_mode; */  // do this once it's cached
347      if (pcre_options & (PCRE_NEWLINE_CRLF|PCRE_NEWLINE_CR|PCRE_NEWLINE_LF)) {
348        newline_mode = (pcre_options &
349                        (PCRE_NEWLINE_CRLF|PCRE_NEWLINE_CR|PCRE_NEWLINE_LF));
350      } else {
351        int newline;
352        pcre_config(PCRE_CONFIG_NEWLINE, &newline);
353        if (newline == 10)
354          newline_mode = PCRE_NEWLINE_LF;
355        else if (newline == 13)
356          newline_mode = PCRE_NEWLINE_CR;
357        else if (newline == 3338)
358          newline_mode = PCRE_NEWLINE_CRLF;
359        else
360          assert("" == "Unexpected return value from pcre_config(NEWLINE)");
361      }
362      return newline_mode;
363    }
364    
365  int RE::GlobalReplace(const StringPiece& rewrite,  int RE::GlobalReplace(const StringPiece& rewrite,
366                        string *str) const {                        string *str) const {
367    int count = 0;    int count = 0;
# Line 350  int RE::GlobalReplace(const StringPiece& Line 380  int RE::GlobalReplace(const StringPiece&
380      if (matchstart == matchend && matchstart == lastend) {      if (matchstart == matchend && matchstart == lastend) {
381        // advance one character if we matched an empty string at the same        // advance one character if we matched an empty string at the same
382        // place as the last match occurred        // place as the last match occurred
383        if (start < static_cast<int>(str->length()))        matchend = start + 1;
384          out.push_back((*str)[start]);        // If the current char is CR and we're in CRLF mode, skip LF too.
385        start++;        // Note it's better to call pcre_fullinfo() than to examine
386          // all_options(), since options_ could have changed bewteen
387          // compile-time and now, but this is simpler and safe enough.
388          if (start+1 < static_cast<int>(str->length()) &&
389              (*str)[start] == '\r' && (*str)[start+1] == '\n' &&
390              NewlineMode(options_.all_options()) == PCRE_NEWLINE_CRLF) {
391            matchend++;
392          }
393          // We also need to advance more than one char if we're in utf8 mode.
394    #ifdef SUPPORT_UTF8
395          if (options_.utf8()) {
396            while (matchend < static_cast<int>(str->length()) &&
397                   ((*str)[matchend] & 0xc0) == 0x80)
398              matchend++;
399          }
400    #endif
401          if (matchend <= static_cast<int>(str->length()))
402            out.append(*str, start, matchend - start);
403          start = matchend;
404      } else {      } else {
405        out.append(*str, start, matchstart - start);        out.append(*str, start, matchstart - start);
406        Rewrite(&out, rewrite, *str, vec, matches);        Rewrite(&out, rewrite, *str, vec, matches);
# Line 382  bool RE::Extract(const StringPiece& rewr Line 430  bool RE::Extract(const StringPiece& rewr
430    return Rewrite(out, rewrite, text, vec, matches);    return Rewrite(out, rewrite, text, vec, matches);
431  }  }
432    
433    /*static*/ string RE::QuoteMeta(const StringPiece& unquoted) {
434      string result;
435    
436      // Escape any ascii character not in [A-Za-z_0-9].
437      //
438      // Note that it's legal to escape a character even if it has no
439      // special meaning in a regular expression -- so this function does
440      // that.  (This also makes it identical to the perl function of the
441      // same name; see `perldoc -f quotemeta`.)
442      for (int ii = 0; ii < unquoted.size(); ++ii) {
443        // Note that using 'isalnum' here raises the benchmark time from
444        // 32ns to 58ns:
445        if ((unquoted[ii] < 'a' || unquoted[ii] > 'z') &&
446            (unquoted[ii] < 'A' || unquoted[ii] > 'Z') &&
447            (unquoted[ii] < '0' || unquoted[ii] > '9') &&
448            unquoted[ii] != '_' &&
449            // If this is the part of a UTF8 or Latin1 character, we need
450            // to copy this byte without escaping.  Experimentally this is
451            // what works correctly with the regexp library.
452            !(unquoted[ii] & 128)) {
453          result += '\\';
454        }
455        result += unquoted[ii];
456      }
457    
458      return result;
459    }
460    
461  /***** Actual matching and rewriting code *****/  /***** Actual matching and rewriting code *****/
462    
463  int RE::TryMatch(const StringPiece& text,  int RE::TryMatch(const StringPiece& text,
# Line 397  int RE::TryMatch(const StringPiece& text Line 473  int RE::TryMatch(const StringPiece& text
473    
474    pcre_extra extra = { 0 };    pcre_extra extra = { 0 };
475    if (options_.match_limit() > 0) {    if (options_.match_limit() > 0) {
476      extra.flags = PCRE_EXTRA_MATCH_LIMIT;      extra.flags |= PCRE_EXTRA_MATCH_LIMIT;
477      extra.match_limit = options_.match_limit();      extra.match_limit = options_.match_limit();
478    }    }
479      if (options_.match_limit_recursion() > 0) {
480        extra.flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
481        extra.match_limit_recursion = options_.match_limit_recursion();
482      }
483    int rc = pcre_exec(re,              // The regular expression object    int rc = pcre_exec(re,              // The regular expression object
484                       &extra,                       &extra,
485                       text.data(),                       (text.data() == NULL) ? "" : text.data(),
486                       text.size(),                       text.size(),
487                       startpos,                       startpos,
488                       (anchor == UNANCHORED) ? 0 : PCRE_ANCHORED,                       (anchor == UNANCHORED) ? 0 : PCRE_ANCHORED,
# Line 449  bool RE::DoMatchImpl(const StringPiece& Line 529  bool RE::DoMatchImpl(const StringPiece&
529    
530    *consumed = vec[1];    *consumed = vec[1];
531    
532    if (args == NULL) {    if (n == 0 || args == NULL) {
533      // We are not interested in results      // We are not interested in results
534      return true;      return true;
535    }    }
536    
537      if (NumberOfCapturingGroups() < n) {
538        // RE has fewer capturing groups than number of arg pointers passed in
539        return false;
540      }
541    
542    // If we got here, we must have matched the whole pattern.    // If we got here, we must have matched the whole pattern.
543    // We do not need (can not do) any more checks on the value of 'matches' here    // We do not need (can not do) any more checks on the value of 'matches' here
544    // -- see the comment for TryMatch.    // -- see the comment for TryMatch.
# Line 517  bool RE::Rewrite(string *out, const Stri Line 602  bool RE::Rewrite(string *out, const Stri
602    
603  // Return the number of capturing subpatterns, or -1 if the  // Return the number of capturing subpatterns, or -1 if the
604  // regexp wasn't valid on construction.  // regexp wasn't valid on construction.
605  int RE::NumberOfCapturingGroups() {  int RE::NumberOfCapturingGroups() const {
606    if (re_partial_ == NULL) return -1;    if (re_partial_ == NULL) return -1;
607    
608    int result;    int result;
# Line 613  bool Arg::parse_ulong_radix(const char* Line 698  bool Arg::parse_ulong_radix(const char*
698    if (n == 0) return false;    if (n == 0) return false;
699    char buf[kMaxNumberLength+1];    char buf[kMaxNumberLength+1];
700    str = TerminateNumber(buf, str, n);    str = TerminateNumber(buf, str, n);
701      if (str[0] == '-') return false;    // strtoul() on a negative number?!
702    char* end;    char* end;
703    errno = 0;    errno = 0;
704    unsigned long r = strtoul(str, &end, radix);    unsigned long r = strtoul(str, &end, radix);
# Line 702  bool Arg::parse_ulonglong_radix(const ch Line 788  bool Arg::parse_ulonglong_radix(const ch
788    if (n == 0) return false;    if (n == 0) return false;
789    char buf[kMaxNumberLength+1];    char buf[kMaxNumberLength+1];
790    str = TerminateNumber(buf, str, n);    str = TerminateNumber(buf, str, n);
791      if (str[0] == '-') return false;    // strtoull() on a negative number?!
792    char* end;    char* end;
793    errno = 0;    errno = 0;
794  #if defined HAVE_STRTOQ  #if defined HAVE_STRTOQ
# Line 756  bool Arg::parse_float(const char* str, i Line 843  bool Arg::parse_float(const char* str, i
843      return parse_##name##_radix(str, n, dest, 0);                       \      return parse_##name##_radix(str, n, dest, 0);                       \
844    }    }
845    
846  DEFINE_INTEGER_PARSERS(short);  DEFINE_INTEGER_PARSERS(short)      /*                                   */
847  DEFINE_INTEGER_PARSERS(ushort);  DEFINE_INTEGER_PARSERS(ushort)     /*                                   */
848  DEFINE_INTEGER_PARSERS(int);  DEFINE_INTEGER_PARSERS(int)        /* Don't use semicolons after these  */
849  DEFINE_INTEGER_PARSERS(uint);  DEFINE_INTEGER_PARSERS(uint)       /* statements because they can cause */
850  DEFINE_INTEGER_PARSERS(long);  DEFINE_INTEGER_PARSERS(long)       /* compiler warnings if the checking */
851  DEFINE_INTEGER_PARSERS(ulong);  DEFINE_INTEGER_PARSERS(ulong)      /* level is turned up high enough.   */
852  DEFINE_INTEGER_PARSERS(longlong);  DEFINE_INTEGER_PARSERS(longlong)   /*                                   */
853  DEFINE_INTEGER_PARSERS(ulonglong);  DEFINE_INTEGER_PARSERS(ulonglong)  /*                                   */
854    
855  #undef DEFINE_INTEGER_PARSERS  #undef DEFINE_INTEGER_PARSERS
856    

Legend:
Removed from v.81  
changed lines
  Added in v.93

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12