#ifndef RE2_RE2_H_
#define RE2_RE2_H_
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <map>
#include <mutex>
#include <string>
#include <type_traits>
#include <vector>
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
#include <string_view>
namespace re2 {
class Prog;
class Regexp;
}
namespace re2 {
class RE2 {
public:
class Arg;
class Options;
class Set;
enum ErrorCode {
NoError = 0,
ErrorInternal,
ErrorBadEscape, ErrorBadCharClass, ErrorBadCharRange, ErrorMissingBracket, ErrorMissingParen, ErrorUnexpectedParen, ErrorTrailingBackslash, ErrorRepeatArgument, ErrorRepeatSize, ErrorRepeatOp, ErrorBadPerlOp, ErrorBadUTF8, ErrorBadNamedCapture, ErrorPatternTooLarge };
enum CannedOptions {
DefaultOptions = 0,
Latin1, POSIX, Quiet };
#ifndef SWIG
RE2(const char* pattern);
RE2(const std::string& pattern);
#endif
RE2(std::string_view pattern);
RE2(std::string_view pattern, const Options& options);
~RE2();
bool ok() const { return error_code() == NoError; }
const std::string& pattern() const { return pattern_; }
const std::string& error() const { return *error_; }
ErrorCode error_code() const { return error_code_; }
const std::string& error_arg() const { return error_arg_; }
int ProgramSize() const;
int ReverseProgramSize() const;
int ProgramFanout(std::vector<int>* histogram) const;
int ReverseProgramFanout(std::vector<int>* histogram) const;
re2::Regexp* Regexp() const { return entire_regexp_; }
static bool FullMatchN(std::string_view text, const RE2& re,
const Arg* const args[], int n);
static bool PartialMatchN(std::string_view text, const RE2& re,
const Arg* const args[], int n);
static bool ConsumeN(std::string_view* input, const RE2& re,
const Arg* const args[], int n);
static bool FindAndConsumeN(std::string_view* input, const RE2& re,
const Arg* const args[], int n);
#ifndef SWIG
private:
template <typename F, typename SP>
static inline bool Apply(F f, SP sp, const RE2& re) {
return f(sp, re, NULL, 0);
}
template <typename F, typename SP, typename... A>
static inline bool Apply(F f, SP sp, const RE2& re, const A&... a) {
const Arg* const args[] = {&a...};
const int n = sizeof...(a);
return f(sp, re, args, n);
}
public:
template <typename... A>
static bool FullMatch(std::string_view text, const RE2& re, A&&... a) {
return Apply(FullMatchN, text, re, Arg(std::forward<A>(a))...);
}
template <typename... A>
static bool PartialMatch(std::string_view text, const RE2& re, A&&... a) {
return Apply(PartialMatchN, text, re, Arg(std::forward<A>(a))...);
}
template <typename... A>
static bool Consume(std::string_view* input, const RE2& re, A&&... a) {
return Apply(ConsumeN, input, re, Arg(std::forward<A>(a))...);
}
template <typename... A>
static bool FindAndConsume(std::string_view* input, const RE2& re, A&&... a) {
return Apply(FindAndConsumeN, input, re, Arg(std::forward<A>(a))...);
}
#endif
static bool Replace(std::string* str,
const RE2& re,
std::string_view rewrite);
static int GlobalReplace(std::string* str,
const RE2& re,
std::string_view rewrite);
static bool Extract(std::string_view text,
const RE2& re,
std::string_view rewrite,
std::string* out);
static std::string QuoteMeta(std::string_view unquoted);
bool PossibleMatchRange(std::string* min, std::string* max,
int maxlen) const;
enum Anchor {
UNANCHORED, ANCHOR_START, ANCHOR_BOTH };
int NumberOfCapturingGroups() const { return num_captures_; }
const std::map<std::string, int>& NamedCapturingGroups() const;
const std::map<int, std::string>& CapturingGroupNames() const;
bool Match(std::string_view text,
size_t startpos,
size_t endpos,
Anchor re_anchor,
std::string_view* submatch,
int nsubmatch) const;
bool CheckRewriteString(std::string_view rewrite,
std::string* error) const;
static int MaxSubmatch(std::string_view rewrite);
bool Rewrite(std::string* out,
std::string_view rewrite,
const std::string_view* vec,
int veclen) const;
class Options {
public:
static const int kDefaultMaxMem = 8<<20;
enum Encoding {
EncodingUTF8 = 1,
EncodingLatin1
};
Options() :
encoding_(EncodingUTF8),
posix_syntax_(false),
longest_match_(false),
log_errors_(false),
max_mem_(kDefaultMaxMem),
literal_(false),
never_nl_(false),
dot_nl_(false),
never_capture_(false),
case_sensitive_(true),
perl_classes_(false),
word_boundary_(false),
one_line_(false) {
}
Options(CannedOptions);
Encoding encoding() const { return encoding_; }
void set_encoding(Encoding encoding) { encoding_ = encoding; }
bool posix_syntax() const { return posix_syntax_; }
void set_posix_syntax(bool b) { posix_syntax_ = b; }
bool longest_match() const { return longest_match_; }
void set_longest_match(bool b) { longest_match_ = b; }
bool log_errors() const { return log_errors_; }
void set_log_errors(bool b) { log_errors_ = b; }
int64_t max_mem() const { return max_mem_; }
void set_max_mem(int64_t m) { max_mem_ = m; }
bool literal() const { return literal_; }
void set_literal(bool b) { literal_ = b; }
bool never_nl() const { return never_nl_; }
void set_never_nl(bool b) { never_nl_ = b; }
bool dot_nl() const { return dot_nl_; }
void set_dot_nl(bool b) { dot_nl_ = b; }
bool never_capture() const { return never_capture_; }
void set_never_capture(bool b) { never_capture_ = b; }
bool case_sensitive() const { return case_sensitive_; }
void set_case_sensitive(bool b) { case_sensitive_ = b; }
bool perl_classes() const { return perl_classes_; }
void set_perl_classes(bool b) { perl_classes_ = b; }
bool word_boundary() const { return word_boundary_; }
void set_word_boundary(bool b) { word_boundary_ = b; }
bool one_line() const { return one_line_; }
void set_one_line(bool b) { one_line_ = b; }
void Copy(const Options& src) {
*this = src;
}
int ParseFlags() const;
private:
Encoding encoding_;
bool posix_syntax_;
bool longest_match_;
bool log_errors_;
int64_t max_mem_;
bool literal_;
bool never_nl_;
bool dot_nl_;
bool never_capture_;
bool case_sensitive_;
bool perl_classes_;
bool word_boundary_;
bool one_line_;
};
const Options& options() const { return options_; }
template <typename T>
static Arg CRadix(T* ptr);
template <typename T>
static Arg Hex(T* ptr);
template <typename T>
static Arg Octal(T* ptr);
private:
void Init(std::string_view pattern, const Options& options);
bool DoMatch(std::string_view text,
Anchor re_anchor,
size_t* consumed,
const Arg* const args[],
int n) const;
re2::Prog* ReverseProg() const;
std::string pattern_; Options options_; re2::Regexp* entire_regexp_; const std::string* error_; ErrorCode error_code_; std::string error_arg_; std::string prefix_; bool prefix_foldcase_; re2::Regexp* suffix_regexp_; re2::Prog* prog_; int num_captures_; bool is_one_pass_;
mutable re2::Prog* rprog_;
mutable const std::map<std::string, int>* named_groups_;
mutable const std::map<int, std::string>* group_names_;
mutable std::once_flag rprog_once_;
mutable std::once_flag named_groups_once_;
mutable std::once_flag group_names_once_;
RE2(const RE2&) = delete;
RE2& operator=(const RE2&) = delete;
};
namespace re2_internal {
template <typename T> struct Parse3ary : public std::false_type {};
template <> struct Parse3ary<void> : public std::true_type {};
template <> struct Parse3ary<std::string> : public std::true_type {};
template <> struct Parse3ary<std::string_view> : public std::true_type {};
template <> struct Parse3ary<char> : public std::true_type {};
template <> struct Parse3ary<signed char> : public std::true_type {};
template <> struct Parse3ary<unsigned char> : public std::true_type {};
template <> struct Parse3ary<float> : public std::true_type {};
template <> struct Parse3ary<double> : public std::true_type {};
template <typename T>
bool Parse(const char* str, size_t n, T* dest);
template <typename T> struct Parse4ary : public std::false_type {};
template <> struct Parse4ary<long> : public std::true_type {};
template <> struct Parse4ary<unsigned long> : public std::true_type {};
template <> struct Parse4ary<short> : public std::true_type {};
template <> struct Parse4ary<unsigned short> : public std::true_type {};
template <> struct Parse4ary<int> : public std::true_type {};
template <> struct Parse4ary<unsigned int> : public std::true_type {};
template <> struct Parse4ary<long long> : public std::true_type {};
template <> struct Parse4ary<unsigned long long> : public std::true_type {};
template <typename T>
bool Parse(const char* str, size_t n, T* dest, int radix);
}
class RE2::Arg {
private:
template <typename T>
using CanParse3ary = typename std::enable_if<
re2_internal::Parse3ary<T>::value,
int>::type;
template <typename T>
using CanParse4ary = typename std::enable_if<
re2_internal::Parse4ary<T>::value,
int>::type;
#if !defined(_MSC_VER)
template <typename T>
using CanParseFrom = typename std::enable_if<
std::is_member_function_pointer<
decltype(static_cast<bool (T::*)(const char*, size_t)>(
&T::ParseFrom))>::value,
int>::type;
#endif
public:
Arg() : Arg(nullptr) {}
Arg(std::nullptr_t ptr) : arg_(ptr), parser_(DoNothing) {}
template <typename T, CanParse3ary<T> = 0>
Arg(T* ptr) : arg_(ptr), parser_(DoParse3ary<T>) {}
template <typename T, CanParse4ary<T> = 0>
Arg(T* ptr) : arg_(ptr), parser_(DoParse4ary<T>) {}
#if !defined(_MSC_VER)
template <typename T, CanParseFrom<T> = 0>
Arg(T* ptr) : arg_(ptr), parser_(DoParseFrom<T>) {}
#endif
typedef bool (*Parser)(const char* str, size_t n, void* dest);
template <typename T>
Arg(T* ptr, Parser parser) : arg_(ptr), parser_(parser) {}
bool Parse(const char* str, size_t n) const {
return (*parser_)(str, n, arg_);
}
private:
static bool DoNothing(const char* , size_t , void* ) {
return true;
}
template <typename T>
static bool DoParse3ary(const char* str, size_t n, void* dest) {
return re2_internal::Parse(str, n, reinterpret_cast<T*>(dest));
}
template <typename T>
static bool DoParse4ary(const char* str, size_t n, void* dest) {
return re2_internal::Parse(str, n, reinterpret_cast<T*>(dest), 10);
}
#if !defined(_MSC_VER)
template <typename T>
static bool DoParseFrom(const char* str, size_t n, void* dest) {
if (dest == NULL) return true;
return reinterpret_cast<T*>(dest)->ParseFrom(str, n);
}
#endif
void* arg_;
Parser parser_;
};
template <typename T>
inline RE2::Arg RE2::CRadix(T* ptr) {
return RE2::Arg(ptr, [](const char* str, size_t n, void* dest) -> bool {
return re2_internal::Parse(str, n, reinterpret_cast<T*>(dest), 0);
});
}
template <typename T>
inline RE2::Arg RE2::Hex(T* ptr) {
return RE2::Arg(ptr, [](const char* str, size_t n, void* dest) -> bool {
return re2_internal::Parse(str, n, reinterpret_cast<T*>(dest), 16);
});
}
template <typename T>
inline RE2::Arg RE2::Octal(T* ptr) {
return RE2::Arg(ptr, [](const char* str, size_t n, void* dest) -> bool {
return re2_internal::Parse(str, n, reinterpret_cast<T*>(dest), 8);
});
}
#ifndef SWIG
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 6
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif
class LazyRE2 {
private:
struct NoArg {};
public:
typedef RE2 element_type;
RE2& operator*() const { return *get(); }
RE2* operator->() const { return get(); }
RE2* get() const {
std::call_once(once_, &LazyRE2::Init, this);
return ptr_;
}
const char* pattern_;
RE2::CannedOptions options_;
NoArg barrier_against_excess_initializers_;
mutable RE2* ptr_;
mutable std::once_flag once_;
private:
static void Init(const LazyRE2* lazy_re2) {
lazy_re2->ptr_ = new RE2(lazy_re2->pattern_, lazy_re2->options_);
}
void operator=(const LazyRE2&); };
#endif
namespace hooks {
#define RE2_HAVE_THREAD_LOCAL
#if (defined(__APPLE__) && !(defined(TARGET_OS_OSX) && TARGET_OS_OSX)) || defined(__MINGW32__)
#undef RE2_HAVE_THREAD_LOCAL
#endif
#ifdef RE2_HAVE_THREAD_LOCAL
extern thread_local const RE2* context;
#endif
struct DFAStateCacheReset {
int64_t state_budget;
size_t state_cache_size;
};
struct DFASearchFailure {
};
#define DECLARE_HOOK(type) \
using type##Callback = void(const type&); \
void Set##type##Hook(type##Callback* cb); \
type##Callback* Get##type##Hook();
DECLARE_HOOK(DFAStateCacheReset)
DECLARE_HOOK(DFASearchFailure)
#undef DECLARE_HOOK
}
}
using re2::RE2;
using re2::LazyRE2;
#endif