Ports libpcrecpp to pcre2
Ports the c++ wrapper around pcre to pcre2 and doing
some modifications on the way.
- Lifts the limitation of matching arguments that
could be passed to the members of pcrecpp::RE without
changing the API.
- The newline mode can no longer be specified as an option
flag. Instead it must be passed to the pattern compiler using
a compile context. Therefore, a member was added to REOptions,
holding the newline mode.
- The PCRE_EXTRA option has no equivalent in pcre2 and was
removed.
Merged-In: I0bd5da97128fda25b8b2014c94bed9422540dd67
Bug: 24091652
Change-Id: I0bd5da97128fda25b8b2014c94bed9422540dd67
diff --git a/Android.bp b/Android.bp
index 00fb54a..2c0ab27 100644
--- a/Android.bp
+++ b/Android.bp
@@ -50,12 +50,17 @@
// === libpcrecpp targets ===
-//cc_library_shared {
-// name: "libpcrecpp",
-// cflags: libpcre_cflags,
-// local_include_dirs: ["dist"],
-//
-// srcs: libpcrecpp_src_files,
-// shared_libs: ["libpcre"],
-// export_include_dirs: ["."],
-//}
+cc_library_shared {
+ name: "libpcrecpp",
+ local_include_dirs: ["pcrecpp/include"],
+ shared_libs: ["libpcre2"],
+ export_include_dirs: [
+ "pcrecpp/include",
+ "include",
+ ],
+ srcs: [
+ "pcrecpp/pcrecpp.cc",
+ "pcrecpp/pcre_scanner.cc",
+ "pcrecpp/pcre_stringpiece.cc",
+ ],
+}
diff --git a/pcrecpp/include/pcre_scanner.h b/pcrecpp/include/pcre_scanner.h
index 5617e45..b2bfabe 100644
--- a/pcrecpp/include/pcre_scanner.h
+++ b/pcrecpp/include/pcre_scanner.h
@@ -53,7 +53,7 @@
namespace pcrecpp {
-class PCRECPP_EXP_DEFN Scanner {
+class Scanner {
public:
Scanner();
explicit Scanner(const std::string& input);
@@ -79,12 +79,13 @@
// parsed and stored into the arguments.
// If it returns true, it skips over the matched input and any
// following input that matches the "skip" regular expression.
- bool Consume(const RE& re,
- const Arg& arg0 = RE::no_arg,
- const Arg& arg1 = RE::no_arg,
- const Arg& arg2 = RE::no_arg
- // TODO: Allow more arguments?
- );
+ template<typename ... ARGS>
+ bool Consume(const RE& re, ARGS && ... args) {
+ const bool result = re.Consume(&input_, args...);
+ if (result && should_skip_)
+ ConsumeSkip();
+ return result;
+ }
// Set the "skip" regular expression. If after consuming some data,
// a prefix of the input matches this RE, it is automatically
diff --git a/pcrecpp/include/pcre_stringpiece.h b/pcrecpp/include/pcre_stringpiece.h
index cc3dc42..51b9812 100644
--- a/pcrecpp/include/pcre_stringpiece.h
+++ b/pcrecpp/include/pcre_stringpiece.h
@@ -50,7 +50,7 @@
#include <bits/type_traits.h>
#endif
-#include <pcre.h>
+#include <pcre2.h>
using std::memcmp;
using std::strlen;
@@ -58,7 +58,7 @@
namespace pcrecpp {
-class PCRECPP_EXP_DEFN StringPiece {
+class StringPiece {
private:
const char* ptr_;
int length_;
@@ -174,7 +174,7 @@
#endif
// allow StringPiece to be logged
-PCRECPP_EXP_DECL std::ostream& operator<<(std::ostream& o,
+extern std::ostream& operator<<(std::ostream& o,
const pcrecpp::StringPiece& piece);
#endif /* _PCRE_STRINGPIECE_H */
diff --git a/pcrecpp/include/pcrecpp.h b/pcrecpp/include/pcrecpp.h
index 3e594b0..0c216b2 100644
--- a/pcrecpp/include/pcrecpp.h
+++ b/pcrecpp/include/pcrecpp.h
@@ -331,11 +331,12 @@
#include <string>
-#include <pcre.h>
+#include <pcre2.h>
#include <pcrecpparg.h> // defines the Arg class
// This isn't technically needed here, but we include it
// anyway so folks who include pcrecpp.h don't have to.
#include <pcre_stringpiece.h>
+#include <memory>
namespace pcrecpp {
@@ -346,16 +347,23 @@
#define PCRE_IS_SET(o) \
(all_options_ & o) == o
+typedef std::shared_ptr<pcre2_match_data> pcre2_match_data_ptr;
+
/***** Compiling regular expressions: the RE class *****/
// RE_Options allow you to set options to be passed along to pcre,
// along with other options we put on top of pcre.
// Only 9 modifiers, plus match_limit and match_limit_recursion,
// are supported now.
-class PCRECPP_EXP_DEFN RE_Options {
+class RE_Options {
public:
// constructor
- RE_Options() : match_limit_(0), match_limit_recursion_(0), all_options_(0) {}
+ RE_Options()
+ : newline_mode_(0),
+ match_limit_(0),
+ match_limit_recursion_(0),
+ all_options_(0) {
+ }
// alternative constructor.
// To facilitate transfer of legacy code from C programs
@@ -365,8 +373,12 @@
// But new code is better off doing
// RE(pattern,
// RE_Options().set_caseless(true).set_multiline(true)).PartialMatch(str);
- RE_Options(int option_flags) : match_limit_(0), match_limit_recursion_(0),
- all_options_(option_flags) {}
+ RE_Options(int option_flags)
+ : newline_mode_(0),
+ match_limit_(0),
+ match_limit_recursion_(0),
+ all_options_(option_flags) {
+ }
// we're fine with the default destructor, copy constructor, etc.
// accessors and mutators
@@ -383,66 +395,74 @@
}
bool caseless() const {
- return PCRE_IS_SET(PCRE_CASELESS);
+ return PCRE_IS_SET(PCRE2_CASELESS);
}
RE_Options &set_caseless(bool x) {
- PCRE_SET_OR_CLEAR(x, PCRE_CASELESS);
+ PCRE_SET_OR_CLEAR(x, PCRE2_CASELESS);
}
bool multiline() const {
- return PCRE_IS_SET(PCRE_MULTILINE);
+ return PCRE_IS_SET(PCRE2_MULTILINE);
}
RE_Options &set_multiline(bool x) {
- PCRE_SET_OR_CLEAR(x, PCRE_MULTILINE);
+ PCRE_SET_OR_CLEAR(x, PCRE2_MULTILINE);
+ }
+
+ int newline_mode() const {
+ if(newline_mode_)
+ return newline_mode_;
+ else {
+ // if newline_mode_ is 0 return the global configuration default
+ int value;
+ pcre2_config_8(PCRE2_CONFIG_NEWLINE, &value);
+ return value;
+ }
+ }
+ RE_Options & set_newline_mode(int newline_mode) {
+ newline_mode_ = newline_mode;
+ return *this;
}
bool dotall() const {
- return PCRE_IS_SET(PCRE_DOTALL);
+ return PCRE_IS_SET(PCRE2_DOTALL);
}
RE_Options &set_dotall(bool x) {
- PCRE_SET_OR_CLEAR(x, PCRE_DOTALL);
+ PCRE_SET_OR_CLEAR(x, PCRE2_DOTALL);
}
bool extended() const {
- return PCRE_IS_SET(PCRE_EXTENDED);
+ return PCRE_IS_SET(PCRE2_EXTENDED);
}
RE_Options &set_extended(bool x) {
- PCRE_SET_OR_CLEAR(x, PCRE_EXTENDED);
+ PCRE_SET_OR_CLEAR(x, PCRE2_EXTENDED);
}
bool dollar_endonly() const {
- return PCRE_IS_SET(PCRE_DOLLAR_ENDONLY);
+ return PCRE_IS_SET(PCRE2_DOLLAR_ENDONLY);
}
RE_Options &set_dollar_endonly(bool x) {
- PCRE_SET_OR_CLEAR(x, PCRE_DOLLAR_ENDONLY);
- }
-
- bool extra() const {
- return PCRE_IS_SET(PCRE_EXTRA);
- }
- RE_Options &set_extra(bool x) {
- PCRE_SET_OR_CLEAR(x, PCRE_EXTRA);
+ PCRE_SET_OR_CLEAR(x, PCRE2_DOLLAR_ENDONLY);
}
bool ungreedy() const {
- return PCRE_IS_SET(PCRE_UNGREEDY);
+ return PCRE_IS_SET(PCRE2_UNGREEDY);
}
RE_Options &set_ungreedy(bool x) {
- PCRE_SET_OR_CLEAR(x, PCRE_UNGREEDY);
+ PCRE_SET_OR_CLEAR(x, PCRE2_UNGREEDY);
}
- bool utf8() const {
- return PCRE_IS_SET(PCRE_UTF8);
+ bool utf() const {
+ return PCRE_IS_SET(PCRE2_UTF);
}
- RE_Options &set_utf8(bool x) {
- PCRE_SET_OR_CLEAR(x, PCRE_UTF8);
+ RE_Options &set_utf(bool x) {
+ PCRE_SET_OR_CLEAR(x, PCRE2_UTF);
}
bool no_auto_capture() const {
- return PCRE_IS_SET(PCRE_NO_AUTO_CAPTURE);
+ return PCRE_IS_SET(PCRE2_NO_AUTO_CAPTURE);
}
RE_Options &set_no_auto_capture(bool x) {
- PCRE_SET_OR_CLEAR(x, PCRE_NO_AUTO_CAPTURE);
+ PCRE_SET_OR_CLEAR(x, PCRE2_NO_AUTO_CAPTURE);
}
RE_Options &set_all_options(int opt) {
@@ -456,14 +476,15 @@
// TODO: add other pcre flags
private:
+ int newline_mode_;
int match_limit_;
int match_limit_recursion_;
int all_options_;
};
// These functions return some common RE_Options
-static inline RE_Options UTF8() {
- return RE_Options().set_utf8(true);
+static inline RE_Options UTF() {
+ return RE_Options().set_utf(true);
}
static inline RE_Options CASELESS() {
@@ -484,7 +505,7 @@
// Interface for regular expression matching. Also corresponds to a
// pre-compiled regular expression. An "RE" object is safe for
// concurrent use by multiple threads.
-class PCRECPP_EXP_DEFN RE {
+class RE {
public:
// We provide implicit conversions from strings so that users can
// pass in a string or a "const char*" wherever an "RE" is expected.
@@ -525,84 +546,63 @@
// If RE could not be created properly, returns an error string.
// Else returns the empty string.
- const string& error() const { return *error_; }
+ const string& error() const { return error_; }
/***** The useful part: the matching interface *****/
// This is provided so one can do pattern.ReplaceAll() just as
// easily as ReplaceAll(pattern-text, ....)
- bool FullMatch(const StringPiece& text,
- const Arg& ptr1 = no_arg,
- const Arg& ptr2 = no_arg,
- const Arg& ptr3 = no_arg,
- const Arg& ptr4 = no_arg,
- const Arg& ptr5 = no_arg,
- const Arg& ptr6 = no_arg,
- const Arg& ptr7 = no_arg,
- const Arg& ptr8 = no_arg,
- const Arg& ptr9 = no_arg,
- const Arg& ptr10 = no_arg,
- const Arg& ptr11 = no_arg,
- const Arg& ptr12 = no_arg,
- const Arg& ptr13 = no_arg,
- const Arg& ptr14 = no_arg,
- const Arg& ptr15 = no_arg,
- const Arg& ptr16 = no_arg) const;
+ template<typename ... ARGS>
+ bool FullMatch(const StringPiece & text, ARGS && ...a) const {
+ // create an array with the size of the number of arguments given
+ Arg args[Args<ARGS...>::count()];
+ // initialize the array with the arguments given
+ Args<ARGS...>::arrayify(args, a...);
- bool PartialMatch(const StringPiece& text,
- const Arg& ptr1 = no_arg,
- const Arg& ptr2 = no_arg,
- const Arg& ptr3 = no_arg,
- const Arg& ptr4 = no_arg,
- const Arg& ptr5 = no_arg,
- const Arg& ptr6 = no_arg,
- const Arg& ptr7 = no_arg,
- const Arg& ptr8 = no_arg,
- const Arg& ptr9 = no_arg,
- const Arg& ptr10 = no_arg,
- const Arg& ptr11 = no_arg,
- const Arg& ptr12 = no_arg,
- const Arg& ptr13 = no_arg,
- const Arg& ptr14 = no_arg,
- const Arg& ptr15 = no_arg,
- const Arg& ptr16 = no_arg) const;
+ return DoMatchImpl(text, ANCHOR_BOTH, NULL, args, Args<ARGS...>::count());
+ }
- bool Consume(StringPiece* input,
- const Arg& ptr1 = no_arg,
- const Arg& ptr2 = no_arg,
- const Arg& ptr3 = no_arg,
- const Arg& ptr4 = no_arg,
- const Arg& ptr5 = no_arg,
- const Arg& ptr6 = no_arg,
- const Arg& ptr7 = no_arg,
- const Arg& ptr8 = no_arg,
- const Arg& ptr9 = no_arg,
- const Arg& ptr10 = no_arg,
- const Arg& ptr11 = no_arg,
- const Arg& ptr12 = no_arg,
- const Arg& ptr13 = no_arg,
- const Arg& ptr14 = no_arg,
- const Arg& ptr15 = no_arg,
- const Arg& ptr16 = no_arg) const;
+ template<typename ... ARGS>
+ bool PartialMatch(const StringPiece& text, ARGS && ...a) const {
+ // create an array with the size of the number of arguments given
+ Arg args[Args<ARGS...>::count()];
+ // initialize the array with the arguments given
+ Args<ARGS...>::arrayify(args, a...);
- bool FindAndConsume(StringPiece* input,
- const Arg& ptr1 = no_arg,
- const Arg& ptr2 = no_arg,
- const Arg& ptr3 = no_arg,
- const Arg& ptr4 = no_arg,
- const Arg& ptr5 = no_arg,
- const Arg& ptr6 = no_arg,
- const Arg& ptr7 = no_arg,
- const Arg& ptr8 = no_arg,
- const Arg& ptr9 = no_arg,
- const Arg& ptr10 = no_arg,
- const Arg& ptr11 = no_arg,
- const Arg& ptr12 = no_arg,
- const Arg& ptr13 = no_arg,
- const Arg& ptr14 = no_arg,
- const Arg& ptr15 = no_arg,
- const Arg& ptr16 = no_arg) const;
+ return DoMatchImpl(text, UNANCHORED, NULL, args, Args<ARGS...>::count());
+ }
+
+ template<typename ... ARGS>
+ bool Consume(StringPiece* input, ARGS && ...a) const {
+ // create an array with the size of the number of arguments given
+ Arg args[Args<ARGS...>::count()];
+ // initialize the array with the arguments given
+ Args<ARGS...>::arrayify(args, a...);
+
+ int consumed;
+ if (DoMatchImpl(*input, ANCHOR_START, &consumed, args,
+ Args<ARGS...>::count())) {
+ input->remove_prefix(consumed);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ template<typename ... ARGS>
+ bool FindAndConsume(StringPiece* input, ARGS && ...a) const {
+ Arg args[Args<ARGS...>::count()];
+ Args<ARGS...>::arrayify(args, a...);
+ int consumed;
+ if (DoMatchImpl(*input, UNANCHORED, &consumed, args,
+ Args<ARGS...>::count())) {
+ input->remove_prefix(consumed);
+ return true;
+ } else {
+ return false;
+ }
+ }
bool Replace(const StringPiece& rewrite,
string *str) const;
@@ -640,21 +640,12 @@
bool DoMatch(const StringPiece& text,
Anchor anchor,
int* consumed,
- const Arg* const* args, int n) const;
+ Arg const argsp[], int n) const;
// Return the number of capturing subpatterns, or -1 if the
// regexp wasn't valid on construction.
int NumberOfCapturingGroups() const;
- // The default value for an argument, to indicate the end of the argument
- // list. This must be used only in optional argument defaults. It should NOT
- // be passed explicitly. Some people have tried to use it like this:
- //
- // FullMatch(x, y, &z, no_arg, &w);
- //
- // This is a mistake, and will not work.
- static Arg no_arg;
-
private:
void Init(const string& pattern, const RE_Options* options);
@@ -675,34 +666,30 @@
int startpos,
Anchor anchor,
bool empty_ok,
- int *vec,
- int vecsize) const;
+ pcre2_match_data_ptr & match_data) const;
// Append the "rewrite" string, with backslash subsitutions from "text"
// and "vec", to string "out".
bool Rewrite(string *out,
const StringPiece& rewrite,
const StringPiece& text,
- int *vec,
- int veclen) const;
+ pcre2_match_data_ptr const & match_data) const;
// internal implementation for DoMatch
bool DoMatchImpl(const StringPiece& text,
Anchor anchor,
int* consumed,
- const Arg* const args[],
- int n,
- int* vec,
- int vecsize) const;
+ const Arg args[],
+ int n) const;
// Compile the regexp for the specified anchoring mode
- pcre* Compile(Anchor anchor);
+ pcre2_code * Compile(Anchor anchor);
string pattern_;
RE_Options options_;
- pcre* re_full_; // For full matches
- pcre* re_partial_; // For partial matches
- const string* error_; // Error indicator (or points to empty string)
+ pcre2_code* re_full_; // For full matches
+ pcre2_code* re_partial_; // For partial matches
+ string error_; // Error indicator
};
} // namespace pcrecpp
diff --git a/pcrecpp/include/pcrecpparg.h b/pcrecpp/include/pcrecpparg.h
index b4f9c3f..0a1713f 100644
--- a/pcrecpp/include/pcrecpparg.h
+++ b/pcrecpp/include/pcrecpparg.h
@@ -35,7 +35,7 @@
#include <stdlib.h> // for NULL
#include <string>
-#include <pcre.h>
+#include <pcre2.h>
namespace pcrecpp {
@@ -54,7 +54,7 @@
}
};
-class PCRECPP_EXP_DEFN Arg {
+class Arg {
public:
// Empty constructor so we can declare arrays of Arg
Arg();
@@ -168,6 +168,40 @@
#undef PCRE_SET_OR_CLEAR
#undef MAKE_INTEGER_PARSER
+template<typename ARG>
+inline Arg wrap_arg(ARG && any) {
+ return Arg(any);
+}
+
+inline Arg const & wrap_arg(Arg const & arg) {
+ return arg;
+}
+
+template<typename ... ARGS>
+struct Args;
+
+template<typename HEAD, typename ... TAIL>
+struct Args<HEAD, TAIL...> {
+ typedef Args<TAIL...> next;
+ constexpr static unsigned count() {
+ return 1 + next::count();
+ }
+ template<typename _HEAD, typename ... _TAIL>
+ inline static void arrayify(Arg * ptr, _HEAD && head, _TAIL && ... tail) {
+ *ptr++ = wrap_arg(head);
+ next::arrayify(ptr, tail...);
+ }
+};
+
+template<>
+struct Args<> {
+ constexpr static unsigned count() {
+ return 0;
+ }
+ inline static void arrayify(Arg *) {
+ }
+};
+
} // namespace pcrecpp
diff --git a/pcrecpp/pcre_scanner.cc b/pcrecpp/pcre_scanner.cc
index 6be2be6..2887d6b 100644
--- a/pcrecpp/pcre_scanner.cc
+++ b/pcrecpp/pcre_scanner.cc
@@ -29,10 +29,6 @@
//
// Author: Sanjay Ghemawat
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include <vector>
#include <assert.h>
@@ -130,15 +126,6 @@
}
-bool Scanner::Consume(const RE& re,
- const Arg& arg0,
- const Arg& arg1,
- const Arg& arg2) {
- const bool result = re.Consume(&input_, arg0, arg1, arg2);
- if (result && should_skip_) ConsumeSkip();
- return result;
-}
-
// helper function to consume *skip_ and honour save_comments_
void Scanner::ConsumeSkip() {
const char* start_data = input_.data();
diff --git a/pcrecpp/pcre_stringpiece.cc b/pcrecpp/pcre_stringpiece.cc
index 67c0f1f..599e466 100644
--- a/pcrecpp/pcre_stringpiece.cc
+++ b/pcrecpp/pcre_stringpiece.cc
@@ -30,10 +30,6 @@
// Author: wilsonh@google.com (Wilson Hsieh)
//
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include <iostream>
#include "pcrecpp_internal.h"
#include "pcre_stringpiece.h"
diff --git a/pcrecpp/pcrecpp.cc b/pcrecpp/pcrecpp.cc
index c595cbc..2c37c44 100644
--- a/pcrecpp/pcrecpp.cc
+++ b/pcrecpp/pcrecpp.cc
@@ -29,10 +29,6 @@
//
// Author: Sanjay Ghemawat
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
@@ -44,39 +40,13 @@
#include <algorithm>
#include "pcrecpp_internal.h"
-#include "pcre.h"
+#include "pcre2.h"
#include "pcrecpp.h"
#include "pcre_stringpiece.h"
namespace pcrecpp {
-// Maximum number of args we can set
-static const int kMaxArgs = 16;
-static const int kVecSize = (1 + kMaxArgs) * 3; // results + PCRE workspace
-
-// Special object that stands-in for no argument
-Arg RE::no_arg((void*)NULL);
-
-// This is for ABI compatibility with old versions of pcre (pre-7.6),
-// which defined a global no_arg variable instead of putting it in the
-// RE class. This works on GCC >= 3, at least. It definitely works
-// for ELF, but may not for other object formats (Mach-O, for
-// instance, does not support aliases.) We could probably have a more
-// inclusive test if we ever needed it. (Note that not only the
-// __attribute__ syntax, but also __USER_LABEL_PREFIX__, are
-// gnu-specific.)
-#if defined(__GNUC__) && __GNUC__ >= 3 && defined(__ELF__)
-# define ULP_AS_STRING(x) ULP_AS_STRING_INTERNAL(x)
-# define ULP_AS_STRING_INTERNAL(x) #x
-# define USER_LABEL_PREFIX_STR ULP_AS_STRING(__USER_LABEL_PREFIX__)
-extern Arg no_arg
- __attribute__((alias(USER_LABEL_PREFIX_STR "_ZN7pcrecpp2RE6no_argE")));
-#endif
-
-// If a regular expression has no error, its error_ field points here
-static const string empty_string;
-
// If the user doesn't ask for any options, we just use this one
static RE_Options default_options;
@@ -87,7 +57,7 @@
} else {
options_ = *options;
}
- error_ = &empty_string;
+ error_ = "";
re_full_ = NULL;
re_partial_ = NULL;
@@ -98,9 +68,9 @@
}
void RE::Cleanup() {
- if (re_full_ != NULL) (*pcre_free)(re_full_);
- if (re_partial_ != NULL) (*pcre_free)(re_partial_);
- if (error_ != &empty_string) delete error_;
+ if (re_full_ != NULL) pcre2_code_free(re_full_);
+ if (re_partial_ != NULL) pcre2_code_free(re_partial_);
+ error_ = "";
}
@@ -108,11 +78,38 @@
Cleanup();
}
+static void format_pcre_error(int error, string & str) {
+ PCRE2_UCHAR8 buffer[256];
+ auto rc = pcre2_get_error_message(error, buffer, 256);
+ str.assign(reinterpret_cast<string::value_type*>(buffer));
+ if (rc == PCRE2_ERROR_NOMEMORY) {
+ str.append("...");
+ }
+}
-pcre* RE::Compile(Anchor anchor) {
+pcre2_code* RE::Compile(Anchor anchor) {
// First, convert RE_Options into pcre options
int pcre_options = 0;
pcre_options = options_.all_options();
+ typedef std::unique_ptr<pcre2_compile_context,
+ decltype(pcre2_compile_context_free)*> compile_context_ptr;
+ compile_context_ptr compile_context(NULL, pcre2_compile_context_free);
+
+ // As of pcre2 the newline mode must be passed through the compile context.
+ // So we only need one if the newline mode is actually set.
+ if (options_.newline_mode()) {
+ compile_context = compile_context_ptr(pcre2_compile_context_create(NULL),
+ pcre2_compile_context_free);
+ if (!compile_context) {
+ error_ = "Unable to allocate memory for pcre2_compile_congext";
+ return NULL;
+ }
+ if (pcre2_set_newline(compile_context.get(),
+ options_.newline_mode()) == PCRE2_ERROR_BADDATA) {
+ error_ = "REOptions: bad newline mode given";
+ return NULL;
+ }
+ }
// Special treatment for anchoring. This is needed because at
// runtime pcre only provides an option for anchoring at the
@@ -126,265 +123,71 @@
// ANCHOR_BOTH Tack a "\z" to the end of the original pattern
// and use a pcre anchored match.
- const char* compile_error;
- int eoffset;
- pcre* re;
+ int compile_error;
+ PCRE2_SIZE eoffset;
+ pcre2_code* re;
if (anchor != ANCHOR_BOTH) {
- re = pcre_compile(pattern_.c_str(), pcre_options,
- &compile_error, &eoffset, NULL);
+ re = pcre2_compile(reinterpret_cast<PCRE2_SPTR>(pattern_.c_str()),
+ pattern_.length(), pcre_options, &compile_error,
+ &eoffset, compile_context.get());
} else {
// Tack a '\z' at the end of RE. Parenthesize it first so that
// the '\z' applies to all top-level alternatives in the regexp.
string wrapped = "(?:"; // A non-counting grouping operator
wrapped += pattern_;
wrapped += ")\\z";
- re = pcre_compile(wrapped.c_str(), pcre_options,
- &compile_error, &eoffset, NULL);
+ re = pcre2_compile(reinterpret_cast<PCRE2_SPTR>(wrapped.c_str()),
+ wrapped.length(), pcre_options, &compile_error, &eoffset,
+ compile_context.get());
}
if (re == NULL) {
- if (error_ == &empty_string) error_ = new string(compile_error);
+ format_pcre_error(compile_error, error_);
}
return re;
}
/***** Matching interfaces *****/
-bool RE::FullMatch(const StringPiece& text,
- const Arg& ptr1,
- const Arg& ptr2,
- const Arg& ptr3,
- const Arg& ptr4,
- const Arg& ptr5,
- const Arg& ptr6,
- const Arg& ptr7,
- const Arg& ptr8,
- const Arg& ptr9,
- const Arg& ptr10,
- const Arg& ptr11,
- const Arg& ptr12,
- const Arg& ptr13,
- const Arg& ptr14,
- const Arg& ptr15,
- const Arg& ptr16) const {
- const Arg* args[kMaxArgs];
- int n = 0;
- if (&ptr1 == &no_arg) goto done; args[n++] = &ptr1;
- if (&ptr2 == &no_arg) goto done; args[n++] = &ptr2;
- if (&ptr3 == &no_arg) goto done; args[n++] = &ptr3;
- if (&ptr4 == &no_arg) goto done; args[n++] = &ptr4;
- if (&ptr5 == &no_arg) goto done; args[n++] = &ptr5;
- if (&ptr6 == &no_arg) goto done; args[n++] = &ptr6;
- if (&ptr7 == &no_arg) goto done; args[n++] = &ptr7;
- if (&ptr8 == &no_arg) goto done; args[n++] = &ptr8;
- if (&ptr9 == &no_arg) goto done; args[n++] = &ptr9;
- if (&ptr10 == &no_arg) goto done; args[n++] = &ptr10;
- if (&ptr11 == &no_arg) goto done; args[n++] = &ptr11;
- if (&ptr12 == &no_arg) goto done; args[n++] = &ptr12;
- if (&ptr13 == &no_arg) goto done; args[n++] = &ptr13;
- if (&ptr14 == &no_arg) goto done; args[n++] = &ptr14;
- if (&ptr15 == &no_arg) goto done; args[n++] = &ptr15;
- if (&ptr16 == &no_arg) goto done; args[n++] = &ptr16;
- done:
-
- int consumed;
- int vec[kVecSize];
- return DoMatchImpl(text, ANCHOR_BOTH, &consumed, args, n, vec, kVecSize);
-}
-
-bool RE::PartialMatch(const StringPiece& text,
- const Arg& ptr1,
- const Arg& ptr2,
- const Arg& ptr3,
- const Arg& ptr4,
- const Arg& ptr5,
- const Arg& ptr6,
- const Arg& ptr7,
- const Arg& ptr8,
- const Arg& ptr9,
- const Arg& ptr10,
- const Arg& ptr11,
- const Arg& ptr12,
- const Arg& ptr13,
- const Arg& ptr14,
- const Arg& ptr15,
- const Arg& ptr16) const {
- const Arg* args[kMaxArgs];
- int n = 0;
- if (&ptr1 == &no_arg) goto done; args[n++] = &ptr1;
- if (&ptr2 == &no_arg) goto done; args[n++] = &ptr2;
- if (&ptr3 == &no_arg) goto done; args[n++] = &ptr3;
- if (&ptr4 == &no_arg) goto done; args[n++] = &ptr4;
- if (&ptr5 == &no_arg) goto done; args[n++] = &ptr5;
- if (&ptr6 == &no_arg) goto done; args[n++] = &ptr6;
- if (&ptr7 == &no_arg) goto done; args[n++] = &ptr7;
- if (&ptr8 == &no_arg) goto done; args[n++] = &ptr8;
- if (&ptr9 == &no_arg) goto done; args[n++] = &ptr9;
- if (&ptr10 == &no_arg) goto done; args[n++] = &ptr10;
- if (&ptr11 == &no_arg) goto done; args[n++] = &ptr11;
- if (&ptr12 == &no_arg) goto done; args[n++] = &ptr12;
- if (&ptr13 == &no_arg) goto done; args[n++] = &ptr13;
- if (&ptr14 == &no_arg) goto done; args[n++] = &ptr14;
- if (&ptr15 == &no_arg) goto done; args[n++] = &ptr15;
- if (&ptr16 == &no_arg) goto done; args[n++] = &ptr16;
- done:
-
- int consumed;
- int vec[kVecSize];
- return DoMatchImpl(text, UNANCHORED, &consumed, args, n, vec, kVecSize);
-}
-
-bool RE::Consume(StringPiece* input,
- const Arg& ptr1,
- const Arg& ptr2,
- const Arg& ptr3,
- const Arg& ptr4,
- const Arg& ptr5,
- const Arg& ptr6,
- const Arg& ptr7,
- const Arg& ptr8,
- const Arg& ptr9,
- const Arg& ptr10,
- const Arg& ptr11,
- const Arg& ptr12,
- const Arg& ptr13,
- const Arg& ptr14,
- const Arg& ptr15,
- const Arg& ptr16) const {
- const Arg* args[kMaxArgs];
- int n = 0;
- if (&ptr1 == &no_arg) goto done; args[n++] = &ptr1;
- if (&ptr2 == &no_arg) goto done; args[n++] = &ptr2;
- if (&ptr3 == &no_arg) goto done; args[n++] = &ptr3;
- if (&ptr4 == &no_arg) goto done; args[n++] = &ptr4;
- if (&ptr5 == &no_arg) goto done; args[n++] = &ptr5;
- if (&ptr6 == &no_arg) goto done; args[n++] = &ptr6;
- if (&ptr7 == &no_arg) goto done; args[n++] = &ptr7;
- if (&ptr8 == &no_arg) goto done; args[n++] = &ptr8;
- if (&ptr9 == &no_arg) goto done; args[n++] = &ptr9;
- if (&ptr10 == &no_arg) goto done; args[n++] = &ptr10;
- if (&ptr11 == &no_arg) goto done; args[n++] = &ptr11;
- if (&ptr12 == &no_arg) goto done; args[n++] = &ptr12;
- if (&ptr13 == &no_arg) goto done; args[n++] = &ptr13;
- if (&ptr14 == &no_arg) goto done; args[n++] = &ptr14;
- if (&ptr15 == &no_arg) goto done; args[n++] = &ptr15;
- if (&ptr16 == &no_arg) goto done; args[n++] = &ptr16;
- done:
-
- int consumed;
- int vec[kVecSize];
- if (DoMatchImpl(*input, ANCHOR_START, &consumed,
- args, n, vec, kVecSize)) {
- input->remove_prefix(consumed);
- return true;
- } else {
- return false;
- }
-}
-
-bool RE::FindAndConsume(StringPiece* input,
- const Arg& ptr1,
- const Arg& ptr2,
- const Arg& ptr3,
- const Arg& ptr4,
- const Arg& ptr5,
- const Arg& ptr6,
- const Arg& ptr7,
- const Arg& ptr8,
- const Arg& ptr9,
- const Arg& ptr10,
- const Arg& ptr11,
- const Arg& ptr12,
- const Arg& ptr13,
- const Arg& ptr14,
- const Arg& ptr15,
- const Arg& ptr16) const {
- const Arg* args[kMaxArgs];
- int n = 0;
- if (&ptr1 == &no_arg) goto done; args[n++] = &ptr1;
- if (&ptr2 == &no_arg) goto done; args[n++] = &ptr2;
- if (&ptr3 == &no_arg) goto done; args[n++] = &ptr3;
- if (&ptr4 == &no_arg) goto done; args[n++] = &ptr4;
- if (&ptr5 == &no_arg) goto done; args[n++] = &ptr5;
- if (&ptr6 == &no_arg) goto done; args[n++] = &ptr6;
- if (&ptr7 == &no_arg) goto done; args[n++] = &ptr7;
- if (&ptr8 == &no_arg) goto done; args[n++] = &ptr8;
- if (&ptr9 == &no_arg) goto done; args[n++] = &ptr9;
- if (&ptr10 == &no_arg) goto done; args[n++] = &ptr10;
- if (&ptr11 == &no_arg) goto done; args[n++] = &ptr11;
- if (&ptr12 == &no_arg) goto done; args[n++] = &ptr12;
- if (&ptr13 == &no_arg) goto done; args[n++] = &ptr13;
- if (&ptr14 == &no_arg) goto done; args[n++] = &ptr14;
- if (&ptr15 == &no_arg) goto done; args[n++] = &ptr15;
- if (&ptr16 == &no_arg) goto done; args[n++] = &ptr16;
- done:
-
- int consumed;
- int vec[kVecSize];
- if (DoMatchImpl(*input, UNANCHORED, &consumed,
- args, n, vec, kVecSize)) {
- input->remove_prefix(consumed);
- return true;
- } else {
- return false;
- }
-}
-
bool RE::Replace(const StringPiece& rewrite,
string *str) const {
- int vec[kVecSize];
- int matches = TryMatch(*str, 0, UNANCHORED, true, vec, kVecSize);
+ pcre2_match_data_ptr match_data;
+ int matches = TryMatch(*str, 0, UNANCHORED, true, match_data);
if (matches == 0)
return false;
string s;
- if (!Rewrite(&s, rewrite, *str, vec, matches))
+ if (!Rewrite(&s, rewrite, *str, match_data))
return false;
+ auto vec = pcre2_get_ovector_pointer(match_data.get());
+
assert(vec[0] >= 0);
assert(vec[1] >= 0);
str->replace(vec[0], vec[1] - vec[0], s);
return true;
}
-// Returns PCRE_NEWLINE_CRLF, PCRE_NEWLINE_CR, or PCRE_NEWLINE_LF.
-// Note that PCRE_NEWLINE_CRLF is defined to be P_N_CR | P_N_LF.
-// Modified by PH to add PCRE_NEWLINE_ANY and PCRE_NEWLINE_ANYCRLF.
-
-static int NewlineMode(int pcre_options) {
- // TODO: if we can make it threadsafe, cache this var
- int newline_mode = 0;
- /* if (newline_mode) return newline_mode; */ // do this once it's cached
- if (pcre_options & (PCRE_NEWLINE_CRLF|PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|
- PCRE_NEWLINE_ANY|PCRE_NEWLINE_ANYCRLF)) {
- newline_mode = (pcre_options &
- (PCRE_NEWLINE_CRLF|PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|
- PCRE_NEWLINE_ANY|PCRE_NEWLINE_ANYCRLF));
- } else {
- int newline;
- pcre_config(PCRE_CONFIG_NEWLINE, &newline);
- if (newline == 10)
- newline_mode = PCRE_NEWLINE_LF;
- else if (newline == 13)
- newline_mode = PCRE_NEWLINE_CR;
- else if (newline == 3338)
- newline_mode = PCRE_NEWLINE_CRLF;
- else if (newline == -1)
- newline_mode = PCRE_NEWLINE_ANY;
- else if (newline == -2)
- newline_mode = PCRE_NEWLINE_ANYCRLF;
- else
- assert(NULL == "Unexpected return value from pcre_config(NEWLINE)");
+static bool is_multi_char_newline_mode(int value) {
+ switch (value) {
+ case PCRE2_NEWLINE_CR:
+ case PCRE2_NEWLINE_LF:
+ return false;
+ case PCRE2_NEWLINE_CRLF:
+ case PCRE2_NEWLINE_ANY:
+ case PCRE2_NEWLINE_ANYCRLF:
+ return true;
+ default:
+ return false;
}
- return newline_mode;
}
int RE::GlobalReplace(const StringPiece& rewrite,
string *str) const {
int count = 0;
- int vec[kVecSize];
string out;
int start = 0;
bool last_match_was_empty_string = false;
+ pcre2_match_data_ptr match_data;
while (start <= static_cast<int>(str->length())) {
// If the previous match was for the empty string, we shouldn't
@@ -399,19 +202,17 @@
// perl -le '$_ = "aa"; s/b*|aa/@/g; print'
int matches;
if (last_match_was_empty_string) {
- matches = TryMatch(*str, start, ANCHOR_START, false, vec, kVecSize);
+ matches = TryMatch(*str, start, ANCHOR_START, false, match_data);
if (matches <= 0) {
int matchend = start + 1; // advance one character.
// If the current char is CR and we're in CRLF mode, skip LF too.
- // Note it's better to call pcre_fullinfo() than to examine
- // all_options(), since options_ could have changed bewteen
+ // Note it's better to call pcre2_pattern_info() than to examine
+ // all_options(), since options_ could have changed between
// compile-time and now, but this is simpler and safe enough.
// Modified by PH to add ANY and ANYCRLF.
if (matchend < static_cast<int>(str->length()) &&
(*str)[start] == '\r' && (*str)[matchend] == '\n' &&
- (NewlineMode(options_.all_options()) == PCRE_NEWLINE_CRLF ||
- NewlineMode(options_.all_options()) == PCRE_NEWLINE_ANY ||
- NewlineMode(options_.all_options()) == PCRE_NEWLINE_ANYCRLF)) {
+ is_multi_char_newline_mode(options_.newline_mode())) {
matchend++;
}
// We also need to advance more than one char if we're in utf8 mode.
@@ -429,15 +230,16 @@
continue;
}
} else {
- matches = TryMatch(*str, start, UNANCHORED, true, vec, kVecSize);
+ matches = TryMatch(*str, start, UNANCHORED, true, match_data);
if (matches <= 0)
break;
}
+ auto vec = pcre2_get_ovector_pointer(match_data.get());
int matchstart = vec[0], matchend = vec[1];
assert(matchstart >= start);
assert(matchend >= matchstart);
out.append(*str, start, matchstart - start);
- Rewrite(&out, rewrite, *str, vec, matches);
+ Rewrite(&out, rewrite, *str, match_data);
start = matchend;
count++;
last_match_was_empty_string = (matchstart == matchend);
@@ -455,12 +257,12 @@
bool RE::Extract(const StringPiece& rewrite,
const StringPiece& text,
string *out) const {
- int vec[kVecSize];
- int matches = TryMatch(text, 0, UNANCHORED, true, vec, kVecSize);
+ pcre2_match_data_ptr match_data;
+ int matches = TryMatch(text, 0, UNANCHORED, true, match_data);
if (matches == 0)
return false;
out->erase();
- return Rewrite(out, rewrite, text, vec, matches);
+ return Rewrite(out, rewrite, text, match_data);
}
/*static*/ string RE::QuoteMeta(const StringPiece& unquoted) {
@@ -498,79 +300,84 @@
}
/***** Actual matching and rewriting code *****/
-
int RE::TryMatch(const StringPiece& text,
int startpos,
Anchor anchor,
bool empty_ok,
- int *vec,
- int vecsize) const {
- pcre* re = (anchor == ANCHOR_BOTH) ? re_full_ : re_partial_;
+ pcre2_match_data_ptr & match_data) const {
+ typedef std::unique_ptr<pcre2_match_context,
+ decltype(pcre2_match_context_free)*> match_context_ptr;
+
+ pcre2_code* re = (anchor == ANCHOR_BOTH) ? re_full_ : re_partial_;
if (re == NULL) {
//fprintf(stderr, "Matching against invalid re: %s\n", error_->c_str());
return 0;
}
+ match_context_ptr match_context = match_context_ptr(
+ pcre2_match_context_create(NULL),
+ pcre2_match_context_free);
+ if (!match_context)
+ return 0;
- pcre_extra extra = { 0, 0, 0, 0, 0, 0, 0, 0 };
if (options_.match_limit() > 0) {
- extra.flags |= PCRE_EXTRA_MATCH_LIMIT;
- extra.match_limit = options_.match_limit();
+ pcre2_set_match_limit(match_context.get(), options_.match_limit());
}
if (options_.match_limit_recursion() > 0) {
- extra.flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
- extra.match_limit_recursion = options_.match_limit_recursion();
+ pcre2_set_recursion_limit(match_context.get(),
+ options_.match_limit_recursion());
+ }
+
+ match_data = pcre2_match_data_ptr(
+ pcre2_match_data_create_from_pattern(re, NULL),
+ pcre2_match_data_free);
+ if (!match_data) {
+ return 0;
}
// int options = 0;
// Changed by PH as a result of bugzilla #1288
- int options = (options_.all_options() & PCRE_NO_UTF8_CHECK);
+ int options = (options_.all_options() & PCRE2_NO_UTF_CHECK);
if (anchor != UNANCHORED)
- options |= PCRE_ANCHORED;
+ options |= PCRE2_ANCHORED;
if (!empty_ok)
- options |= PCRE_NOTEMPTY;
+ options |= PCRE2_NOTEMPTY;
- int rc = pcre_exec(re, // The regular expression object
- &extra,
- (text.data() == NULL) ? "" : text.data(),
- text.size(),
- startpos,
- options,
- vec,
- vecsize);
+ int rc = pcre2_match(
+ re, reinterpret_cast<PCRE2_SPTR>((text.empty()) ? "" : text.data()),
+ text.size(), startpos, options, match_data.get(), match_context.get());
// Handle errors
- if (rc == PCRE_ERROR_NOMATCH) {
+ if (rc == PCRE2_ERROR_NOMATCH) {
+ return 0;
+ }
+ if (rc == PCRE2_ERROR_PARTIAL) {
+ // not sure what to do with partial yet
return 0;
} else if (rc < 0) {
- //fprintf(stderr, "Unexpected return code: %d when matching '%s'\n",
- // re, pattern_.c_str());
+ // For any other error condition also return 0.
return 0;
- } else if (rc == 0) {
- // pcre_exec() returns 0 as a special case when the number of
- // capturing subpatterns exceeds the size of the vector.
- // When this happens, there is a match and the output vector
- // is filled, but we miss out on the positions of the extra subpatterns.
- rc = vecsize / 2;
}
- return rc;
+ return rc; // return number of matches found
}
bool RE::DoMatchImpl(const StringPiece& text,
Anchor anchor,
int* consumed,
- const Arg* const* args,
- int n,
- int* vec,
- int vecsize) const {
- assert((1 + n) * 3 <= vecsize); // results + PCRE workspace
- int matches = TryMatch(text, 0, anchor, true, vec, vecsize);
+ const Arg* args,
+ int n) const {
+ pcre2_match_data_ptr match_data;
+ int matches = TryMatch(text, 0, anchor, true, match_data);
assert(matches >= 0); // TryMatch never returns negatives
if (matches == 0)
return false;
- *consumed = vec[1];
+ auto vec = pcre2_get_ovector_pointer(match_data.get());
+
+ // allow for NULL
+ if (consumed != NULL)
+ *consumed = vec[1];
if (n == 0 || args == NULL) {
// We are not interested in results
@@ -588,7 +395,7 @@
for (int i = 0; i < n; i++) {
const int start = vec[2*(i+1)];
const int limit = vec[2*(i+1)+1];
- if (!args[i]->Parse(text.data() + start, limit-start)) {
+ if (!args[i].Parse(text.data() + start, limit - start)) {
// TODO: Should we indicate what the error was?
return false;
}
@@ -600,27 +407,25 @@
bool RE::DoMatch(const StringPiece& text,
Anchor anchor,
int* consumed,
- const Arg* const args[],
+ Arg const args[],
int n) const {
assert(n >= 0);
- size_t const vecsize = (1 + n) * 3; // results + PCRE workspace
- // (as for kVecSize)
- int space[21]; // use stack allocation for small vecsize (common case)
- int* vec = vecsize <= 21 ? space : new int[vecsize];
- bool retval = DoMatchImpl(text, anchor, consumed, args, n, vec, (int)vecsize);
- if (vec != space) delete [] vec;
+ bool retval = DoMatchImpl(text, anchor, consumed, args, n);
return retval;
}
bool RE::Rewrite(string *out, const StringPiece &rewrite,
- const StringPiece &text, int *vec, int veclen) const {
+ const StringPiece &text,
+ pcre2_match_data_ptr const & match_data) const {
+ auto veclen = pcre2_get_ovector_count(match_data.get());
+ auto vec = pcre2_get_ovector_pointer(match_data.get());
for (const char *s = rewrite.data(), *end = s + rewrite.size();
s < end; s++) {
int c = *s;
if (c == '\\') {
c = *++s;
if (isdigit(c)) {
- int n = (c - '0');
+ decltype(veclen) n = (c - '0');
if (n >= veclen) {
//fprintf(stderr, requested group %d in regexp %.*s\n",
// n, rewrite.size(), rewrite.data());
@@ -649,10 +454,8 @@
if (re_partial_ == NULL) return -1;
int result;
- int pcre_retval = pcre_fullinfo(re_partial_, // The regular expression object
- NULL, // We did not study the pattern
- PCRE_INFO_CAPTURECOUNT,
- &result);
+ int pcre_retval = pcre2_pattern_info(re_partial_, PCRE2_INFO_CAPTURECOUNT,
+ &result);
assert(pcre_retval == 0);
return result;
}
diff --git a/pcrecpp/pcrecpp_unittest.cc b/pcrecpp/pcrecpp_unittest.cc
index 92cae8f..67f2398 100644
--- a/pcrecpp/pcrecpp_unittest.cc
+++ b/pcrecpp/pcrecpp_unittest.cc
@@ -333,7 +333,8 @@
#endif
for (const ReplaceTest *t = tests; t->original != NULL; ++t) {
- RE re(t->regexp, RE_Options(PCRE_NEWLINE_CRLF).set_utf8(support_utf8));
+ RE re(t->regexp, RE_Options().set_newline_mode(PCRE2_NEWLINE_CRLF)
+ .set_utf(support_utf8));
assert(re.error().empty());
string one(t->original);
CHECK(re.Replace(t->rewrite, &one));
@@ -346,14 +347,16 @@
// One final test: test \r\n replacement when we're not in CRLF mode
{
- RE re("b*", RE_Options(PCRE_NEWLINE_CR).set_utf8(support_utf8));
+ RE re("b*", RE_Options().set_newline_mode(PCRE2_NEWLINE_CR)
+ .set_utf(support_utf8));
assert(re.error().empty());
string all("aa\r\naa\r\n");
CHECK_EQ(re.GlobalReplace("bb", &all), 9);
CHECK_EQ(all, string("bbabbabb\rbb\nbbabbabb\rbb\nbb"));
}
{
- RE re("b*", RE_Options(PCRE_NEWLINE_LF).set_utf8(support_utf8));
+ RE re("b*", RE_Options().set_newline_mode(PCRE2_NEWLINE_LF)
+ .set_utf(support_utf8));
assert(re.error().empty());
string all("aa\r\naa\r\n");
CHECK_EQ(re.GlobalReplace("bb", &all), 9);
@@ -662,17 +665,6 @@
TestOneOption("DOLLAR_ENDONLY 2", "world$", str, options2.set_dollar_endonly(true), false, false);
}
-static void Test_EXTRA() {
- RE_Options options;
- const char *str = "HELLO";
-
- options.set_extra(true);
- TestOneOption("EXTRA 1", "\\HELL\\O", str, options, true, false );
- TestOneOption("EXTRA 2", "\\HELL\\O", str, RE_Options().set_extra(true), true, false );
- options.set_extra(false);
- TestOneOption("no EXTRA", "\\HELL\\O", str, options, true );
-}
-
static void Test_EXTENDED() {
RE_Options options;
RE_Options options2;
@@ -738,18 +730,18 @@
static void Test_all_options() {
const char *str = "HELLO\n" "cruel\n" "world";
RE_Options options;
- options.set_all_options(PCRE_CASELESS | PCRE_DOTALL);
+ options.set_all_options(PCRE2_CASELESS | PCRE2_DOTALL);
TestOneOption("all_options (CASELESS|DOTALL)", "^hello.*WORLD", str , options, false);
options.set_all_options(0);
TestOneOption("all_options (0)", "^hello.*WORLD", str , options, false, false);
- options.set_all_options(PCRE_MULTILINE | PCRE_EXTENDED);
+ options.set_all_options(PCRE2_MULTILINE | PCRE2_EXTENDED);
TestOneOption("all_options (MULTILINE|EXTENDED)", " ^ c r u e l $ ", str, options, false);
TestOneOption("all_options (MULTILINE|EXTENDED) with constructor",
" ^ c r u e l $ ",
str,
- RE_Options(PCRE_MULTILINE | PCRE_EXTENDED),
+ RE_Options(PCRE2_MULTILINE | PCRE2_EXTENDED),
false);
TestOneOption("all_options (MULTILINE|EXTENDED) with concatenation",
@@ -774,7 +766,6 @@
Test_EXTENDED();
Test_NO_AUTO_CAPTURE();
Test_UNGREEDY();
- Test_EXTRA();
Test_all_options();
}