修改pods
This commit is contained in:
117
Pods/gRPC-C++/third_party/re2/re2/bitmap256.h
generated
vendored
Normal file
117
Pods/gRPC-C++/third_party/re2/re2/bitmap256.h
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
// Copyright 2016 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RE2_BITMAP256_H_
|
||||
#define RE2_BITMAP256_H_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util/util.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
namespace re2 {
|
||||
|
||||
class Bitmap256 {
|
||||
public:
|
||||
Bitmap256() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
// Clears all of the bits.
|
||||
void Clear() {
|
||||
memset(words_, 0, sizeof words_);
|
||||
}
|
||||
|
||||
// Tests the bit with index c.
|
||||
bool Test(int c) const {
|
||||
DCHECK_GE(c, 0);
|
||||
DCHECK_LE(c, 255);
|
||||
|
||||
return (words_[c / 64] & (uint64_t{1} << (c % 64))) != 0;
|
||||
}
|
||||
|
||||
// Sets the bit with index c.
|
||||
void Set(int c) {
|
||||
DCHECK_GE(c, 0);
|
||||
DCHECK_LE(c, 255);
|
||||
|
||||
words_[c / 64] |= (uint64_t{1} << (c % 64));
|
||||
}
|
||||
|
||||
// Finds the next non-zero bit with index >= c.
|
||||
// Returns -1 if no such bit exists.
|
||||
int FindNextSetBit(int c) const;
|
||||
|
||||
private:
|
||||
// Finds the least significant non-zero bit in n.
|
||||
static int FindLSBSet(uint64_t n) {
|
||||
DCHECK_NE(n, 0);
|
||||
#if defined(__GNUC__)
|
||||
return __builtin_ctzll(n);
|
||||
#elif defined(_MSC_VER) && defined(_M_X64)
|
||||
unsigned long c;
|
||||
_BitScanForward64(&c, n);
|
||||
return static_cast<int>(c);
|
||||
#elif defined(_MSC_VER) && defined(_M_IX86)
|
||||
unsigned long c;
|
||||
if (static_cast<uint32_t>(n) != 0) {
|
||||
_BitScanForward(&c, static_cast<uint32_t>(n));
|
||||
return static_cast<int>(c);
|
||||
} else {
|
||||
_BitScanForward(&c, static_cast<uint32_t>(n >> 32));
|
||||
return static_cast<int>(c) + 32;
|
||||
}
|
||||
#else
|
||||
int c = 63;
|
||||
for (int shift = 1 << 5; shift != 0; shift >>= 1) {
|
||||
uint64_t word = n << shift;
|
||||
if (word != 0) {
|
||||
n = word;
|
||||
c -= shift;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t words_[4];
|
||||
};
|
||||
|
||||
int Bitmap256::FindNextSetBit(int c) const {
|
||||
DCHECK_GE(c, 0);
|
||||
DCHECK_LE(c, 255);
|
||||
|
||||
// Check the word that contains the bit. Mask out any lower bits.
|
||||
int i = c / 64;
|
||||
uint64_t word = words_[i] & (~uint64_t{0} << (c % 64));
|
||||
if (word != 0)
|
||||
return (i * 64) + FindLSBSet(word);
|
||||
|
||||
// Check any following words.
|
||||
i++;
|
||||
switch (i) {
|
||||
case 1:
|
||||
if (words_[1] != 0)
|
||||
return (1 * 64) + FindLSBSet(words_[1]);
|
||||
FALLTHROUGH_INTENDED;
|
||||
case 2:
|
||||
if (words_[2] != 0)
|
||||
return (2 * 64) + FindLSBSet(words_[2]);
|
||||
FALLTHROUGH_INTENDED;
|
||||
case 3:
|
||||
if (words_[3] != 0)
|
||||
return (3 * 64) + FindLSBSet(words_[3]);
|
||||
FALLTHROUGH_INTENDED;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace re2
|
||||
|
||||
#endif // RE2_BITMAP256_H_
|
||||
114
Pods/gRPC-C++/third_party/re2/re2/filtered_re2.h
generated
vendored
Normal file
114
Pods/gRPC-C++/third_party/re2/re2/filtered_re2.h
generated
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
// Copyright 2009 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RE2_FILTERED_RE2_H_
|
||||
#define RE2_FILTERED_RE2_H_
|
||||
|
||||
// The class FilteredRE2 is used as a wrapper to multiple RE2 regexps.
|
||||
// It provides a prefilter mechanism that helps in cutting down the
|
||||
// number of regexps that need to be actually searched.
|
||||
//
|
||||
// By design, it does not include a string matching engine. This is to
|
||||
// allow the user of the class to use their favorite string matching
|
||||
// engine. The overall flow is: Add all the regexps using Add, then
|
||||
// Compile the FilteredRE2. Compile returns strings that need to be
|
||||
// matched. Note that the returned strings are lowercased and distinct.
|
||||
// For applying regexps to a search text, the caller does the string
|
||||
// matching using the returned strings. When doing the string match,
|
||||
// note that the caller has to do that in a case-insensitive way or
|
||||
// on a lowercased version of the search text. Then call FirstMatch
|
||||
// or AllMatches with a vector of indices of strings that were found
|
||||
// in the text to get the actual regexp matches.
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "re2/re2.h"
|
||||
|
||||
namespace re2 {
|
||||
|
||||
class PrefilterTree;
|
||||
|
||||
class FilteredRE2 {
|
||||
public:
|
||||
FilteredRE2();
|
||||
explicit FilteredRE2(int min_atom_len);
|
||||
~FilteredRE2();
|
||||
|
||||
// Not copyable.
|
||||
FilteredRE2(const FilteredRE2&) = delete;
|
||||
FilteredRE2& operator=(const FilteredRE2&) = delete;
|
||||
// Movable.
|
||||
FilteredRE2(FilteredRE2&& other);
|
||||
FilteredRE2& operator=(FilteredRE2&& other);
|
||||
|
||||
// Uses RE2 constructor to create a RE2 object (re). Returns
|
||||
// re->error_code(). If error_code is other than NoError, then re is
|
||||
// deleted and not added to re2_vec_.
|
||||
RE2::ErrorCode Add(const StringPiece& pattern,
|
||||
const RE2::Options& options,
|
||||
int* id);
|
||||
|
||||
// Prepares the regexps added by Add for filtering. Returns a set
|
||||
// of strings that the caller should check for in candidate texts.
|
||||
// The returned strings are lowercased and distinct. When doing
|
||||
// string matching, it should be performed in a case-insensitive
|
||||
// way or the search text should be lowercased first. Call after
|
||||
// all Add calls are done.
|
||||
void Compile(std::vector<std::string>* strings_to_match);
|
||||
|
||||
// Returns the index of the first matching regexp.
|
||||
// Returns -1 on no match. Can be called prior to Compile.
|
||||
// Does not do any filtering: simply tries to Match the
|
||||
// regexps in a loop.
|
||||
int SlowFirstMatch(const StringPiece& text) const;
|
||||
|
||||
// Returns the index of the first matching regexp.
|
||||
// Returns -1 on no match. Compile has to be called before
|
||||
// calling this.
|
||||
int FirstMatch(const StringPiece& text,
|
||||
const std::vector<int>& atoms) const;
|
||||
|
||||
// Returns the indices of all matching regexps, after first clearing
|
||||
// matched_regexps.
|
||||
bool AllMatches(const StringPiece& text,
|
||||
const std::vector<int>& atoms,
|
||||
std::vector<int>* matching_regexps) const;
|
||||
|
||||
// Returns the indices of all potentially matching regexps after first
|
||||
// clearing potential_regexps.
|
||||
// A regexp is potentially matching if it passes the filter.
|
||||
// If a regexp passes the filter it may still not match.
|
||||
// A regexp that does not pass the filter is guaranteed to not match.
|
||||
void AllPotentials(const std::vector<int>& atoms,
|
||||
std::vector<int>* potential_regexps) const;
|
||||
|
||||
// The number of regexps added.
|
||||
int NumRegexps() const { return static_cast<int>(re2_vec_.size()); }
|
||||
|
||||
// Get the individual RE2 objects.
|
||||
const RE2& GetRE2(int regexpid) const { return *re2_vec_[regexpid]; }
|
||||
|
||||
private:
|
||||
// Print prefilter.
|
||||
void PrintPrefilter(int regexpid);
|
||||
|
||||
// Useful for testing and debugging.
|
||||
void RegexpsGivenStrings(const std::vector<int>& matched_atoms,
|
||||
std::vector<int>* passed_regexps);
|
||||
|
||||
// All the regexps in the FilteredRE2.
|
||||
std::vector<RE2*> re2_vec_;
|
||||
|
||||
// Has the FilteredRE2 been compiled using Compile()
|
||||
bool compiled_;
|
||||
|
||||
// An AND-OR tree of string atoms used for filtering regexps.
|
||||
std::unique_ptr<PrefilterTree> prefilter_tree_;
|
||||
};
|
||||
|
||||
} // namespace re2
|
||||
|
||||
#endif // RE2_FILTERED_RE2_H_
|
||||
55
Pods/gRPC-C++/third_party/re2/re2/pod_array.h
generated
vendored
Normal file
55
Pods/gRPC-C++/third_party/re2/re2/pod_array.h
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright 2018 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RE2_POD_ARRAY_H_
|
||||
#define RE2_POD_ARRAY_H_
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
namespace re2 {
|
||||
|
||||
template <typename T>
|
||||
class PODArray {
|
||||
public:
|
||||
static_assert(std::is_trivial<T>::value && std::is_standard_layout<T>::value,
|
||||
"T must be POD");
|
||||
|
||||
PODArray()
|
||||
: ptr_() {}
|
||||
explicit PODArray(int len)
|
||||
: ptr_(std::allocator<T>().allocate(len), Deleter(len)) {}
|
||||
|
||||
T* data() const {
|
||||
return ptr_.get();
|
||||
}
|
||||
|
||||
int size() const {
|
||||
return ptr_.get_deleter().len_;
|
||||
}
|
||||
|
||||
T& operator[](int pos) const {
|
||||
return ptr_[pos];
|
||||
}
|
||||
|
||||
private:
|
||||
struct Deleter {
|
||||
Deleter()
|
||||
: len_(0) {}
|
||||
explicit Deleter(int len)
|
||||
: len_(len) {}
|
||||
|
||||
void operator()(T* ptr) const {
|
||||
std::allocator<T>().deallocate(ptr, len_);
|
||||
}
|
||||
|
||||
int len_;
|
||||
};
|
||||
|
||||
std::unique_ptr<T[], Deleter> ptr_;
|
||||
};
|
||||
|
||||
} // namespace re2
|
||||
|
||||
#endif // RE2_POD_ARRAY_H_
|
||||
108
Pods/gRPC-C++/third_party/re2/re2/prefilter.h
generated
vendored
Normal file
108
Pods/gRPC-C++/third_party/re2/re2/prefilter.h
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
// Copyright 2009 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RE2_PREFILTER_H_
|
||||
#define RE2_PREFILTER_H_
|
||||
|
||||
// Prefilter is the class used to extract string guards from regexps.
|
||||
// Rather than using Prefilter class directly, use FilteredRE2.
|
||||
// See filtered_re2.h
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "util/util.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
namespace re2 {
|
||||
|
||||
class RE2;
|
||||
|
||||
class Regexp;
|
||||
|
||||
class Prefilter {
|
||||
// Instead of using Prefilter directly, use FilteredRE2; see filtered_re2.h
|
||||
public:
|
||||
enum Op {
|
||||
ALL = 0, // Everything matches
|
||||
NONE, // Nothing matches
|
||||
ATOM, // The string atom() must match
|
||||
AND, // All in subs() must match
|
||||
OR, // One of subs() must match
|
||||
};
|
||||
|
||||
explicit Prefilter(Op op);
|
||||
~Prefilter();
|
||||
|
||||
Op op() { return op_; }
|
||||
const std::string& atom() const { return atom_; }
|
||||
void set_unique_id(int id) { unique_id_ = id; }
|
||||
int unique_id() const { return unique_id_; }
|
||||
|
||||
// The children of the Prefilter node.
|
||||
std::vector<Prefilter*>* subs() {
|
||||
DCHECK(op_ == AND || op_ == OR);
|
||||
return subs_;
|
||||
}
|
||||
|
||||
// Set the children vector. Prefilter takes ownership of subs and
|
||||
// subs_ will be deleted when Prefilter is deleted.
|
||||
void set_subs(std::vector<Prefilter*>* subs) { subs_ = subs; }
|
||||
|
||||
// Given a RE2, return a Prefilter. The caller takes ownership of
|
||||
// the Prefilter and should deallocate it. Returns NULL if Prefilter
|
||||
// cannot be formed.
|
||||
static Prefilter* FromRE2(const RE2* re2);
|
||||
|
||||
// Returns a readable debug string of the prefilter.
|
||||
std::string DebugString() const;
|
||||
|
||||
private:
|
||||
class Info;
|
||||
|
||||
// Combines two prefilters together to create an AND. The passed
|
||||
// Prefilters will be part of the returned Prefilter or deleted.
|
||||
static Prefilter* And(Prefilter* a, Prefilter* b);
|
||||
|
||||
// Combines two prefilters together to create an OR. The passed
|
||||
// Prefilters will be part of the returned Prefilter or deleted.
|
||||
static Prefilter* Or(Prefilter* a, Prefilter* b);
|
||||
|
||||
// Generalized And/Or
|
||||
static Prefilter* AndOr(Op op, Prefilter* a, Prefilter* b);
|
||||
|
||||
static Prefilter* FromRegexp(Regexp* a);
|
||||
|
||||
static Prefilter* FromString(const std::string& str);
|
||||
|
||||
static Prefilter* OrStrings(std::set<std::string>* ss);
|
||||
|
||||
static Info* BuildInfo(Regexp* re);
|
||||
|
||||
Prefilter* Simplify();
|
||||
|
||||
// Kind of Prefilter.
|
||||
Op op_;
|
||||
|
||||
// Sub-matches for AND or OR Prefilter.
|
||||
std::vector<Prefilter*>* subs_;
|
||||
|
||||
// Actual string to match in leaf node.
|
||||
std::string atom_;
|
||||
|
||||
// If different prefilters have the same string atom, or if they are
|
||||
// structurally the same (e.g., OR of same atom strings) they are
|
||||
// considered the same unique nodes. This is the id for each unique
|
||||
// node. This field is populated with a unique id for every node,
|
||||
// and -1 for duplicate nodes.
|
||||
int unique_id_;
|
||||
|
||||
Prefilter(const Prefilter&) = delete;
|
||||
Prefilter& operator=(const Prefilter&) = delete;
|
||||
};
|
||||
|
||||
} // namespace re2
|
||||
|
||||
#endif // RE2_PREFILTER_H_
|
||||
140
Pods/gRPC-C++/third_party/re2/re2/prefilter_tree.h
generated
vendored
Normal file
140
Pods/gRPC-C++/third_party/re2/re2/prefilter_tree.h
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright 2009 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RE2_PREFILTER_TREE_H_
|
||||
#define RE2_PREFILTER_TREE_H_
|
||||
|
||||
// The PrefilterTree class is used to form an AND-OR tree of strings
|
||||
// that would trigger each regexp. The 'prefilter' of each regexp is
|
||||
// added to PrefilterTree, and then PrefilterTree is used to find all
|
||||
// the unique strings across the prefilters. During search, by using
|
||||
// matches from a string matching engine, PrefilterTree deduces the
|
||||
// set of regexps that are to be triggered. The 'string matching
|
||||
// engine' itself is outside of this class, and the caller can use any
|
||||
// favorite engine. PrefilterTree provides a set of strings (called
|
||||
// atoms) that the user of this class should use to do the string
|
||||
// matching.
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "util/util.h"
|
||||
#include "re2/prefilter.h"
|
||||
#include "re2/sparse_array.h"
|
||||
|
||||
namespace re2 {
|
||||
|
||||
class PrefilterTree {
|
||||
public:
|
||||
PrefilterTree();
|
||||
explicit PrefilterTree(int min_atom_len);
|
||||
~PrefilterTree();
|
||||
|
||||
// Adds the prefilter for the next regexp. Note that we assume that
|
||||
// Add called sequentially for all regexps. All Add calls
|
||||
// must precede Compile.
|
||||
void Add(Prefilter* prefilter);
|
||||
|
||||
// The Compile returns a vector of string in atom_vec.
|
||||
// Call this after all the prefilters are added through Add.
|
||||
// No calls to Add after Compile are allowed.
|
||||
// The caller should use the returned set of strings to do string matching.
|
||||
// Each time a string matches, the corresponding index then has to be
|
||||
// and passed to RegexpsGivenStrings below.
|
||||
void Compile(std::vector<std::string>* atom_vec);
|
||||
|
||||
// Given the indices of the atoms that matched, returns the indexes
|
||||
// of regexps that should be searched. The matched_atoms should
|
||||
// contain all the ids of string atoms that were found to match the
|
||||
// content. The caller can use any string match engine to perform
|
||||
// this function. This function is thread safe.
|
||||
void RegexpsGivenStrings(const std::vector<int>& matched_atoms,
|
||||
std::vector<int>* regexps) const;
|
||||
|
||||
// Print debug prefilter. Also prints unique ids associated with
|
||||
// nodes of the prefilter of the regexp.
|
||||
void PrintPrefilter(int regexpid);
|
||||
|
||||
private:
|
||||
typedef SparseArray<int> IntMap;
|
||||
// TODO(junyer): Use std::unordered_set<Prefilter*> instead?
|
||||
// It should be trivial to get rid of the stringification...
|
||||
typedef std::map<std::string, Prefilter*> NodeMap;
|
||||
|
||||
// Each unique node has a corresponding Entry that helps in
|
||||
// passing the matching trigger information along the tree.
|
||||
struct Entry {
|
||||
public:
|
||||
// How many children should match before this node triggers the
|
||||
// parent. For an atom and an OR node, this is 1 and for an AND
|
||||
// node, it is the number of unique children.
|
||||
int propagate_up_at_count;
|
||||
|
||||
// When this node is ready to trigger the parent, what are the indices
|
||||
// of the parent nodes to trigger. The reason there may be more than
|
||||
// one is because of sharing. For example (abc | def) and (xyz | def)
|
||||
// are two different nodes, but they share the atom 'def'. So when
|
||||
// 'def' matches, it triggers two parents, corresponding to the two
|
||||
// different OR nodes.
|
||||
std::vector<int> parents;
|
||||
|
||||
// When this node is ready to trigger the parent, what are the
|
||||
// regexps that are triggered.
|
||||
std::vector<int> regexps;
|
||||
};
|
||||
|
||||
// Returns true if the prefilter node should be kept.
|
||||
bool KeepNode(Prefilter* node) const;
|
||||
|
||||
// This function assigns unique ids to various parts of the
|
||||
// prefilter, by looking at if these nodes are already in the
|
||||
// PrefilterTree.
|
||||
void AssignUniqueIds(NodeMap* nodes, std::vector<std::string>* atom_vec);
|
||||
|
||||
// Given the matching atoms, find the regexps to be triggered.
|
||||
void PropagateMatch(const std::vector<int>& atom_ids,
|
||||
IntMap* regexps) const;
|
||||
|
||||
// Returns the prefilter node that has the same NodeString as this
|
||||
// node. For the canonical node, returns node.
|
||||
Prefilter* CanonicalNode(NodeMap* nodes, Prefilter* node);
|
||||
|
||||
// A string that uniquely identifies the node. Assumes that the
|
||||
// children of node has already been assigned unique ids.
|
||||
std::string NodeString(Prefilter* node) const;
|
||||
|
||||
// Recursively constructs a readable prefilter string.
|
||||
std::string DebugNodeString(Prefilter* node) const;
|
||||
|
||||
// Used for debugging.
|
||||
void PrintDebugInfo(NodeMap* nodes);
|
||||
|
||||
// These are all the nodes formed by Compile. Essentially, there is
|
||||
// one node for each unique atom and each unique AND/OR node.
|
||||
std::vector<Entry> entries_;
|
||||
|
||||
// indices of regexps that always pass through the filter (since we
|
||||
// found no required literals in these regexps).
|
||||
std::vector<int> unfiltered_;
|
||||
|
||||
// vector of Prefilter for all regexps.
|
||||
std::vector<Prefilter*> prefilter_vec_;
|
||||
|
||||
// Atom index in returned strings to entry id mapping.
|
||||
std::vector<int> atom_index_to_id_;
|
||||
|
||||
// Has the prefilter tree been compiled.
|
||||
bool compiled_;
|
||||
|
||||
// Strings less than this length are not stored as atoms.
|
||||
const int min_atom_len_;
|
||||
|
||||
PrefilterTree(const PrefilterTree&) = delete;
|
||||
PrefilterTree& operator=(const PrefilterTree&) = delete;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // RE2_PREFILTER_TREE_H_
|
||||
467
Pods/gRPC-C++/third_party/re2/re2/prog.h
generated
vendored
Normal file
467
Pods/gRPC-C++/third_party/re2/re2/prog.h
generated
vendored
Normal file
@@ -0,0 +1,467 @@
|
||||
// Copyright 2007 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RE2_PROG_H_
|
||||
#define RE2_PROG_H_
|
||||
|
||||
// Compiled representation of regular expressions.
|
||||
// See regexp.h for the Regexp class, which represents a regular
|
||||
// expression symbolically.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
|
||||
#include "util/util.h"
|
||||
#include "util/logging.h"
|
||||
#include "re2/pod_array.h"
|
||||
#include "re2/re2.h"
|
||||
#include "re2/sparse_array.h"
|
||||
#include "re2/sparse_set.h"
|
||||
|
||||
namespace re2 {
|
||||
|
||||
// Opcodes for Inst
|
||||
enum InstOp {
|
||||
kInstAlt = 0, // choose between out_ and out1_
|
||||
kInstAltMatch, // Alt: out_ is [00-FF] and back, out1_ is match; or vice versa.
|
||||
kInstByteRange, // next (possible case-folded) byte must be in [lo_, hi_]
|
||||
kInstCapture, // capturing parenthesis number cap_
|
||||
kInstEmptyWidth, // empty-width special (^ $ ...); bit(s) set in empty_
|
||||
kInstMatch, // found a match!
|
||||
kInstNop, // no-op; occasionally unavoidable
|
||||
kInstFail, // never match; occasionally unavoidable
|
||||
kNumInst,
|
||||
};
|
||||
|
||||
// Bit flags for empty-width specials
|
||||
enum EmptyOp {
|
||||
kEmptyBeginLine = 1<<0, // ^ - beginning of line
|
||||
kEmptyEndLine = 1<<1, // $ - end of line
|
||||
kEmptyBeginText = 1<<2, // \A - beginning of text
|
||||
kEmptyEndText = 1<<3, // \z - end of text
|
||||
kEmptyWordBoundary = 1<<4, // \b - word boundary
|
||||
kEmptyNonWordBoundary = 1<<5, // \B - not \b
|
||||
kEmptyAllFlags = (1<<6)-1,
|
||||
};
|
||||
|
||||
class DFA;
|
||||
class Regexp;
|
||||
|
||||
// Compiled form of regexp program.
|
||||
class Prog {
|
||||
public:
|
||||
Prog();
|
||||
~Prog();
|
||||
|
||||
// Single instruction in regexp program.
|
||||
class Inst {
|
||||
public:
|
||||
// See the assertion below for why this is so.
|
||||
Inst() = default;
|
||||
|
||||
// Copyable.
|
||||
Inst(const Inst&) = default;
|
||||
Inst& operator=(const Inst&) = default;
|
||||
|
||||
// Constructors per opcode
|
||||
void InitAlt(uint32_t out, uint32_t out1);
|
||||
void InitByteRange(int lo, int hi, int foldcase, uint32_t out);
|
||||
void InitCapture(int cap, uint32_t out);
|
||||
void InitEmptyWidth(EmptyOp empty, uint32_t out);
|
||||
void InitMatch(int id);
|
||||
void InitNop(uint32_t out);
|
||||
void InitFail();
|
||||
|
||||
// Getters
|
||||
int id(Prog* p) { return static_cast<int>(this - p->inst_.data()); }
|
||||
InstOp opcode() { return static_cast<InstOp>(out_opcode_&7); }
|
||||
int last() { return (out_opcode_>>3)&1; }
|
||||
int out() { return out_opcode_>>4; }
|
||||
int out1() { DCHECK(opcode() == kInstAlt || opcode() == kInstAltMatch); return out1_; }
|
||||
int cap() { DCHECK_EQ(opcode(), kInstCapture); return cap_; }
|
||||
int lo() { DCHECK_EQ(opcode(), kInstByteRange); return lo_; }
|
||||
int hi() { DCHECK_EQ(opcode(), kInstByteRange); return hi_; }
|
||||
int foldcase() { DCHECK_EQ(opcode(), kInstByteRange); return hint_foldcase_&1; }
|
||||
int hint() { DCHECK_EQ(opcode(), kInstByteRange); return hint_foldcase_>>1; }
|
||||
int match_id() { DCHECK_EQ(opcode(), kInstMatch); return match_id_; }
|
||||
EmptyOp empty() { DCHECK_EQ(opcode(), kInstEmptyWidth); return empty_; }
|
||||
|
||||
bool greedy(Prog* p) {
|
||||
DCHECK_EQ(opcode(), kInstAltMatch);
|
||||
return p->inst(out())->opcode() == kInstByteRange ||
|
||||
(p->inst(out())->opcode() == kInstNop &&
|
||||
p->inst(p->inst(out())->out())->opcode() == kInstByteRange);
|
||||
}
|
||||
|
||||
// Does this inst (an kInstByteRange) match c?
|
||||
inline bool Matches(int c) {
|
||||
DCHECK_EQ(opcode(), kInstByteRange);
|
||||
if (foldcase() && 'A' <= c && c <= 'Z')
|
||||
c += 'a' - 'A';
|
||||
return lo_ <= c && c <= hi_;
|
||||
}
|
||||
|
||||
// Returns string representation for debugging.
|
||||
std::string Dump();
|
||||
|
||||
// Maximum instruction id.
|
||||
// (Must fit in out_opcode_. PatchList/last steal another bit.)
|
||||
static const int kMaxInst = (1<<28) - 1;
|
||||
|
||||
private:
|
||||
void set_opcode(InstOp opcode) {
|
||||
out_opcode_ = (out()<<4) | (last()<<3) | opcode;
|
||||
}
|
||||
|
||||
void set_last() {
|
||||
out_opcode_ = (out()<<4) | (1<<3) | opcode();
|
||||
}
|
||||
|
||||
void set_out(int out) {
|
||||
out_opcode_ = (out<<4) | (last()<<3) | opcode();
|
||||
}
|
||||
|
||||
void set_out_opcode(int out, InstOp opcode) {
|
||||
out_opcode_ = (out<<4) | (last()<<3) | opcode;
|
||||
}
|
||||
|
||||
uint32_t out_opcode_; // 28 bits: out, 1 bit: last, 3 (low) bits: opcode
|
||||
union { // additional instruction arguments:
|
||||
uint32_t out1_; // opcode == kInstAlt
|
||||
// alternate next instruction
|
||||
|
||||
int32_t cap_; // opcode == kInstCapture
|
||||
// Index of capture register (holds text
|
||||
// position recorded by capturing parentheses).
|
||||
// For \n (the submatch for the nth parentheses),
|
||||
// the left parenthesis captures into register 2*n
|
||||
// and the right one captures into register 2*n+1.
|
||||
|
||||
int32_t match_id_; // opcode == kInstMatch
|
||||
// Match ID to identify this match (for re2::Set).
|
||||
|
||||
struct { // opcode == kInstByteRange
|
||||
uint8_t lo_; // byte range is lo_-hi_ inclusive
|
||||
uint8_t hi_; //
|
||||
uint16_t hint_foldcase_; // 15 bits: hint, 1 (low) bit: foldcase
|
||||
// hint to execution engines: the delta to the
|
||||
// next instruction (in the current list) worth
|
||||
// exploring iff this instruction matched; 0
|
||||
// means there are no remaining possibilities,
|
||||
// which is most likely for character classes.
|
||||
// foldcase: A-Z -> a-z before checking range.
|
||||
};
|
||||
|
||||
EmptyOp empty_; // opcode == kInstEmptyWidth
|
||||
// empty_ is bitwise OR of kEmpty* flags above.
|
||||
};
|
||||
|
||||
friend class Compiler;
|
||||
friend struct PatchList;
|
||||
friend class Prog;
|
||||
};
|
||||
|
||||
// Inst must be trivial so that we can freely clear it with memset(3).
|
||||
// Arrays of Inst are initialised by copying the initial elements with
|
||||
// memmove(3) and then clearing any remaining elements with memset(3).
|
||||
static_assert(std::is_trivial<Inst>::value, "Inst must be trivial");
|
||||
|
||||
// Whether to anchor the search.
|
||||
enum Anchor {
|
||||
kUnanchored, // match anywhere
|
||||
kAnchored, // match only starting at beginning of text
|
||||
};
|
||||
|
||||
// Kind of match to look for (for anchor != kFullMatch)
|
||||
//
|
||||
// kLongestMatch mode finds the overall longest
|
||||
// match but still makes its submatch choices the way
|
||||
// Perl would, not in the way prescribed by POSIX.
|
||||
// The POSIX rules are much more expensive to implement,
|
||||
// and no one has needed them.
|
||||
//
|
||||
// kFullMatch is not strictly necessary -- we could use
|
||||
// kLongestMatch and then check the length of the match -- but
|
||||
// the matching code can run faster if it knows to consider only
|
||||
// full matches.
|
||||
enum MatchKind {
|
||||
kFirstMatch, // like Perl, PCRE
|
||||
kLongestMatch, // like egrep or POSIX
|
||||
kFullMatch, // match only entire text; implies anchor==kAnchored
|
||||
kManyMatch // for SearchDFA, records set of matches
|
||||
};
|
||||
|
||||
Inst *inst(int id) { return &inst_[id]; }
|
||||
int start() { return start_; }
|
||||
void set_start(int start) { start_ = start; }
|
||||
int start_unanchored() { return start_unanchored_; }
|
||||
void set_start_unanchored(int start) { start_unanchored_ = start; }
|
||||
int size() { return size_; }
|
||||
bool reversed() { return reversed_; }
|
||||
void set_reversed(bool reversed) { reversed_ = reversed; }
|
||||
int list_count() { return list_count_; }
|
||||
int inst_count(InstOp op) { return inst_count_[op]; }
|
||||
uint16_t* list_heads() { return list_heads_.data(); }
|
||||
size_t bit_state_text_max_size() { return bit_state_text_max_size_; }
|
||||
int64_t dfa_mem() { return dfa_mem_; }
|
||||
void set_dfa_mem(int64_t dfa_mem) { dfa_mem_ = dfa_mem; }
|
||||
bool anchor_start() { return anchor_start_; }
|
||||
void set_anchor_start(bool b) { anchor_start_ = b; }
|
||||
bool anchor_end() { return anchor_end_; }
|
||||
void set_anchor_end(bool b) { anchor_end_ = b; }
|
||||
int bytemap_range() { return bytemap_range_; }
|
||||
const uint8_t* bytemap() { return bytemap_; }
|
||||
bool can_prefix_accel() { return prefix_size_ != 0; }
|
||||
|
||||
// Accelerates to the first likely occurrence of the prefix.
|
||||
// Returns a pointer to the first byte or NULL if not found.
|
||||
const void* PrefixAccel(const void* data, size_t size) {
|
||||
DCHECK(can_prefix_accel());
|
||||
if (prefix_foldcase_) {
|
||||
return PrefixAccel_ShiftDFA(data, size);
|
||||
} else if (prefix_size_ != 1) {
|
||||
return PrefixAccel_FrontAndBack(data, size);
|
||||
} else {
|
||||
return memchr(data, prefix_front_, size);
|
||||
}
|
||||
}
|
||||
|
||||
// Configures prefix accel using the analysis performed during compilation.
|
||||
void ConfigurePrefixAccel(const std::string& prefix, bool prefix_foldcase);
|
||||
|
||||
// An implementation of prefix accel that uses prefix_dfa_ to perform
|
||||
// case-insensitive search.
|
||||
const void* PrefixAccel_ShiftDFA(const void* data, size_t size);
|
||||
|
||||
// An implementation of prefix accel that looks for prefix_front_ and
|
||||
// prefix_back_ to return fewer false positives than memchr(3) alone.
|
||||
const void* PrefixAccel_FrontAndBack(const void* data, size_t size);
|
||||
|
||||
// Returns string representation of program for debugging.
|
||||
std::string Dump();
|
||||
std::string DumpUnanchored();
|
||||
std::string DumpByteMap();
|
||||
|
||||
// Returns the set of kEmpty flags that are in effect at
|
||||
// position p within context.
|
||||
static uint32_t EmptyFlags(const StringPiece& context, const char* p);
|
||||
|
||||
// Returns whether byte c is a word character: ASCII only.
|
||||
// Used by the implementation of \b and \B.
|
||||
// This is not right for Unicode, but:
|
||||
// - it's hard to get right in a byte-at-a-time matching world
|
||||
// (the DFA has only one-byte lookahead).
|
||||
// - even if the lookahead were possible, the Progs would be huge.
|
||||
// This crude approximation is the same one PCRE uses.
|
||||
static bool IsWordChar(uint8_t c) {
|
||||
return ('A' <= c && c <= 'Z') ||
|
||||
('a' <= c && c <= 'z') ||
|
||||
('0' <= c && c <= '9') ||
|
||||
c == '_';
|
||||
}
|
||||
|
||||
// Execution engines. They all search for the regexp (run the prog)
|
||||
// in text, which is in the larger context (used for ^ $ \b etc).
|
||||
// Anchor and kind control the kind of search.
|
||||
// Returns true if match found, false if not.
|
||||
// If match found, fills match[0..nmatch-1] with submatch info.
|
||||
// match[0] is overall match, match[1] is first set of parens, etc.
|
||||
// If a particular submatch is not matched during the regexp match,
|
||||
// it is set to NULL.
|
||||
//
|
||||
// Matching text == StringPiece(NULL, 0) is treated as any other empty
|
||||
// string, but note that on return, it will not be possible to distinguish
|
||||
// submatches that matched that empty string from submatches that didn't
|
||||
// match anything. Either way, match[i] == NULL.
|
||||
|
||||
// Search using NFA: can find submatches but kind of slow.
|
||||
bool SearchNFA(const StringPiece& text, const StringPiece& context,
|
||||
Anchor anchor, MatchKind kind,
|
||||
StringPiece* match, int nmatch);
|
||||
|
||||
// Search using DFA: much faster than NFA but only finds
|
||||
// end of match and can use a lot more memory.
|
||||
// Returns whether a match was found.
|
||||
// If the DFA runs out of memory, sets *failed to true and returns false.
|
||||
// If matches != NULL and kind == kManyMatch and there is a match,
|
||||
// SearchDFA fills matches with the match IDs of the final matching state.
|
||||
bool SearchDFA(const StringPiece& text, const StringPiece& context,
|
||||
Anchor anchor, MatchKind kind, StringPiece* match0,
|
||||
bool* failed, SparseSet* matches);
|
||||
|
||||
// The callback issued after building each DFA state with BuildEntireDFA().
|
||||
// If next is null, then the memory budget has been exhausted and building
|
||||
// will halt. Otherwise, the state has been built and next points to an array
|
||||
// of bytemap_range()+1 slots holding the next states as per the bytemap and
|
||||
// kByteEndText. The number of the state is implied by the callback sequence:
|
||||
// the first callback is for state 0, the second callback is for state 1, ...
|
||||
// match indicates whether the state is a matching state.
|
||||
using DFAStateCallback = std::function<void(const int* next, bool match)>;
|
||||
|
||||
// Build the entire DFA for the given match kind.
|
||||
// Usually the DFA is built out incrementally, as needed, which
|
||||
// avoids lots of unnecessary work.
|
||||
// If cb is not empty, it receives one callback per state built.
|
||||
// Returns the number of states built.
|
||||
// FOR TESTING OR EXPERIMENTAL PURPOSES ONLY.
|
||||
int BuildEntireDFA(MatchKind kind, const DFAStateCallback& cb);
|
||||
|
||||
// Compute bytemap.
|
||||
void ComputeByteMap();
|
||||
|
||||
// Run peep-hole optimizer on program.
|
||||
void Optimize();
|
||||
|
||||
// One-pass NFA: only correct if IsOnePass() is true,
|
||||
// but much faster than NFA (competitive with PCRE)
|
||||
// for those expressions.
|
||||
bool IsOnePass();
|
||||
bool SearchOnePass(const StringPiece& text, const StringPiece& context,
|
||||
Anchor anchor, MatchKind kind,
|
||||
StringPiece* match, int nmatch);
|
||||
|
||||
// Bit-state backtracking. Fast on small cases but uses memory
|
||||
// proportional to the product of the list count and the text size.
|
||||
bool CanBitState() { return list_heads_.data() != NULL; }
|
||||
bool SearchBitState(const StringPiece& text, const StringPiece& context,
|
||||
Anchor anchor, MatchKind kind,
|
||||
StringPiece* match, int nmatch);
|
||||
|
||||
static const int kMaxOnePassCapture = 5; // $0 through $4
|
||||
|
||||
// Backtracking search: the gold standard against which the other
|
||||
// implementations are checked. FOR TESTING ONLY.
|
||||
// It allocates a ton of memory to avoid running forever.
|
||||
// It is also recursive, so can't use in production (will overflow stacks).
|
||||
// The name "Unsafe" here is supposed to be a flag that
|
||||
// you should not be using this function.
|
||||
bool UnsafeSearchBacktrack(const StringPiece& text,
|
||||
const StringPiece& context,
|
||||
Anchor anchor, MatchKind kind,
|
||||
StringPiece* match, int nmatch);
|
||||
|
||||
// Computes range for any strings matching regexp. The min and max can in
|
||||
// some cases be arbitrarily precise, so the caller gets to specify the
|
||||
// maximum desired length of string returned.
|
||||
//
|
||||
// Assuming PossibleMatchRange(&min, &max, N) returns successfully, any
|
||||
// string s that is an anchored match for this regexp satisfies
|
||||
// min <= s && s <= max.
|
||||
//
|
||||
// Note that PossibleMatchRange() will only consider the first copy of an
|
||||
// infinitely repeated element (i.e., any regexp element followed by a '*' or
|
||||
// '+' operator). Regexps with "{N}" constructions are not affected, as those
|
||||
// do not compile down to infinite repetitions.
|
||||
//
|
||||
// Returns true on success, false on error.
|
||||
bool PossibleMatchRange(std::string* min, std::string* max, int maxlen);
|
||||
|
||||
// Outputs the program fanout into the given sparse array.
|
||||
void Fanout(SparseArray<int>* fanout);
|
||||
|
||||
// Compiles a collection of regexps to Prog. Each regexp will have
|
||||
// its own Match instruction recording the index in the output vector.
|
||||
static Prog* CompileSet(Regexp* re, RE2::Anchor anchor, int64_t max_mem);
|
||||
|
||||
// Flattens the Prog from "tree" form to "list" form. This is an in-place
|
||||
// operation in the sense that the old instructions are lost.
|
||||
void Flatten();
|
||||
|
||||
// Walks the Prog; the "successor roots" or predecessors of the reachable
|
||||
// instructions are marked in rootmap or predmap/predvec, respectively.
|
||||
// reachable and stk are preallocated scratch structures.
|
||||
void MarkSuccessors(SparseArray<int>* rootmap,
|
||||
SparseArray<int>* predmap,
|
||||
std::vector<std::vector<int>>* predvec,
|
||||
SparseSet* reachable, std::vector<int>* stk);
|
||||
|
||||
// Walks the Prog from the given "root" instruction; the "dominator root"
|
||||
// of the reachable instructions (if such exists) is marked in rootmap.
|
||||
// reachable and stk are preallocated scratch structures.
|
||||
void MarkDominator(int root, SparseArray<int>* rootmap,
|
||||
SparseArray<int>* predmap,
|
||||
std::vector<std::vector<int>>* predvec,
|
||||
SparseSet* reachable, std::vector<int>* stk);
|
||||
|
||||
// Walks the Prog from the given "root" instruction; the reachable
|
||||
// instructions are emitted in "list" form and appended to flat.
|
||||
// reachable and stk are preallocated scratch structures.
|
||||
void EmitList(int root, SparseArray<int>* rootmap,
|
||||
std::vector<Inst>* flat,
|
||||
SparseSet* reachable, std::vector<int>* stk);
|
||||
|
||||
// Computes hints for ByteRange instructions in [begin, end).
|
||||
void ComputeHints(std::vector<Inst>* flat, int begin, int end);
|
||||
|
||||
// Controls whether the DFA should bail out early if the NFA would be faster.
|
||||
// FOR TESTING ONLY.
|
||||
static void TESTING_ONLY_set_dfa_should_bail_when_slow(bool b);
|
||||
|
||||
private:
|
||||
friend class Compiler;
|
||||
|
||||
DFA* GetDFA(MatchKind kind);
|
||||
void DeleteDFA(DFA* dfa);
|
||||
|
||||
bool anchor_start_; // regexp has explicit start anchor
|
||||
bool anchor_end_; // regexp has explicit end anchor
|
||||
bool reversed_; // whether program runs backward over input
|
||||
bool did_flatten_; // has Flatten been called?
|
||||
bool did_onepass_; // has IsOnePass been called?
|
||||
|
||||
int start_; // entry point for program
|
||||
int start_unanchored_; // unanchored entry point for program
|
||||
int size_; // number of instructions
|
||||
int bytemap_range_; // bytemap_[x] < bytemap_range_
|
||||
|
||||
bool prefix_foldcase_; // whether prefix is case-insensitive
|
||||
size_t prefix_size_; // size of prefix (0 if no prefix)
|
||||
union {
|
||||
uint64_t* prefix_dfa_; // "Shift DFA" for prefix
|
||||
struct {
|
||||
int prefix_front_; // first byte of prefix
|
||||
int prefix_back_; // last byte of prefix
|
||||
};
|
||||
};
|
||||
|
||||
int list_count_; // count of lists (see above)
|
||||
int inst_count_[kNumInst]; // count of instructions by opcode
|
||||
PODArray<uint16_t> list_heads_; // sparse array enumerating list heads
|
||||
// not populated if size_ is overly large
|
||||
size_t bit_state_text_max_size_; // upper bound (inclusive) on text.size()
|
||||
|
||||
PODArray<Inst> inst_; // pointer to instruction array
|
||||
PODArray<uint8_t> onepass_nodes_; // data for OnePass nodes
|
||||
|
||||
int64_t dfa_mem_; // Maximum memory for DFAs.
|
||||
DFA* dfa_first_; // DFA cached for kFirstMatch/kManyMatch
|
||||
DFA* dfa_longest_; // DFA cached for kLongestMatch/kFullMatch
|
||||
|
||||
uint8_t bytemap_[256]; // map from input bytes to byte classes
|
||||
|
||||
std::once_flag dfa_first_once_;
|
||||
std::once_flag dfa_longest_once_;
|
||||
|
||||
Prog(const Prog&) = delete;
|
||||
Prog& operator=(const Prog&) = delete;
|
||||
};
|
||||
|
||||
// std::string_view in MSVC has iterators that aren't just pointers and
|
||||
// that don't allow comparisons between different objects - not even if
|
||||
// those objects are views into the same string! Thus, we provide these
|
||||
// conversion functions for convenience.
|
||||
static inline const char* BeginPtr(const StringPiece& s) {
|
||||
return s.data();
|
||||
}
|
||||
static inline const char* EndPtr(const StringPiece& s) {
|
||||
return s.data() + s.size();
|
||||
}
|
||||
|
||||
} // namespace re2
|
||||
|
||||
#endif // RE2_PROG_H_
|
||||
1017
Pods/gRPC-C++/third_party/re2/re2/re2.h
generated
vendored
Normal file
1017
Pods/gRPC-C++/third_party/re2/re2/re2.h
generated
vendored
Normal file
@@ -0,0 +1,1017 @@
|
||||
// Copyright 2003-2009 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RE2_RE2_H_
|
||||
#define RE2_RE2_H_
|
||||
|
||||
// C++ interface to the re2 regular-expression library.
|
||||
// RE2 supports Perl-style regular expressions (with extensions like
|
||||
// \d, \w, \s, ...).
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// REGEXP SYNTAX:
|
||||
//
|
||||
// This module uses the re2 library and hence supports
|
||||
// its syntax for regular expressions, which is similar to Perl's with
|
||||
// some of the more complicated things thrown away. In particular,
|
||||
// backreferences and generalized assertions are not available, nor is \Z.
|
||||
//
|
||||
// See https://github.com/google/re2/wiki/Syntax for the syntax
|
||||
// supported by RE2, and a comparison with PCRE and PERL regexps.
|
||||
//
|
||||
// For those not familiar with Perl's regular expressions,
|
||||
// here are some examples of the most commonly used extensions:
|
||||
//
|
||||
// "hello (\\w+) world" -- \w matches a "word" character
|
||||
// "version (\\d+)" -- \d matches a digit
|
||||
// "hello\\s+world" -- \s matches any whitespace character
|
||||
// "\\b(\\w+)\\b" -- \b matches non-empty string at word boundary
|
||||
// "(?i)hello" -- (?i) turns on case-insensitive matching
|
||||
// "/\\*(.*?)\\*/" -- .*? matches . minimum no. of times possible
|
||||
//
|
||||
// The double backslashes are needed when writing C++ string literals.
|
||||
// However, they should NOT be used when writing C++11 raw string literals:
|
||||
//
|
||||
// R"(hello (\w+) world)" -- \w matches a "word" character
|
||||
// R"(version (\d+))" -- \d matches a digit
|
||||
// R"(hello\s+world)" -- \s matches any whitespace character
|
||||
// R"(\b(\w+)\b)" -- \b matches non-empty string at word boundary
|
||||
// R"((?i)hello)" -- (?i) turns on case-insensitive matching
|
||||
// R"(/\*(.*?)\*/)" -- .*? matches . minimum no. of times possible
|
||||
//
|
||||
// When using UTF-8 encoding, case-insensitive matching will perform
|
||||
// simple case folding, not full case folding.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// MATCHING INTERFACE:
|
||||
//
|
||||
// The "FullMatch" operation checks that supplied text matches a
|
||||
// supplied pattern exactly.
|
||||
//
|
||||
// Example: successful match
|
||||
// CHECK(RE2::FullMatch("hello", "h.*o"));
|
||||
//
|
||||
// Example: unsuccessful match (requires full match):
|
||||
// CHECK(!RE2::FullMatch("hello", "e"));
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// UTF-8 AND THE MATCHING INTERFACE:
|
||||
//
|
||||
// By default, the pattern and input text are interpreted as UTF-8.
|
||||
// The RE2::Latin1 option causes them to be interpreted as Latin-1.
|
||||
//
|
||||
// Example:
|
||||
// CHECK(RE2::FullMatch(utf8_string, RE2(utf8_pattern)));
|
||||
// CHECK(RE2::FullMatch(latin1_string, RE2(latin1_pattern, RE2::Latin1)));
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// MATCHING WITH SUBSTRING EXTRACTION:
|
||||
//
|
||||
// You can supply extra pointer arguments to extract matched substrings.
|
||||
// On match failure, none of the pointees will have been modified.
|
||||
// On match success, the substrings will be converted (as necessary) and
|
||||
// their values will be assigned to their pointees until all conversions
|
||||
// have succeeded or one conversion has failed.
|
||||
// On conversion failure, the pointees will be in an indeterminate state
|
||||
// because the caller has no way of knowing which conversion failed.
|
||||
// However, conversion cannot fail for types like string and StringPiece
|
||||
// that do not inspect the substring contents. Hence, in the common case
|
||||
// where all of the pointees are of such types, failure is always due to
|
||||
// match failure and thus none of the pointees will have been modified.
|
||||
//
|
||||
// Example: extracts "ruby" into "s" and 1234 into "i"
|
||||
// int i;
|
||||
// std::string s;
|
||||
// CHECK(RE2::FullMatch("ruby:1234", "(\\w+):(\\d+)", &s, &i));
|
||||
//
|
||||
// Example: fails because string cannot be stored in integer
|
||||
// CHECK(!RE2::FullMatch("ruby", "(.*)", &i));
|
||||
//
|
||||
// Example: fails because there aren't enough sub-patterns
|
||||
// CHECK(!RE2::FullMatch("ruby:1234", "\\w+:\\d+", &s));
|
||||
//
|
||||
// Example: does not try to extract any extra sub-patterns
|
||||
// CHECK(RE2::FullMatch("ruby:1234", "(\\w+):(\\d+)", &s));
|
||||
//
|
||||
// Example: does not try to extract into NULL
|
||||
// CHECK(RE2::FullMatch("ruby:1234", "(\\w+):(\\d+)", NULL, &i));
|
||||
//
|
||||
// Example: integer overflow causes failure
|
||||
// CHECK(!RE2::FullMatch("ruby:1234567891234", "\\w+:(\\d+)", &i));
|
||||
//
|
||||
// NOTE(rsc): Asking for substrings slows successful matches quite a bit.
|
||||
// This may get a little faster in the future, but right now is slower
|
||||
// than PCRE. On the other hand, failed matches run *very* fast (faster
|
||||
// than PCRE), as do matches without substring extraction.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// PARTIAL MATCHES
|
||||
//
|
||||
// You can use the "PartialMatch" operation when you want the pattern
|
||||
// to match any substring of the text.
|
||||
//
|
||||
// Example: simple search for a string:
|
||||
// CHECK(RE2::PartialMatch("hello", "ell"));
|
||||
//
|
||||
// Example: find first number in a string
|
||||
// int number;
|
||||
// CHECK(RE2::PartialMatch("x*100 + 20", "(\\d+)", &number));
|
||||
// CHECK_EQ(number, 100);
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// PRE-COMPILED REGULAR EXPRESSIONS
|
||||
//
|
||||
// RE2 makes it easy to use any string as a regular expression, without
|
||||
// requiring a separate compilation step.
|
||||
//
|
||||
// If speed is of the essence, you can create a pre-compiled "RE2"
|
||||
// object from the pattern and use it multiple times. If you do so,
|
||||
// you can typically parse text faster than with sscanf.
|
||||
//
|
||||
// Example: precompile pattern for faster matching:
|
||||
// RE2 pattern("h.*o");
|
||||
// while (ReadLine(&str)) {
|
||||
// if (RE2::FullMatch(str, pattern)) ...;
|
||||
// }
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// SCANNING TEXT INCREMENTALLY
|
||||
//
|
||||
// The "Consume" operation may be useful if you want to repeatedly
|
||||
// match regular expressions at the front of a string and skip over
|
||||
// them as they match. This requires use of the "StringPiece" type,
|
||||
// which represents a sub-range of a real string.
|
||||
//
|
||||
// Example: read lines of the form "var = value" from a string.
|
||||
// std::string contents = ...; // Fill string somehow
|
||||
// StringPiece input(contents); // Wrap a StringPiece around it
|
||||
//
|
||||
// std::string var;
|
||||
// int value;
|
||||
// while (RE2::Consume(&input, "(\\w+) = (\\d+)\n", &var, &value)) {
|
||||
// ...;
|
||||
// }
|
||||
//
|
||||
// Each successful call to "Consume" will set "var/value", and also
|
||||
// advance "input" so it points past the matched text. Note that if the
|
||||
// regular expression matches an empty string, input will advance
|
||||
// by 0 bytes. If the regular expression being used might match
|
||||
// an empty string, the loop body must check for this case and either
|
||||
// advance the string or break out of the loop.
|
||||
//
|
||||
// The "FindAndConsume" operation is similar to "Consume" but does not
|
||||
// anchor your match at the beginning of the string. For example, you
|
||||
// could extract all words from a string by repeatedly calling
|
||||
// RE2::FindAndConsume(&input, "(\\w+)", &word)
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// USING VARIABLE NUMBER OF ARGUMENTS
|
||||
//
|
||||
// The above operations require you to know the number of arguments
|
||||
// when you write the code. This is not always possible or easy (for
|
||||
// example, the regular expression may be calculated at run time).
|
||||
// You can use the "N" version of the operations when the number of
|
||||
// match arguments are determined at run time.
|
||||
//
|
||||
// Example:
|
||||
// const RE2::Arg* args[10];
|
||||
// int n;
|
||||
// // ... populate args with pointers to RE2::Arg values ...
|
||||
// // ... set n to the number of RE2::Arg objects ...
|
||||
// bool match = RE2::FullMatchN(input, pattern, args, n);
|
||||
//
|
||||
// The last statement is equivalent to
|
||||
//
|
||||
// bool match = RE2::FullMatch(input, pattern,
|
||||
// *args[0], *args[1], ..., *args[n - 1]);
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// PARSING HEX/OCTAL/C-RADIX NUMBERS
|
||||
//
|
||||
// By default, if you pass a pointer to a numeric value, the
|
||||
// corresponding text is interpreted as a base-10 number. You can
|
||||
// instead wrap the pointer with a call to one of the operators Hex(),
|
||||
// Octal(), or CRadix() to interpret the text in another base. The
|
||||
// CRadix operator interprets C-style "0" (base-8) and "0x" (base-16)
|
||||
// prefixes, but defaults to base-10.
|
||||
//
|
||||
// Example:
|
||||
// int a, b, c, d;
|
||||
// CHECK(RE2::FullMatch("100 40 0100 0x40", "(.*) (.*) (.*) (.*)",
|
||||
// RE2::Octal(&a), RE2::Hex(&b), RE2::CRadix(&c), RE2::CRadix(&d));
|
||||
// will leave 64 in a, b, c, and d.
|
||||
|
||||
#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 "re2/stringpiece.h"
|
||||
|
||||
namespace re2 {
|
||||
class Prog;
|
||||
class Regexp;
|
||||
} // namespace re2
|
||||
|
||||
namespace re2 {
|
||||
|
||||
// Interface for regular expression matching. Also corresponds to a
|
||||
// pre-compiled regular expression. An "RE2" object is safe for
|
||||
// concurrent use by multiple threads.
|
||||
class RE2 {
|
||||
public:
|
||||
// We convert user-passed pointers into special Arg objects
|
||||
class Arg;
|
||||
class Options;
|
||||
|
||||
// Defined in set.h.
|
||||
class Set;
|
||||
|
||||
enum ErrorCode {
|
||||
NoError = 0,
|
||||
|
||||
// Unexpected error
|
||||
ErrorInternal,
|
||||
|
||||
// Parse errors
|
||||
ErrorBadEscape, // bad escape sequence
|
||||
ErrorBadCharClass, // bad character class
|
||||
ErrorBadCharRange, // bad character class range
|
||||
ErrorMissingBracket, // missing closing ]
|
||||
ErrorMissingParen, // missing closing )
|
||||
ErrorUnexpectedParen, // unexpected closing )
|
||||
ErrorTrailingBackslash, // trailing \ at end of regexp
|
||||
ErrorRepeatArgument, // repeat argument missing, e.g. "*"
|
||||
ErrorRepeatSize, // bad repetition argument
|
||||
ErrorRepeatOp, // bad repetition operator
|
||||
ErrorBadPerlOp, // bad perl operator
|
||||
ErrorBadUTF8, // invalid UTF-8 in regexp
|
||||
ErrorBadNamedCapture, // bad named capture group
|
||||
ErrorPatternTooLarge // pattern too large (compile failed)
|
||||
};
|
||||
|
||||
// Predefined common options.
|
||||
// If you need more complicated things, instantiate
|
||||
// an Option class, possibly passing one of these to
|
||||
// the Option constructor, change the settings, and pass that
|
||||
// Option class to the RE2 constructor.
|
||||
enum CannedOptions {
|
||||
DefaultOptions = 0,
|
||||
Latin1, // treat input as Latin-1 (default UTF-8)
|
||||
POSIX, // POSIX syntax, leftmost-longest match
|
||||
Quiet // do not log about regexp parse errors
|
||||
};
|
||||
|
||||
// Need to have the const char* and const std::string& forms for implicit
|
||||
// conversions when passing string literals to FullMatch and PartialMatch.
|
||||
// Otherwise the StringPiece form would be sufficient.
|
||||
#ifndef SWIG
|
||||
RE2(const char* pattern);
|
||||
RE2(const std::string& pattern);
|
||||
#endif
|
||||
RE2(const StringPiece& pattern);
|
||||
RE2(const StringPiece& pattern, const Options& options);
|
||||
~RE2();
|
||||
|
||||
// Returns whether RE2 was created properly.
|
||||
bool ok() const { return error_code() == NoError; }
|
||||
|
||||
// The string specification for this RE2. E.g.
|
||||
// RE2 re("ab*c?d+");
|
||||
// re.pattern(); // "ab*c?d+"
|
||||
const std::string& pattern() const { return pattern_; }
|
||||
|
||||
// If RE2 could not be created properly, returns an error string.
|
||||
// Else returns the empty string.
|
||||
const std::string& error() const { return *error_; }
|
||||
|
||||
// If RE2 could not be created properly, returns an error code.
|
||||
// Else returns RE2::NoError (== 0).
|
||||
ErrorCode error_code() const { return error_code_; }
|
||||
|
||||
// If RE2 could not be created properly, returns the offending
|
||||
// portion of the regexp.
|
||||
const std::string& error_arg() const { return error_arg_; }
|
||||
|
||||
// Returns the program size, a very approximate measure of a regexp's "cost".
|
||||
// Larger numbers are more expensive than smaller numbers.
|
||||
int ProgramSize() const;
|
||||
int ReverseProgramSize() const;
|
||||
|
||||
// If histogram is not null, outputs the program fanout
|
||||
// as a histogram bucketed by powers of 2.
|
||||
// Returns the number of the largest non-empty bucket.
|
||||
int ProgramFanout(std::vector<int>* histogram) const;
|
||||
int ReverseProgramFanout(std::vector<int>* histogram) const;
|
||||
|
||||
// Returns the underlying Regexp; not for general use.
|
||||
// Returns entire_regexp_ so that callers don't need
|
||||
// to know about prefix_ and prefix_foldcase_.
|
||||
re2::Regexp* Regexp() const { return entire_regexp_; }
|
||||
|
||||
/***** The array-based matching interface ******/
|
||||
|
||||
// The functions here have names ending in 'N' and are used to implement
|
||||
// the functions whose names are the prefix before the 'N'. It is sometimes
|
||||
// useful to invoke them directly, but the syntax is awkward, so the 'N'-less
|
||||
// versions should be preferred.
|
||||
static bool FullMatchN(const StringPiece& text, const RE2& re,
|
||||
const Arg* const args[], int n);
|
||||
static bool PartialMatchN(const StringPiece& text, const RE2& re,
|
||||
const Arg* const args[], int n);
|
||||
static bool ConsumeN(StringPiece* input, const RE2& re,
|
||||
const Arg* const args[], int n);
|
||||
static bool FindAndConsumeN(StringPiece* 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:
|
||||
// In order to allow FullMatch() et al. to be called with a varying number
|
||||
// of arguments of varying types, we use two layers of variadic templates.
|
||||
// The first layer constructs the temporary Arg objects. The second layer
|
||||
// (above) constructs the array of pointers to the temporary Arg objects.
|
||||
|
||||
/***** The useful part: the matching interface *****/
|
||||
|
||||
// Matches "text" against "re". If pointer arguments are
|
||||
// supplied, copies matched sub-patterns into them.
|
||||
//
|
||||
// You can pass in a "const char*" or a "std::string" for "text".
|
||||
// You can pass in a "const char*" or a "std::string" or a "RE2" for "re".
|
||||
//
|
||||
// The provided pointer arguments can be pointers to any scalar numeric
|
||||
// type, or one of:
|
||||
// std::string (matched piece is copied to string)
|
||||
// StringPiece (StringPiece is mutated to point to matched piece)
|
||||
// T (where "bool T::ParseFrom(const char*, size_t)" exists)
|
||||
// (void*)NULL (the corresponding matched sub-pattern is not copied)
|
||||
//
|
||||
// Returns true iff all of the following conditions are satisfied:
|
||||
// a. "text" matches "re" fully - from the beginning to the end of "text".
|
||||
// b. The number of matched sub-patterns is >= number of supplied pointers.
|
||||
// c. The "i"th argument has a suitable type for holding the
|
||||
// string captured as the "i"th sub-pattern. If you pass in
|
||||
// NULL for the "i"th argument, or pass fewer arguments than
|
||||
// number of sub-patterns, the "i"th captured sub-pattern is
|
||||
// ignored.
|
||||
//
|
||||
// CAVEAT: An optional sub-pattern that does not exist in the
|
||||
// matched string is assigned the empty string. Therefore, the
|
||||
// following will return false (because the empty string is not a
|
||||
// valid number):
|
||||
// int number;
|
||||
// RE2::FullMatch("abc", "[a-z]+(\\d+)?", &number);
|
||||
template <typename... A>
|
||||
static bool FullMatch(const StringPiece& text, const RE2& re, A&&... a) {
|
||||
return Apply(FullMatchN, text, re, Arg(std::forward<A>(a))...);
|
||||
}
|
||||
|
||||
// Like FullMatch(), except that "re" is allowed to match a substring
|
||||
// of "text".
|
||||
//
|
||||
// Returns true iff all of the following conditions are satisfied:
|
||||
// a. "text" matches "re" partially - for some substring of "text".
|
||||
// b. The number of matched sub-patterns is >= number of supplied pointers.
|
||||
// c. The "i"th argument has a suitable type for holding the
|
||||
// string captured as the "i"th sub-pattern. If you pass in
|
||||
// NULL for the "i"th argument, or pass fewer arguments than
|
||||
// number of sub-patterns, the "i"th captured sub-pattern is
|
||||
// ignored.
|
||||
template <typename... A>
|
||||
static bool PartialMatch(const StringPiece& text, const RE2& re, A&&... a) {
|
||||
return Apply(PartialMatchN, text, re, Arg(std::forward<A>(a))...);
|
||||
}
|
||||
|
||||
// Like FullMatch() and PartialMatch(), except that "re" has to match
|
||||
// a prefix of the text, and "input" is advanced past the matched
|
||||
// text. Note: "input" is modified iff this routine returns true
|
||||
// and "re" matched a non-empty substring of "input".
|
||||
//
|
||||
// Returns true iff all of the following conditions are satisfied:
|
||||
// a. "input" matches "re" partially - for some prefix of "input".
|
||||
// b. The number of matched sub-patterns is >= number of supplied pointers.
|
||||
// c. The "i"th argument has a suitable type for holding the
|
||||
// string captured as the "i"th sub-pattern. If you pass in
|
||||
// NULL for the "i"th argument, or pass fewer arguments than
|
||||
// number of sub-patterns, the "i"th captured sub-pattern is
|
||||
// ignored.
|
||||
template <typename... A>
|
||||
static bool Consume(StringPiece* input, const RE2& re, A&&... a) {
|
||||
return Apply(ConsumeN, input, re, Arg(std::forward<A>(a))...);
|
||||
}
|
||||
|
||||
// Like Consume(), but does not anchor the match at the beginning of
|
||||
// the text. That is, "re" need not start its match at the beginning
|
||||
// of "input". For example, "FindAndConsume(s, "(\\w+)", &word)" finds
|
||||
// the next word in "s" and stores it in "word".
|
||||
//
|
||||
// Returns true iff all of the following conditions are satisfied:
|
||||
// a. "input" matches "re" partially - for some substring of "input".
|
||||
// b. The number of matched sub-patterns is >= number of supplied pointers.
|
||||
// c. The "i"th argument has a suitable type for holding the
|
||||
// string captured as the "i"th sub-pattern. If you pass in
|
||||
// NULL for the "i"th argument, or pass fewer arguments than
|
||||
// number of sub-patterns, the "i"th captured sub-pattern is
|
||||
// ignored.
|
||||
template <typename... A>
|
||||
static bool FindAndConsume(StringPiece* input, const RE2& re, A&&... a) {
|
||||
return Apply(FindAndConsumeN, input, re, Arg(std::forward<A>(a))...);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Replace the first match of "re" in "str" with "rewrite".
|
||||
// Within "rewrite", backslash-escaped digits (\1 to \9) can be
|
||||
// used to insert text matching corresponding parenthesized group
|
||||
// from the pattern. \0 in "rewrite" refers to the entire matching
|
||||
// text. E.g.,
|
||||
//
|
||||
// std::string s = "yabba dabba doo";
|
||||
// CHECK(RE2::Replace(&s, "b+", "d"));
|
||||
//
|
||||
// will leave "s" containing "yada dabba doo"
|
||||
//
|
||||
// Returns true if the pattern matches and a replacement occurs,
|
||||
// false otherwise.
|
||||
static bool Replace(std::string* str,
|
||||
const RE2& re,
|
||||
const StringPiece& rewrite);
|
||||
|
||||
// Like Replace(), except replaces successive non-overlapping occurrences
|
||||
// of the pattern in the string with the rewrite. E.g.
|
||||
//
|
||||
// std::string s = "yabba dabba doo";
|
||||
// CHECK(RE2::GlobalReplace(&s, "b+", "d"));
|
||||
//
|
||||
// will leave "s" containing "yada dada doo"
|
||||
// Replacements are not subject to re-matching.
|
||||
//
|
||||
// Because GlobalReplace only replaces non-overlapping matches,
|
||||
// replacing "ana" within "banana" makes only one replacement, not two.
|
||||
//
|
||||
// Returns the number of replacements made.
|
||||
static int GlobalReplace(std::string* str,
|
||||
const RE2& re,
|
||||
const StringPiece& rewrite);
|
||||
|
||||
// Like Replace, except that if the pattern matches, "rewrite"
|
||||
// is copied into "out" with substitutions. The non-matching
|
||||
// portions of "text" are ignored.
|
||||
//
|
||||
// Returns true iff a match occurred and the extraction happened
|
||||
// successfully; if no match occurs, the string is left unaffected.
|
||||
//
|
||||
// REQUIRES: "text" must not alias any part of "*out".
|
||||
static bool Extract(const StringPiece& text,
|
||||
const RE2& re,
|
||||
const StringPiece& rewrite,
|
||||
std::string* out);
|
||||
|
||||
// Escapes all potentially meaningful regexp characters in
|
||||
// 'unquoted'. The returned string, used as a regular expression,
|
||||
// will match exactly the original string. For example,
|
||||
// 1.5-2.0?
|
||||
// may become:
|
||||
// 1\.5\-2\.0\?
|
||||
static std::string QuoteMeta(const StringPiece& unquoted);
|
||||
|
||||
// Computes range for any strings matching regexp. The min and max can in
|
||||
// some cases be arbitrarily precise, so the caller gets to specify the
|
||||
// maximum desired length of string returned.
|
||||
//
|
||||
// Assuming PossibleMatchRange(&min, &max, N) returns successfully, any
|
||||
// string s that is an anchored match for this regexp satisfies
|
||||
// min <= s && s <= max.
|
||||
//
|
||||
// Note that PossibleMatchRange() will only consider the first copy of an
|
||||
// infinitely repeated element (i.e., any regexp element followed by a '*' or
|
||||
// '+' operator). Regexps with "{N}" constructions are not affected, as those
|
||||
// do not compile down to infinite repetitions.
|
||||
//
|
||||
// Returns true on success, false on error.
|
||||
bool PossibleMatchRange(std::string* min, std::string* max,
|
||||
int maxlen) const;
|
||||
|
||||
// Generic matching interface
|
||||
|
||||
// Type of match.
|
||||
enum Anchor {
|
||||
UNANCHORED, // No anchoring
|
||||
ANCHOR_START, // Anchor at start only
|
||||
ANCHOR_BOTH // Anchor at start and end
|
||||
};
|
||||
|
||||
// Return the number of capturing subpatterns, or -1 if the
|
||||
// regexp wasn't valid on construction. The overall match ($0)
|
||||
// does not count: if the regexp is "(a)(b)", returns 2.
|
||||
int NumberOfCapturingGroups() const { return num_captures_; }
|
||||
|
||||
// Return a map from names to capturing indices.
|
||||
// The map records the index of the leftmost group
|
||||
// with the given name.
|
||||
// Only valid until the re is deleted.
|
||||
const std::map<std::string, int>& NamedCapturingGroups() const;
|
||||
|
||||
// Return a map from capturing indices to names.
|
||||
// The map has no entries for unnamed groups.
|
||||
// Only valid until the re is deleted.
|
||||
const std::map<int, std::string>& CapturingGroupNames() const;
|
||||
|
||||
// General matching routine.
|
||||
// Match against text starting at offset startpos
|
||||
// and stopping the search at offset endpos.
|
||||
// Returns true if match found, false if not.
|
||||
// On a successful match, fills in submatch[] (up to nsubmatch entries)
|
||||
// with information about submatches.
|
||||
// I.e. matching RE2("(foo)|(bar)baz") on "barbazbla" will return true, with
|
||||
// submatch[0] = "barbaz", submatch[1].data() = NULL, submatch[2] = "bar",
|
||||
// submatch[3].data() = NULL, ..., up to submatch[nsubmatch-1].data() = NULL.
|
||||
// Caveat: submatch[] may be clobbered even on match failure.
|
||||
//
|
||||
// Don't ask for more match information than you will use:
|
||||
// runs much faster with nsubmatch == 1 than nsubmatch > 1, and
|
||||
// runs even faster if nsubmatch == 0.
|
||||
// Doesn't make sense to use nsubmatch > 1 + NumberOfCapturingGroups(),
|
||||
// but will be handled correctly.
|
||||
//
|
||||
// Passing text == StringPiece(NULL, 0) will be handled like any other
|
||||
// empty string, but note that on return, it will not be possible to tell
|
||||
// whether submatch i matched the empty string or did not match:
|
||||
// either way, submatch[i].data() == NULL.
|
||||
bool Match(const StringPiece& text,
|
||||
size_t startpos,
|
||||
size_t endpos,
|
||||
Anchor re_anchor,
|
||||
StringPiece* submatch,
|
||||
int nsubmatch) const;
|
||||
|
||||
// Check that the given rewrite string is suitable for use with this
|
||||
// regular expression. It checks that:
|
||||
// * The regular expression has enough parenthesized subexpressions
|
||||
// to satisfy all of the \N tokens in rewrite
|
||||
// * The rewrite string doesn't have any syntax errors. E.g.,
|
||||
// '\' followed by anything other than a digit or '\'.
|
||||
// A true return value guarantees that Replace() and Extract() won't
|
||||
// fail because of a bad rewrite string.
|
||||
bool CheckRewriteString(const StringPiece& rewrite,
|
||||
std::string* error) const;
|
||||
|
||||
// Returns the maximum submatch needed for the rewrite to be done by
|
||||
// Replace(). E.g. if rewrite == "foo \\2,\\1", returns 2.
|
||||
static int MaxSubmatch(const StringPiece& rewrite);
|
||||
|
||||
// Append the "rewrite" string, with backslash subsitutions from "vec",
|
||||
// to string "out".
|
||||
// Returns true on success. This method can fail because of a malformed
|
||||
// rewrite string. CheckRewriteString guarantees that the rewrite will
|
||||
// be sucessful.
|
||||
bool Rewrite(std::string* out,
|
||||
const StringPiece& rewrite,
|
||||
const StringPiece* vec,
|
||||
int veclen) const;
|
||||
|
||||
// Constructor options
|
||||
class Options {
|
||||
public:
|
||||
// The options are (defaults in parentheses):
|
||||
//
|
||||
// utf8 (true) text and pattern are UTF-8; otherwise Latin-1
|
||||
// posix_syntax (false) restrict regexps to POSIX egrep syntax
|
||||
// longest_match (false) search for longest match, not first match
|
||||
// log_errors (true) log syntax and execution errors to ERROR
|
||||
// max_mem (see below) approx. max memory footprint of RE2
|
||||
// literal (false) interpret string as literal, not regexp
|
||||
// never_nl (false) never match \n, even if it is in regexp
|
||||
// dot_nl (false) dot matches everything including new line
|
||||
// never_capture (false) parse all parens as non-capturing
|
||||
// case_sensitive (true) match is case-sensitive (regexp can override
|
||||
// with (?i) unless in posix_syntax mode)
|
||||
//
|
||||
// The following options are only consulted when posix_syntax == true.
|
||||
// When posix_syntax == false, these features are always enabled and
|
||||
// cannot be turned off; to perform multi-line matching in that case,
|
||||
// begin the regexp with (?m).
|
||||
// perl_classes (false) allow Perl's \d \s \w \D \S \W
|
||||
// word_boundary (false) allow Perl's \b \B (word boundary and not)
|
||||
// one_line (false) ^ and $ only match beginning and end of text
|
||||
//
|
||||
// The max_mem option controls how much memory can be used
|
||||
// to hold the compiled form of the regexp (the Prog) and
|
||||
// its cached DFA graphs. Code Search placed limits on the number
|
||||
// of Prog instructions and DFA states: 10,000 for both.
|
||||
// In RE2, those limits would translate to about 240 KB per Prog
|
||||
// and perhaps 2.5 MB per DFA (DFA state sizes vary by regexp; RE2 does a
|
||||
// better job of keeping them small than Code Search did).
|
||||
// Each RE2 has two Progs (one forward, one reverse), and each Prog
|
||||
// can have two DFAs (one first match, one longest match).
|
||||
// That makes 4 DFAs:
|
||||
//
|
||||
// forward, first-match - used for UNANCHORED or ANCHOR_START searches
|
||||
// if opt.longest_match() == false
|
||||
// forward, longest-match - used for all ANCHOR_BOTH searches,
|
||||
// and the other two kinds if
|
||||
// opt.longest_match() == true
|
||||
// reverse, first-match - never used
|
||||
// reverse, longest-match - used as second phase for unanchored searches
|
||||
//
|
||||
// The RE2 memory budget is statically divided between the two
|
||||
// Progs and then the DFAs: two thirds to the forward Prog
|
||||
// and one third to the reverse Prog. The forward Prog gives half
|
||||
// of what it has left over to each of its DFAs. The reverse Prog
|
||||
// gives it all to its longest-match DFA.
|
||||
//
|
||||
// Once a DFA fills its budget, it flushes its cache and starts over.
|
||||
// If this happens too often, RE2 falls back on the NFA implementation.
|
||||
|
||||
// For now, make the default budget something close to Code Search.
|
||||
static const int kDefaultMaxMem = 8<<20;
|
||||
|
||||
enum Encoding {
|
||||
EncodingUTF8 = 1,
|
||||
EncodingLatin1
|
||||
};
|
||||
|
||||
Options() :
|
||||
encoding_(EncodingUTF8),
|
||||
posix_syntax_(false),
|
||||
longest_match_(false),
|
||||
log_errors_(true),
|
||||
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) {
|
||||
}
|
||||
|
||||
/*implicit*/ 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_;
|
||||
};
|
||||
|
||||
// Returns the options set in the constructor.
|
||||
const Options& options() const { return options_; }
|
||||
|
||||
// Argument converters; see below.
|
||||
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(const StringPiece& pattern, const Options& options);
|
||||
|
||||
bool DoMatch(const StringPiece& text,
|
||||
Anchor re_anchor,
|
||||
size_t* consumed,
|
||||
const Arg* const args[],
|
||||
int n) const;
|
||||
|
||||
re2::Prog* ReverseProg() const;
|
||||
|
||||
std::string pattern_; // string regular expression
|
||||
Options options_; // option flags
|
||||
re2::Regexp* entire_regexp_; // parsed regular expression
|
||||
const std::string* error_; // error indicator (or points to empty string)
|
||||
ErrorCode error_code_; // error code
|
||||
std::string error_arg_; // fragment of regexp showing error
|
||||
std::string prefix_; // required prefix (before suffix_regexp_)
|
||||
bool prefix_foldcase_; // prefix_ is ASCII case-insensitive
|
||||
re2::Regexp* suffix_regexp_; // parsed regular expression, prefix_ removed
|
||||
re2::Prog* prog_; // compiled program for regexp
|
||||
int num_captures_; // number of capturing groups
|
||||
bool is_one_pass_; // can use prog_->SearchOnePass?
|
||||
|
||||
// Reverse Prog for DFA execution only
|
||||
mutable re2::Prog* rprog_;
|
||||
// Map from capture names to indices
|
||||
mutable const std::map<std::string, int>* named_groups_;
|
||||
// Map from capture indices to names
|
||||
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;
|
||||
};
|
||||
|
||||
/***** Implementation details *****/
|
||||
|
||||
namespace re2_internal {
|
||||
|
||||
// Types for which the 3-ary Parse() function template has specializations.
|
||||
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<StringPiece> : 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);
|
||||
|
||||
// Types for which the 4-ary Parse() function template has specializations.
|
||||
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);
|
||||
|
||||
} // namespace re2_internal
|
||||
|
||||
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* /*str*/, size_t /*n*/, void* /*dest*/) {
|
||||
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
|
||||
// Silence warnings about missing initializers for members of LazyRE2.
|
||||
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 6
|
||||
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
#endif
|
||||
|
||||
// Helper for writing global or static RE2s safely.
|
||||
// Write
|
||||
// static LazyRE2 re = {".*"};
|
||||
// and then use *re instead of writing
|
||||
// static RE2 re(".*");
|
||||
// The former is more careful about multithreaded
|
||||
// situations than the latter.
|
||||
//
|
||||
// N.B. This class never deletes the RE2 object that
|
||||
// it constructs: that's a feature, so that it can be used
|
||||
// for global and function static variables.
|
||||
class LazyRE2 {
|
||||
private:
|
||||
struct NoArg {};
|
||||
|
||||
public:
|
||||
typedef RE2 element_type; // support std::pointer_traits
|
||||
|
||||
// Constructor omitted to preserve braced initialization in C++98.
|
||||
|
||||
// Pretend to be a pointer to Type (never NULL due to on-demand creation):
|
||||
RE2& operator*() const { return *get(); }
|
||||
RE2* operator->() const { return get(); }
|
||||
|
||||
// Named accessor/initializer:
|
||||
RE2* get() const {
|
||||
std::call_once(once_, &LazyRE2::Init, this);
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
// All data fields must be public to support {"foo"} initialization.
|
||||
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&); // disallowed
|
||||
};
|
||||
#endif
|
||||
|
||||
namespace hooks {
|
||||
|
||||
// Most platforms support thread_local. Older versions of iOS don't support
|
||||
// thread_local, but for the sake of brevity, we lump together all versions
|
||||
// of Apple platforms that aren't macOS. If an iOS application really needs
|
||||
// the context pointee someday, we can get more specific then...
|
||||
//
|
||||
// As per https://github.com/google/re2/issues/325, thread_local support in
|
||||
// MinGW seems to be buggy. (FWIW, Abseil folks also avoid it.)
|
||||
#define RE2_HAVE_THREAD_LOCAL
|
||||
#if (defined(__APPLE__) && !(defined(TARGET_OS_OSX) && TARGET_OS_OSX)) || defined(__MINGW32__)
|
||||
#undef RE2_HAVE_THREAD_LOCAL
|
||||
#endif
|
||||
|
||||
// A hook must not make any assumptions regarding the lifetime of the context
|
||||
// pointee beyond the current invocation of the hook. Pointers and references
|
||||
// obtained via the context pointee should be considered invalidated when the
|
||||
// hook returns. Hence, any data about the context pointee (e.g. its pattern)
|
||||
// would have to be copied in order for it to be kept for an indefinite time.
|
||||
//
|
||||
// A hook must not use RE2 for matching. Control flow reentering RE2::Match()
|
||||
// could result in infinite mutual recursion. To discourage that possibility,
|
||||
// RE2 will not maintain the context pointer correctly when used in that way.
|
||||
#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 {
|
||||
// Nothing yet...
|
||||
};
|
||||
|
||||
#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
|
||||
|
||||
} // namespace hooks
|
||||
|
||||
} // namespace re2
|
||||
|
||||
using re2::RE2;
|
||||
using re2::LazyRE2;
|
||||
|
||||
#endif // RE2_RE2_H_
|
||||
665
Pods/gRPC-C++/third_party/re2/re2/regexp.h
generated
vendored
Normal file
665
Pods/gRPC-C++/third_party/re2/re2/regexp.h
generated
vendored
Normal file
@@ -0,0 +1,665 @@
|
||||
// Copyright 2006 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RE2_REGEXP_H_
|
||||
#define RE2_REGEXP_H_
|
||||
|
||||
// --- SPONSORED LINK --------------------------------------------------
|
||||
// If you want to use this library for regular expression matching,
|
||||
// you should use re2/re2.h, which provides a class RE2 that
|
||||
// mimics the PCRE interface provided by PCRE's C++ wrappers.
|
||||
// This header describes the low-level interface used to implement RE2
|
||||
// and may change in backwards-incompatible ways from time to time.
|
||||
// In contrast, RE2's interface will not.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// Regular expression library: parsing, execution, and manipulation
|
||||
// of regular expressions.
|
||||
//
|
||||
// Any operation that traverses the Regexp structures should be written
|
||||
// using Regexp::Walker (see walker-inl.h), not recursively, because deeply nested
|
||||
// regular expressions such as x++++++++++++++++++++... might cause recursive
|
||||
// traversals to overflow the stack.
|
||||
//
|
||||
// It is the caller's responsibility to provide appropriate mutual exclusion
|
||||
// around manipulation of the regexps. RE2 does this.
|
||||
//
|
||||
// PARSING
|
||||
//
|
||||
// Regexp::Parse parses regular expressions encoded in UTF-8.
|
||||
// The default syntax is POSIX extended regular expressions,
|
||||
// with the following changes:
|
||||
//
|
||||
// 1. Backreferences (optional in POSIX EREs) are not supported.
|
||||
// (Supporting them precludes the use of DFA-based
|
||||
// matching engines.)
|
||||
//
|
||||
// 2. Collating elements and collation classes are not supported.
|
||||
// (No one has needed or wanted them.)
|
||||
//
|
||||
// The exact syntax accepted can be modified by passing flags to
|
||||
// Regexp::Parse. In particular, many of the basic Perl additions
|
||||
// are available. The flags are documented below (search for LikePerl).
|
||||
//
|
||||
// If parsed with the flag Regexp::Latin1, both the regular expression
|
||||
// and the input to the matching routines are assumed to be encoded in
|
||||
// Latin-1, not UTF-8.
|
||||
//
|
||||
// EXECUTION
|
||||
//
|
||||
// Once Regexp has parsed a regular expression, it provides methods
|
||||
// to search text using that regular expression. These methods are
|
||||
// implemented via calling out to other regular expression libraries.
|
||||
// (Let's call them the sublibraries.)
|
||||
//
|
||||
// To call a sublibrary, Regexp does not simply prepare a
|
||||
// string version of the regular expression and hand it to the
|
||||
// sublibrary. Instead, Regexp prepares, from its own parsed form, the
|
||||
// corresponding internal representation used by the sublibrary.
|
||||
// This has the drawback of needing to know the internal representation
|
||||
// used by the sublibrary, but it has two important benefits:
|
||||
//
|
||||
// 1. The syntax and meaning of regular expressions is guaranteed
|
||||
// to be that used by Regexp's parser, not the syntax expected
|
||||
// by the sublibrary. Regexp might accept a restricted or
|
||||
// expanded syntax for regular expressions as compared with
|
||||
// the sublibrary. As long as Regexp can translate from its
|
||||
// internal form into the sublibrary's, clients need not know
|
||||
// exactly which sublibrary they are using.
|
||||
//
|
||||
// 2. The sublibrary parsers are bypassed. For whatever reason,
|
||||
// sublibrary regular expression parsers often have security
|
||||
// problems. For example, plan9grep's regular expression parser
|
||||
// has a buffer overflow in its handling of large character
|
||||
// classes, and PCRE's parser has had buffer overflow problems
|
||||
// in the past. Security-team requires sandboxing of sublibrary
|
||||
// regular expression parsers. Avoiding the sublibrary parsers
|
||||
// avoids the sandbox.
|
||||
//
|
||||
// The execution methods we use now are provided by the compiled form,
|
||||
// Prog, described in prog.h
|
||||
//
|
||||
// MANIPULATION
|
||||
//
|
||||
// Unlike other regular expression libraries, Regexp makes its parsed
|
||||
// form accessible to clients, so that client code can analyze the
|
||||
// parsed regular expressions.
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "util/util.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/utf.h"
|
||||
#include "re2/stringpiece.h"
|
||||
|
||||
namespace re2 {
|
||||
|
||||
// Keep in sync with string list kOpcodeNames[] in testing/dump.cc
|
||||
enum RegexpOp {
|
||||
// Matches no strings.
|
||||
kRegexpNoMatch = 1,
|
||||
|
||||
// Matches empty string.
|
||||
kRegexpEmptyMatch,
|
||||
|
||||
// Matches rune_.
|
||||
kRegexpLiteral,
|
||||
|
||||
// Matches runes_.
|
||||
kRegexpLiteralString,
|
||||
|
||||
// Matches concatenation of sub_[0..nsub-1].
|
||||
kRegexpConcat,
|
||||
// Matches union of sub_[0..nsub-1].
|
||||
kRegexpAlternate,
|
||||
|
||||
// Matches sub_[0] zero or more times.
|
||||
kRegexpStar,
|
||||
// Matches sub_[0] one or more times.
|
||||
kRegexpPlus,
|
||||
// Matches sub_[0] zero or one times.
|
||||
kRegexpQuest,
|
||||
|
||||
// Matches sub_[0] at least min_ times, at most max_ times.
|
||||
// max_ == -1 means no upper limit.
|
||||
kRegexpRepeat,
|
||||
|
||||
// Parenthesized (capturing) subexpression. Index is cap_.
|
||||
// Optionally, capturing name is name_.
|
||||
kRegexpCapture,
|
||||
|
||||
// Matches any character.
|
||||
kRegexpAnyChar,
|
||||
|
||||
// Matches any byte [sic].
|
||||
kRegexpAnyByte,
|
||||
|
||||
// Matches empty string at beginning of line.
|
||||
kRegexpBeginLine,
|
||||
// Matches empty string at end of line.
|
||||
kRegexpEndLine,
|
||||
|
||||
// Matches word boundary "\b".
|
||||
kRegexpWordBoundary,
|
||||
// Matches not-a-word boundary "\B".
|
||||
kRegexpNoWordBoundary,
|
||||
|
||||
// Matches empty string at beginning of text.
|
||||
kRegexpBeginText,
|
||||
// Matches empty string at end of text.
|
||||
kRegexpEndText,
|
||||
|
||||
// Matches character class given by cc_.
|
||||
kRegexpCharClass,
|
||||
|
||||
// Forces match of entire expression right now,
|
||||
// with match ID match_id_ (used by RE2::Set).
|
||||
kRegexpHaveMatch,
|
||||
|
||||
kMaxRegexpOp = kRegexpHaveMatch,
|
||||
};
|
||||
|
||||
// Keep in sync with string list in regexp.cc
|
||||
enum RegexpStatusCode {
|
||||
// No error
|
||||
kRegexpSuccess = 0,
|
||||
|
||||
// Unexpected error
|
||||
kRegexpInternalError,
|
||||
|
||||
// Parse errors
|
||||
kRegexpBadEscape, // bad escape sequence
|
||||
kRegexpBadCharClass, // bad character class
|
||||
kRegexpBadCharRange, // bad character class range
|
||||
kRegexpMissingBracket, // missing closing ]
|
||||
kRegexpMissingParen, // missing closing )
|
||||
kRegexpUnexpectedParen, // unexpected closing )
|
||||
kRegexpTrailingBackslash, // at end of regexp
|
||||
kRegexpRepeatArgument, // repeat argument missing, e.g. "*"
|
||||
kRegexpRepeatSize, // bad repetition argument
|
||||
kRegexpRepeatOp, // bad repetition operator
|
||||
kRegexpBadPerlOp, // bad perl operator
|
||||
kRegexpBadUTF8, // invalid UTF-8 in regexp
|
||||
kRegexpBadNamedCapture, // bad named capture
|
||||
};
|
||||
|
||||
// Error status for certain operations.
|
||||
class RegexpStatus {
|
||||
public:
|
||||
RegexpStatus() : code_(kRegexpSuccess), tmp_(NULL) {}
|
||||
~RegexpStatus() { delete tmp_; }
|
||||
|
||||
void set_code(RegexpStatusCode code) { code_ = code; }
|
||||
void set_error_arg(const StringPiece& error_arg) { error_arg_ = error_arg; }
|
||||
void set_tmp(std::string* tmp) { delete tmp_; tmp_ = tmp; }
|
||||
RegexpStatusCode code() const { return code_; }
|
||||
const StringPiece& error_arg() const { return error_arg_; }
|
||||
bool ok() const { return code() == kRegexpSuccess; }
|
||||
|
||||
// Copies state from status.
|
||||
void Copy(const RegexpStatus& status);
|
||||
|
||||
// Returns text equivalent of code, e.g.:
|
||||
// "Bad character class"
|
||||
static std::string CodeText(RegexpStatusCode code);
|
||||
|
||||
// Returns text describing error, e.g.:
|
||||
// "Bad character class: [z-a]"
|
||||
std::string Text() const;
|
||||
|
||||
private:
|
||||
RegexpStatusCode code_; // Kind of error
|
||||
StringPiece error_arg_; // Piece of regexp containing syntax error.
|
||||
std::string* tmp_; // Temporary storage, possibly where error_arg_ is.
|
||||
|
||||
RegexpStatus(const RegexpStatus&) = delete;
|
||||
RegexpStatus& operator=(const RegexpStatus&) = delete;
|
||||
};
|
||||
|
||||
// Compiled form; see prog.h
|
||||
class Prog;
|
||||
|
||||
struct RuneRange {
|
||||
RuneRange() : lo(0), hi(0) { }
|
||||
RuneRange(int l, int h) : lo(l), hi(h) { }
|
||||
Rune lo;
|
||||
Rune hi;
|
||||
};
|
||||
|
||||
// Less-than on RuneRanges treats a == b if they overlap at all.
|
||||
// This lets us look in a set to find the range covering a particular Rune.
|
||||
struct RuneRangeLess {
|
||||
bool operator()(const RuneRange& a, const RuneRange& b) const {
|
||||
return a.hi < b.lo;
|
||||
}
|
||||
};
|
||||
|
||||
class CharClassBuilder;
|
||||
|
||||
class CharClass {
|
||||
public:
|
||||
void Delete();
|
||||
|
||||
typedef RuneRange* iterator;
|
||||
iterator begin() { return ranges_; }
|
||||
iterator end() { return ranges_ + nranges_; }
|
||||
|
||||
int size() { return nrunes_; }
|
||||
bool empty() { return nrunes_ == 0; }
|
||||
bool full() { return nrunes_ == Runemax+1; }
|
||||
bool FoldsASCII() { return folds_ascii_; }
|
||||
|
||||
bool Contains(Rune r) const;
|
||||
CharClass* Negate();
|
||||
|
||||
private:
|
||||
CharClass(); // not implemented
|
||||
~CharClass(); // not implemented
|
||||
static CharClass* New(size_t maxranges);
|
||||
|
||||
friend class CharClassBuilder;
|
||||
|
||||
bool folds_ascii_;
|
||||
int nrunes_;
|
||||
RuneRange *ranges_;
|
||||
int nranges_;
|
||||
|
||||
CharClass(const CharClass&) = delete;
|
||||
CharClass& operator=(const CharClass&) = delete;
|
||||
};
|
||||
|
||||
class Regexp {
|
||||
public:
|
||||
|
||||
// Flags for parsing. Can be ORed together.
|
||||
enum ParseFlags {
|
||||
NoParseFlags = 0,
|
||||
FoldCase = 1<<0, // Fold case during matching (case-insensitive).
|
||||
Literal = 1<<1, // Treat s as literal string instead of a regexp.
|
||||
ClassNL = 1<<2, // Allow char classes like [^a-z] and \D and \s
|
||||
// and [[:space:]] to match newline.
|
||||
DotNL = 1<<3, // Allow . to match newline.
|
||||
MatchNL = ClassNL | DotNL,
|
||||
OneLine = 1<<4, // Treat ^ and $ as only matching at beginning and
|
||||
// end of text, not around embedded newlines.
|
||||
// (Perl's default)
|
||||
Latin1 = 1<<5, // Regexp and text are in Latin1, not UTF-8.
|
||||
NonGreedy = 1<<6, // Repetition operators are non-greedy by default.
|
||||
PerlClasses = 1<<7, // Allow Perl character classes like \d.
|
||||
PerlB = 1<<8, // Allow Perl's \b and \B.
|
||||
PerlX = 1<<9, // Perl extensions:
|
||||
// non-capturing parens - (?: )
|
||||
// non-greedy operators - *? +? ?? {}?
|
||||
// flag edits - (?i) (?-i) (?i: )
|
||||
// i - FoldCase
|
||||
// m - !OneLine
|
||||
// s - DotNL
|
||||
// U - NonGreedy
|
||||
// line ends: \A \z
|
||||
// \Q and \E to disable/enable metacharacters
|
||||
// (?P<name>expr) for named captures
|
||||
// \C to match any single byte
|
||||
UnicodeGroups = 1<<10, // Allow \p{Han} for Unicode Han group
|
||||
// and \P{Han} for its negation.
|
||||
NeverNL = 1<<11, // Never match NL, even if the regexp mentions
|
||||
// it explicitly.
|
||||
NeverCapture = 1<<12, // Parse all parens as non-capturing.
|
||||
|
||||
// As close to Perl as we can get.
|
||||
LikePerl = ClassNL | OneLine | PerlClasses | PerlB | PerlX |
|
||||
UnicodeGroups,
|
||||
|
||||
// Internal use only.
|
||||
WasDollar = 1<<13, // on kRegexpEndText: was $ in regexp text
|
||||
AllParseFlags = (1<<14)-1,
|
||||
};
|
||||
|
||||
// Get. No set, Regexps are logically immutable once created.
|
||||
RegexpOp op() { return static_cast<RegexpOp>(op_); }
|
||||
int nsub() { return nsub_; }
|
||||
bool simple() { return simple_ != 0; }
|
||||
ParseFlags parse_flags() { return static_cast<ParseFlags>(parse_flags_); }
|
||||
int Ref(); // For testing.
|
||||
|
||||
Regexp** sub() {
|
||||
if(nsub_ <= 1)
|
||||
return &subone_;
|
||||
else
|
||||
return submany_;
|
||||
}
|
||||
|
||||
int min() { DCHECK_EQ(op_, kRegexpRepeat); return min_; }
|
||||
int max() { DCHECK_EQ(op_, kRegexpRepeat); return max_; }
|
||||
Rune rune() { DCHECK_EQ(op_, kRegexpLiteral); return rune_; }
|
||||
CharClass* cc() { DCHECK_EQ(op_, kRegexpCharClass); return cc_; }
|
||||
int cap() { DCHECK_EQ(op_, kRegexpCapture); return cap_; }
|
||||
const std::string* name() { DCHECK_EQ(op_, kRegexpCapture); return name_; }
|
||||
Rune* runes() { DCHECK_EQ(op_, kRegexpLiteralString); return runes_; }
|
||||
int nrunes() { DCHECK_EQ(op_, kRegexpLiteralString); return nrunes_; }
|
||||
int match_id() { DCHECK_EQ(op_, kRegexpHaveMatch); return match_id_; }
|
||||
|
||||
// Increments reference count, returns object as convenience.
|
||||
Regexp* Incref();
|
||||
|
||||
// Decrements reference count and deletes this object if count reaches 0.
|
||||
void Decref();
|
||||
|
||||
// Parses string s to produce regular expression, returned.
|
||||
// Caller must release return value with re->Decref().
|
||||
// On failure, sets *status (if status != NULL) and returns NULL.
|
||||
static Regexp* Parse(const StringPiece& s, ParseFlags flags,
|
||||
RegexpStatus* status);
|
||||
|
||||
// Returns a _new_ simplified version of the current regexp.
|
||||
// Does not edit the current regexp.
|
||||
// Caller must release return value with re->Decref().
|
||||
// Simplified means that counted repetition has been rewritten
|
||||
// into simpler terms and all Perl/POSIX features have been
|
||||
// removed. The result will capture exactly the same
|
||||
// subexpressions the original did, unless formatted with ToString.
|
||||
Regexp* Simplify();
|
||||
friend class CoalesceWalker;
|
||||
friend class SimplifyWalker;
|
||||
|
||||
// Parses the regexp src and then simplifies it and sets *dst to the
|
||||
// string representation of the simplified form. Returns true on success.
|
||||
// Returns false and sets *status (if status != NULL) on parse error.
|
||||
static bool SimplifyRegexp(const StringPiece& src, ParseFlags flags,
|
||||
std::string* dst, RegexpStatus* status);
|
||||
|
||||
// Returns the number of capturing groups in the regexp.
|
||||
int NumCaptures();
|
||||
friend class NumCapturesWalker;
|
||||
|
||||
// Returns a map from names to capturing group indices,
|
||||
// or NULL if the regexp contains no named capture groups.
|
||||
// The caller is responsible for deleting the map.
|
||||
std::map<std::string, int>* NamedCaptures();
|
||||
|
||||
// Returns a map from capturing group indices to capturing group
|
||||
// names or NULL if the regexp contains no named capture groups. The
|
||||
// caller is responsible for deleting the map.
|
||||
std::map<int, std::string>* CaptureNames();
|
||||
|
||||
// Returns a string representation of the current regexp,
|
||||
// using as few parentheses as possible.
|
||||
std::string ToString();
|
||||
|
||||
// Convenience functions. They consume the passed reference,
|
||||
// so in many cases you should use, e.g., Plus(re->Incref(), flags).
|
||||
// They do not consume allocated arrays like subs or runes.
|
||||
static Regexp* Plus(Regexp* sub, ParseFlags flags);
|
||||
static Regexp* Star(Regexp* sub, ParseFlags flags);
|
||||
static Regexp* Quest(Regexp* sub, ParseFlags flags);
|
||||
static Regexp* Concat(Regexp** subs, int nsubs, ParseFlags flags);
|
||||
static Regexp* Alternate(Regexp** subs, int nsubs, ParseFlags flags);
|
||||
static Regexp* Capture(Regexp* sub, ParseFlags flags, int cap);
|
||||
static Regexp* Repeat(Regexp* sub, ParseFlags flags, int min, int max);
|
||||
static Regexp* NewLiteral(Rune rune, ParseFlags flags);
|
||||
static Regexp* NewCharClass(CharClass* cc, ParseFlags flags);
|
||||
static Regexp* LiteralString(Rune* runes, int nrunes, ParseFlags flags);
|
||||
static Regexp* HaveMatch(int match_id, ParseFlags flags);
|
||||
|
||||
// Like Alternate but does not factor out common prefixes.
|
||||
static Regexp* AlternateNoFactor(Regexp** subs, int nsubs, ParseFlags flags);
|
||||
|
||||
// Debugging function. Returns string format for regexp
|
||||
// that makes structure clear. Does NOT use regexp syntax.
|
||||
std::string Dump();
|
||||
|
||||
// Helper traversal class, defined fully in walker-inl.h.
|
||||
template<typename T> class Walker;
|
||||
|
||||
// Compile to Prog. See prog.h
|
||||
// Reverse prog expects to be run over text backward.
|
||||
// Construction and execution of prog will
|
||||
// stay within approximately max_mem bytes of memory.
|
||||
// If max_mem <= 0, a reasonable default is used.
|
||||
Prog* CompileToProg(int64_t max_mem);
|
||||
Prog* CompileToReverseProg(int64_t max_mem);
|
||||
|
||||
// Whether to expect this library to find exactly the same answer as PCRE
|
||||
// when running this regexp. Most regexps do mimic PCRE exactly, but a few
|
||||
// obscure cases behave differently. Technically this is more a property
|
||||
// of the Prog than the Regexp, but the computation is much easier to do
|
||||
// on the Regexp. See mimics_pcre.cc for the exact conditions.
|
||||
bool MimicsPCRE();
|
||||
|
||||
// Benchmarking function.
|
||||
void NullWalk();
|
||||
|
||||
// Whether every match of this regexp must be anchored and
|
||||
// begin with a non-empty fixed string (perhaps after ASCII
|
||||
// case-folding). If so, returns the prefix and the sub-regexp that
|
||||
// follows it.
|
||||
// Callers should expect *prefix, *foldcase and *suffix to be "zeroed"
|
||||
// regardless of the return value.
|
||||
bool RequiredPrefix(std::string* prefix, bool* foldcase,
|
||||
Regexp** suffix);
|
||||
|
||||
// Whether every match of this regexp must be unanchored and
|
||||
// begin with a non-empty fixed string (perhaps after ASCII
|
||||
// case-folding). If so, returns the prefix.
|
||||
// Callers should expect *prefix and *foldcase to be "zeroed"
|
||||
// regardless of the return value.
|
||||
bool RequiredPrefixForAccel(std::string* prefix, bool* foldcase);
|
||||
|
||||
// Controls the maximum repeat count permitted by the parser.
|
||||
// FOR FUZZING ONLY.
|
||||
static void FUZZING_ONLY_set_maximum_repeat_count(int i);
|
||||
|
||||
private:
|
||||
// Constructor allocates vectors as appropriate for operator.
|
||||
explicit Regexp(RegexpOp op, ParseFlags parse_flags);
|
||||
|
||||
// Use Decref() instead of delete to release Regexps.
|
||||
// This is private to catch deletes at compile time.
|
||||
~Regexp();
|
||||
void Destroy();
|
||||
bool QuickDestroy();
|
||||
|
||||
// Helpers for Parse. Listed here so they can edit Regexps.
|
||||
class ParseState;
|
||||
|
||||
friend class ParseState;
|
||||
friend bool ParseCharClass(StringPiece* s, Regexp** out_re,
|
||||
RegexpStatus* status);
|
||||
|
||||
// Helper for testing [sic].
|
||||
friend bool RegexpEqualTestingOnly(Regexp*, Regexp*);
|
||||
|
||||
// Computes whether Regexp is already simple.
|
||||
bool ComputeSimple();
|
||||
|
||||
// Constructor that generates a Star, Plus or Quest,
|
||||
// squashing the pair if sub is also a Star, Plus or Quest.
|
||||
static Regexp* StarPlusOrQuest(RegexpOp op, Regexp* sub, ParseFlags flags);
|
||||
|
||||
// Constructor that generates a concatenation or alternation,
|
||||
// enforcing the limit on the number of subexpressions for
|
||||
// a particular Regexp.
|
||||
static Regexp* ConcatOrAlternate(RegexpOp op, Regexp** subs, int nsubs,
|
||||
ParseFlags flags, bool can_factor);
|
||||
|
||||
// Returns the leading string that re starts with.
|
||||
// The returned Rune* points into a piece of re,
|
||||
// so it must not be used after the caller calls re->Decref().
|
||||
static Rune* LeadingString(Regexp* re, int* nrune, ParseFlags* flags);
|
||||
|
||||
// Removes the first n leading runes from the beginning of re.
|
||||
// Edits re in place.
|
||||
static void RemoveLeadingString(Regexp* re, int n);
|
||||
|
||||
// Returns the leading regexp in re's top-level concatenation.
|
||||
// The returned Regexp* points at re or a sub-expression of re,
|
||||
// so it must not be used after the caller calls re->Decref().
|
||||
static Regexp* LeadingRegexp(Regexp* re);
|
||||
|
||||
// Removes LeadingRegexp(re) from re and returns the remainder.
|
||||
// Might edit re in place.
|
||||
static Regexp* RemoveLeadingRegexp(Regexp* re);
|
||||
|
||||
// Simplifies an alternation of literal strings by factoring out
|
||||
// common prefixes.
|
||||
static int FactorAlternation(Regexp** sub, int nsub, ParseFlags flags);
|
||||
friend class FactorAlternationImpl;
|
||||
|
||||
// Is a == b? Only efficient on regexps that have not been through
|
||||
// Simplify yet - the expansion of a kRegexpRepeat will make this
|
||||
// take a long time. Do not call on such regexps, hence private.
|
||||
static bool Equal(Regexp* a, Regexp* b);
|
||||
|
||||
// Allocate space for n sub-regexps.
|
||||
void AllocSub(int n) {
|
||||
DCHECK(n >= 0 && static_cast<uint16_t>(n) == n);
|
||||
if (n > 1)
|
||||
submany_ = new Regexp*[n];
|
||||
nsub_ = static_cast<uint16_t>(n);
|
||||
}
|
||||
|
||||
// Add Rune to LiteralString
|
||||
void AddRuneToString(Rune r);
|
||||
|
||||
// Swaps this with that, in place.
|
||||
void Swap(Regexp *that);
|
||||
|
||||
// Operator. See description of operators above.
|
||||
// uint8_t instead of RegexpOp to control space usage.
|
||||
uint8_t op_;
|
||||
|
||||
// Is this regexp structure already simple
|
||||
// (has it been returned by Simplify)?
|
||||
// uint8_t instead of bool to control space usage.
|
||||
uint8_t simple_;
|
||||
|
||||
// Flags saved from parsing and used during execution.
|
||||
// (Only FoldCase is used.)
|
||||
// uint16_t instead of ParseFlags to control space usage.
|
||||
uint16_t parse_flags_;
|
||||
|
||||
// Reference count. Exists so that SimplifyRegexp can build
|
||||
// regexp structures that are dags rather than trees to avoid
|
||||
// exponential blowup in space requirements.
|
||||
// uint16_t to control space usage.
|
||||
// The standard regexp routines will never generate a
|
||||
// ref greater than the maximum repeat count (kMaxRepeat),
|
||||
// but even so, Incref and Decref consult an overflow map
|
||||
// when ref_ reaches kMaxRef.
|
||||
uint16_t ref_;
|
||||
static const uint16_t kMaxRef = 0xffff;
|
||||
|
||||
// Subexpressions.
|
||||
// uint16_t to control space usage.
|
||||
// Concat and Alternate handle larger numbers of subexpressions
|
||||
// by building concatenation or alternation trees.
|
||||
// Other routines should call Concat or Alternate instead of
|
||||
// filling in sub() by hand.
|
||||
uint16_t nsub_;
|
||||
static const uint16_t kMaxNsub = 0xffff;
|
||||
union {
|
||||
Regexp** submany_; // if nsub_ > 1
|
||||
Regexp* subone_; // if nsub_ == 1
|
||||
};
|
||||
|
||||
// Extra space for parse and teardown stacks.
|
||||
Regexp* down_;
|
||||
|
||||
// Arguments to operator. See description of operators above.
|
||||
union {
|
||||
struct { // Repeat
|
||||
int max_;
|
||||
int min_;
|
||||
};
|
||||
struct { // Capture
|
||||
int cap_;
|
||||
std::string* name_;
|
||||
};
|
||||
struct { // LiteralString
|
||||
int nrunes_;
|
||||
Rune* runes_;
|
||||
};
|
||||
struct { // CharClass
|
||||
// These two could be in separate union members,
|
||||
// but it wouldn't save any space (there are other two-word structs)
|
||||
// and keeping them separate avoids confusion during parsing.
|
||||
CharClass* cc_;
|
||||
CharClassBuilder* ccb_;
|
||||
};
|
||||
Rune rune_; // Literal
|
||||
int match_id_; // HaveMatch
|
||||
void *the_union_[2]; // as big as any other element, for memset
|
||||
};
|
||||
|
||||
Regexp(const Regexp&) = delete;
|
||||
Regexp& operator=(const Regexp&) = delete;
|
||||
};
|
||||
|
||||
// Character class set: contains non-overlapping, non-abutting RuneRanges.
|
||||
typedef std::set<RuneRange, RuneRangeLess> RuneRangeSet;
|
||||
|
||||
class CharClassBuilder {
|
||||
public:
|
||||
CharClassBuilder();
|
||||
|
||||
typedef RuneRangeSet::iterator iterator;
|
||||
iterator begin() { return ranges_.begin(); }
|
||||
iterator end() { return ranges_.end(); }
|
||||
|
||||
int size() { return nrunes_; }
|
||||
bool empty() { return nrunes_ == 0; }
|
||||
bool full() { return nrunes_ == Runemax+1; }
|
||||
|
||||
bool Contains(Rune r);
|
||||
bool FoldsASCII();
|
||||
bool AddRange(Rune lo, Rune hi); // returns whether class changed
|
||||
CharClassBuilder* Copy();
|
||||
void AddCharClass(CharClassBuilder* cc);
|
||||
void Negate();
|
||||
void RemoveAbove(Rune r);
|
||||
CharClass* GetCharClass();
|
||||
void AddRangeFlags(Rune lo, Rune hi, Regexp::ParseFlags parse_flags);
|
||||
|
||||
private:
|
||||
static const uint32_t AlphaMask = (1<<26) - 1;
|
||||
uint32_t upper_; // bitmap of A-Z
|
||||
uint32_t lower_; // bitmap of a-z
|
||||
int nrunes_;
|
||||
RuneRangeSet ranges_;
|
||||
|
||||
CharClassBuilder(const CharClassBuilder&) = delete;
|
||||
CharClassBuilder& operator=(const CharClassBuilder&) = delete;
|
||||
};
|
||||
|
||||
// Bitwise ops on ParseFlags produce ParseFlags.
|
||||
inline Regexp::ParseFlags operator|(Regexp::ParseFlags a,
|
||||
Regexp::ParseFlags b) {
|
||||
return static_cast<Regexp::ParseFlags>(
|
||||
static_cast<int>(a) | static_cast<int>(b));
|
||||
}
|
||||
|
||||
inline Regexp::ParseFlags operator^(Regexp::ParseFlags a,
|
||||
Regexp::ParseFlags b) {
|
||||
return static_cast<Regexp::ParseFlags>(
|
||||
static_cast<int>(a) ^ static_cast<int>(b));
|
||||
}
|
||||
|
||||
inline Regexp::ParseFlags operator&(Regexp::ParseFlags a,
|
||||
Regexp::ParseFlags b) {
|
||||
return static_cast<Regexp::ParseFlags>(
|
||||
static_cast<int>(a) & static_cast<int>(b));
|
||||
}
|
||||
|
||||
inline Regexp::ParseFlags operator~(Regexp::ParseFlags a) {
|
||||
// Attempting to produce a value out of enum's range has undefined behaviour.
|
||||
return static_cast<Regexp::ParseFlags>(
|
||||
~static_cast<int>(a) & static_cast<int>(Regexp::AllParseFlags));
|
||||
}
|
||||
|
||||
} // namespace re2
|
||||
|
||||
#endif // RE2_REGEXP_H_
|
||||
85
Pods/gRPC-C++/third_party/re2/re2/set.h
generated
vendored
Normal file
85
Pods/gRPC-C++/third_party/re2/re2/set.h
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
// Copyright 2010 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RE2_SET_H_
|
||||
#define RE2_SET_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "re2/re2.h"
|
||||
|
||||
namespace re2 {
|
||||
class Prog;
|
||||
class Regexp;
|
||||
} // namespace re2
|
||||
|
||||
namespace re2 {
|
||||
|
||||
// An RE2::Set represents a collection of regexps that can
|
||||
// be searched for simultaneously.
|
||||
class RE2::Set {
|
||||
public:
|
||||
enum ErrorKind {
|
||||
kNoError = 0,
|
||||
kNotCompiled, // The set is not compiled.
|
||||
kOutOfMemory, // The DFA ran out of memory.
|
||||
kInconsistent, // The result is inconsistent. This should never happen.
|
||||
};
|
||||
|
||||
struct ErrorInfo {
|
||||
ErrorKind kind;
|
||||
};
|
||||
|
||||
Set(const RE2::Options& options, RE2::Anchor anchor);
|
||||
~Set();
|
||||
|
||||
// Not copyable.
|
||||
Set(const Set&) = delete;
|
||||
Set& operator=(const Set&) = delete;
|
||||
// Movable.
|
||||
Set(Set&& other);
|
||||
Set& operator=(Set&& other);
|
||||
|
||||
// Adds pattern to the set using the options passed to the constructor.
|
||||
// Returns the index that will identify the regexp in the output of Match(),
|
||||
// or -1 if the regexp cannot be parsed.
|
||||
// Indices are assigned in sequential order starting from 0.
|
||||
// Errors do not increment the index; if error is not NULL, *error will hold
|
||||
// the error message from the parser.
|
||||
int Add(const StringPiece& pattern, std::string* error);
|
||||
|
||||
// Compiles the set in preparation for matching.
|
||||
// Returns false if the compiler runs out of memory.
|
||||
// Add() must not be called again after Compile().
|
||||
// Compile() must be called before Match().
|
||||
bool Compile();
|
||||
|
||||
// Returns true if text matches at least one of the regexps in the set.
|
||||
// Fills v (if not NULL) with the indices of the matching regexps.
|
||||
// Callers must not expect v to be sorted.
|
||||
bool Match(const StringPiece& text, std::vector<int>* v) const;
|
||||
|
||||
// As above, but populates error_info (if not NULL) when none of the regexps
|
||||
// in the set matched. This can inform callers when DFA execution fails, for
|
||||
// example, because they might wish to handle that case differently.
|
||||
bool Match(const StringPiece& text, std::vector<int>* v,
|
||||
ErrorInfo* error_info) const;
|
||||
|
||||
private:
|
||||
typedef std::pair<std::string, re2::Regexp*> Elem;
|
||||
|
||||
RE2::Options options_;
|
||||
RE2::Anchor anchor_;
|
||||
std::vector<Elem> elem_;
|
||||
bool compiled_;
|
||||
int size_;
|
||||
std::unique_ptr<re2::Prog> prog_;
|
||||
};
|
||||
|
||||
} // namespace re2
|
||||
|
||||
#endif // RE2_SET_H_
|
||||
392
Pods/gRPC-C++/third_party/re2/re2/sparse_array.h
generated
vendored
Normal file
392
Pods/gRPC-C++/third_party/re2/re2/sparse_array.h
generated
vendored
Normal file
@@ -0,0 +1,392 @@
|
||||
// Copyright 2006 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RE2_SPARSE_ARRAY_H_
|
||||
#define RE2_SPARSE_ARRAY_H_
|
||||
|
||||
// DESCRIPTION
|
||||
//
|
||||
// SparseArray<T>(m) is a map from integers in [0, m) to T values.
|
||||
// It requires (sizeof(T)+sizeof(int))*m memory, but it provides
|
||||
// fast iteration through the elements in the array and fast clearing
|
||||
// of the array. The array has a concept of certain elements being
|
||||
// uninitialized (having no value).
|
||||
//
|
||||
// Insertion and deletion are constant time operations.
|
||||
//
|
||||
// Allocating the array is a constant time operation
|
||||
// when memory allocation is a constant time operation.
|
||||
//
|
||||
// Clearing the array is a constant time operation (unusual!).
|
||||
//
|
||||
// Iterating through the array is an O(n) operation, where n
|
||||
// is the number of items in the array (not O(m)).
|
||||
//
|
||||
// The array iterator visits entries in the order they were first
|
||||
// inserted into the array. It is safe to add items to the array while
|
||||
// using an iterator: the iterator will visit indices added to the array
|
||||
// during the iteration, but will not re-visit indices whose values
|
||||
// change after visiting. Thus SparseArray can be a convenient
|
||||
// implementation of a work queue.
|
||||
//
|
||||
// The SparseArray implementation is NOT thread-safe. It is up to the
|
||||
// caller to make sure only one thread is accessing the array. (Typically
|
||||
// these arrays are temporary values and used in situations where speed is
|
||||
// important.)
|
||||
//
|
||||
// The SparseArray interface does not present all the usual STL bells and
|
||||
// whistles.
|
||||
//
|
||||
// Implemented with reference to Briggs & Torczon, An Efficient
|
||||
// Representation for Sparse Sets, ACM Letters on Programming Languages
|
||||
// and Systems, Volume 2, Issue 1-4 (March-Dec. 1993), pp. 59-69.
|
||||
//
|
||||
// Briggs & Torczon popularized this technique, but it had been known
|
||||
// long before their paper. They point out that Aho, Hopcroft, and
|
||||
// Ullman's 1974 Design and Analysis of Computer Algorithms and Bentley's
|
||||
// 1986 Programming Pearls both hint at the technique in exercises to the
|
||||
// reader (in Aho & Hopcroft, exercise 2.12; in Bentley, column 1
|
||||
// exercise 8).
|
||||
//
|
||||
// Briggs & Torczon describe a sparse set implementation. I have
|
||||
// trivially generalized it to create a sparse array (actually the original
|
||||
// target of the AHU and Bentley exercises).
|
||||
|
||||
// IMPLEMENTATION
|
||||
//
|
||||
// SparseArray is an array dense_ and an array sparse_ of identical size.
|
||||
// At any point, the number of elements in the sparse array is size_.
|
||||
//
|
||||
// The array dense_ contains the size_ elements in the sparse array (with
|
||||
// their indices),
|
||||
// in the order that the elements were first inserted. This array is dense:
|
||||
// the size_ pairs are dense_[0] through dense_[size_-1].
|
||||
//
|
||||
// The array sparse_ maps from indices in [0,m) to indices in [0,size_).
|
||||
// For indices present in the array, dense_[sparse_[i]].index_ == i.
|
||||
// For indices not present in the array, sparse_ can contain any value at all,
|
||||
// perhaps outside the range [0, size_) but perhaps not.
|
||||
//
|
||||
// The lax requirement on sparse_ values makes clearing the array very easy:
|
||||
// set size_ to 0. Lookups are slightly more complicated.
|
||||
// An index i has a value in the array if and only if:
|
||||
// sparse_[i] is in [0, size_) AND
|
||||
// dense_[sparse_[i]].index_ == i.
|
||||
// If both these properties hold, only then it is safe to refer to
|
||||
// dense_[sparse_[i]].value_
|
||||
// as the value associated with index i.
|
||||
//
|
||||
// To insert a new entry, set sparse_[i] to size_,
|
||||
// initialize dense_[size_], and then increment size_.
|
||||
//
|
||||
// To make the sparse array as efficient as possible for non-primitive types,
|
||||
// elements may or may not be destroyed when they are deleted from the sparse
|
||||
// array through a call to resize(). They immediately become inaccessible, but
|
||||
// they are only guaranteed to be destroyed when the SparseArray destructor is
|
||||
// called.
|
||||
//
|
||||
// A moved-from SparseArray will be empty.
|
||||
|
||||
// Doing this simplifies the logic below.
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#if __has_feature(memory_sanitizer)
|
||||
#include <sanitizer/msan_interface.h>
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "re2/pod_array.h"
|
||||
|
||||
namespace re2 {
|
||||
|
||||
template<typename Value>
|
||||
class SparseArray {
|
||||
public:
|
||||
SparseArray();
|
||||
explicit SparseArray(int max_size);
|
||||
~SparseArray();
|
||||
|
||||
// IndexValue pairs: exposed in SparseArray::iterator.
|
||||
class IndexValue;
|
||||
|
||||
typedef IndexValue* iterator;
|
||||
typedef const IndexValue* const_iterator;
|
||||
|
||||
SparseArray(const SparseArray& src);
|
||||
SparseArray(SparseArray&& src);
|
||||
|
||||
SparseArray& operator=(const SparseArray& src);
|
||||
SparseArray& operator=(SparseArray&& src);
|
||||
|
||||
// Return the number of entries in the array.
|
||||
int size() const {
|
||||
return size_;
|
||||
}
|
||||
|
||||
// Indicate whether the array is empty.
|
||||
int empty() const {
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
// Iterate over the array.
|
||||
iterator begin() {
|
||||
return dense_.data();
|
||||
}
|
||||
iterator end() {
|
||||
return dense_.data() + size_;
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return dense_.data();
|
||||
}
|
||||
const_iterator end() const {
|
||||
return dense_.data() + size_;
|
||||
}
|
||||
|
||||
// Change the maximum size of the array.
|
||||
// Invalidates all iterators.
|
||||
void resize(int new_max_size);
|
||||
|
||||
// Return the maximum size of the array.
|
||||
// Indices can be in the range [0, max_size).
|
||||
int max_size() const {
|
||||
if (dense_.data() != NULL)
|
||||
return dense_.size();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Clear the array.
|
||||
void clear() {
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
// Check whether index i is in the array.
|
||||
bool has_index(int i) const;
|
||||
|
||||
// Comparison function for sorting.
|
||||
// Can sort the sparse array so that future iterations
|
||||
// will visit indices in increasing order using
|
||||
// std::sort(arr.begin(), arr.end(), arr.less);
|
||||
static bool less(const IndexValue& a, const IndexValue& b);
|
||||
|
||||
public:
|
||||
// Set the value at index i to v.
|
||||
iterator set(int i, const Value& v) {
|
||||
return SetInternal(true, i, v);
|
||||
}
|
||||
|
||||
// Set the value at new index i to v.
|
||||
// Fast but unsafe: only use if has_index(i) is false.
|
||||
iterator set_new(int i, const Value& v) {
|
||||
return SetInternal(false, i, v);
|
||||
}
|
||||
|
||||
// Set the value at index i to v.
|
||||
// Fast but unsafe: only use if has_index(i) is true.
|
||||
iterator set_existing(int i, const Value& v) {
|
||||
return SetExistingInternal(i, v);
|
||||
}
|
||||
|
||||
// Get the value at index i.
|
||||
// Fast but unsafe: only use if has_index(i) is true.
|
||||
Value& get_existing(int i) {
|
||||
assert(has_index(i));
|
||||
return dense_[sparse_[i]].value_;
|
||||
}
|
||||
const Value& get_existing(int i) const {
|
||||
assert(has_index(i));
|
||||
return dense_[sparse_[i]].value_;
|
||||
}
|
||||
|
||||
private:
|
||||
iterator SetInternal(bool allow_existing, int i, const Value& v) {
|
||||
DebugCheckInvariants();
|
||||
if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(max_size())) {
|
||||
assert(false && "illegal index");
|
||||
// Semantically, end() would be better here, but we already know
|
||||
// the user did something stupid, so begin() insulates them from
|
||||
// dereferencing an invalid pointer.
|
||||
return begin();
|
||||
}
|
||||
if (!allow_existing) {
|
||||
assert(!has_index(i));
|
||||
create_index(i);
|
||||
} else {
|
||||
if (!has_index(i))
|
||||
create_index(i);
|
||||
}
|
||||
return SetExistingInternal(i, v);
|
||||
}
|
||||
|
||||
iterator SetExistingInternal(int i, const Value& v) {
|
||||
DebugCheckInvariants();
|
||||
assert(has_index(i));
|
||||
dense_[sparse_[i]].value_ = v;
|
||||
DebugCheckInvariants();
|
||||
return dense_.data() + sparse_[i];
|
||||
}
|
||||
|
||||
// Add the index i to the array.
|
||||
// Only use if has_index(i) is known to be false.
|
||||
// Since it doesn't set the value associated with i,
|
||||
// this function is private, only intended as a helper
|
||||
// for other methods.
|
||||
void create_index(int i);
|
||||
|
||||
// In debug mode, verify that some invariant properties of the class
|
||||
// are being maintained. This is called at the end of the constructor
|
||||
// and at the beginning and end of all public non-const member functions.
|
||||
void DebugCheckInvariants() const;
|
||||
|
||||
// Initializes memory for elements [min, max).
|
||||
void MaybeInitializeMemory(int min, int max) {
|
||||
#if __has_feature(memory_sanitizer)
|
||||
__msan_unpoison(sparse_.data() + min, (max - min) * sizeof sparse_[0]);
|
||||
#elif defined(RE2_ON_VALGRIND)
|
||||
for (int i = min; i < max; i++) {
|
||||
sparse_[i] = 0xababababU;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int size_ = 0;
|
||||
PODArray<int> sparse_;
|
||||
PODArray<IndexValue> dense_;
|
||||
};
|
||||
|
||||
template<typename Value>
|
||||
SparseArray<Value>::SparseArray() = default;
|
||||
|
||||
template<typename Value>
|
||||
SparseArray<Value>::SparseArray(const SparseArray& src)
|
||||
: size_(src.size_),
|
||||
sparse_(src.max_size()),
|
||||
dense_(src.max_size()) {
|
||||
std::copy_n(src.sparse_.data(), src.max_size(), sparse_.data());
|
||||
std::copy_n(src.dense_.data(), src.max_size(), dense_.data());
|
||||
}
|
||||
|
||||
template<typename Value>
|
||||
SparseArray<Value>::SparseArray(SparseArray&& src)
|
||||
: size_(src.size_),
|
||||
sparse_(std::move(src.sparse_)),
|
||||
dense_(std::move(src.dense_)) {
|
||||
src.size_ = 0;
|
||||
}
|
||||
|
||||
template<typename Value>
|
||||
SparseArray<Value>& SparseArray<Value>::operator=(const SparseArray& src) {
|
||||
// Construct these first for exception safety.
|
||||
PODArray<int> a(src.max_size());
|
||||
PODArray<IndexValue> b(src.max_size());
|
||||
|
||||
size_ = src.size_;
|
||||
sparse_ = std::move(a);
|
||||
dense_ = std::move(b);
|
||||
std::copy_n(src.sparse_.data(), src.max_size(), sparse_.data());
|
||||
std::copy_n(src.dense_.data(), src.max_size(), dense_.data());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Value>
|
||||
SparseArray<Value>& SparseArray<Value>::operator=(SparseArray&& src) {
|
||||
size_ = src.size_;
|
||||
sparse_ = std::move(src.sparse_);
|
||||
dense_ = std::move(src.dense_);
|
||||
src.size_ = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// IndexValue pairs: exposed in SparseArray::iterator.
|
||||
template<typename Value>
|
||||
class SparseArray<Value>::IndexValue {
|
||||
public:
|
||||
int index() const { return index_; }
|
||||
Value& value() { return value_; }
|
||||
const Value& value() const { return value_; }
|
||||
|
||||
private:
|
||||
friend class SparseArray;
|
||||
int index_;
|
||||
Value value_;
|
||||
};
|
||||
|
||||
// Change the maximum size of the array.
|
||||
// Invalidates all iterators.
|
||||
template<typename Value>
|
||||
void SparseArray<Value>::resize(int new_max_size) {
|
||||
DebugCheckInvariants();
|
||||
if (new_max_size > max_size()) {
|
||||
const int old_max_size = max_size();
|
||||
|
||||
// Construct these first for exception safety.
|
||||
PODArray<int> a(new_max_size);
|
||||
PODArray<IndexValue> b(new_max_size);
|
||||
|
||||
std::copy_n(sparse_.data(), old_max_size, a.data());
|
||||
std::copy_n(dense_.data(), old_max_size, b.data());
|
||||
|
||||
sparse_ = std::move(a);
|
||||
dense_ = std::move(b);
|
||||
|
||||
MaybeInitializeMemory(old_max_size, new_max_size);
|
||||
}
|
||||
if (size_ > new_max_size)
|
||||
size_ = new_max_size;
|
||||
DebugCheckInvariants();
|
||||
}
|
||||
|
||||
// Check whether index i is in the array.
|
||||
template<typename Value>
|
||||
bool SparseArray<Value>::has_index(int i) const {
|
||||
assert(i >= 0);
|
||||
assert(i < max_size());
|
||||
if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(max_size())) {
|
||||
return false;
|
||||
}
|
||||
// Unsigned comparison avoids checking sparse_[i] < 0.
|
||||
return (uint32_t)sparse_[i] < (uint32_t)size_ &&
|
||||
dense_[sparse_[i]].index_ == i;
|
||||
}
|
||||
|
||||
template<typename Value>
|
||||
void SparseArray<Value>::create_index(int i) {
|
||||
assert(!has_index(i));
|
||||
assert(size_ < max_size());
|
||||
sparse_[i] = size_;
|
||||
dense_[size_].index_ = i;
|
||||
size_++;
|
||||
}
|
||||
|
||||
template<typename Value> SparseArray<Value>::SparseArray(int max_size) :
|
||||
sparse_(max_size), dense_(max_size) {
|
||||
MaybeInitializeMemory(size_, max_size);
|
||||
DebugCheckInvariants();
|
||||
}
|
||||
|
||||
template<typename Value> SparseArray<Value>::~SparseArray() {
|
||||
DebugCheckInvariants();
|
||||
}
|
||||
|
||||
template<typename Value> void SparseArray<Value>::DebugCheckInvariants() const {
|
||||
assert(0 <= size_);
|
||||
assert(size_ <= max_size());
|
||||
}
|
||||
|
||||
// Comparison function for sorting.
|
||||
template<typename Value> bool SparseArray<Value>::less(const IndexValue& a,
|
||||
const IndexValue& b) {
|
||||
return a.index_ < b.index_;
|
||||
}
|
||||
|
||||
} // namespace re2
|
||||
|
||||
#endif // RE2_SPARSE_ARRAY_H_
|
||||
264
Pods/gRPC-C++/third_party/re2/re2/sparse_set.h
generated
vendored
Normal file
264
Pods/gRPC-C++/third_party/re2/re2/sparse_set.h
generated
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
// Copyright 2006 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RE2_SPARSE_SET_H_
|
||||
#define RE2_SPARSE_SET_H_
|
||||
|
||||
// DESCRIPTION
|
||||
//
|
||||
// SparseSet(m) is a set of integers in [0, m).
|
||||
// It requires sizeof(int)*m memory, but it provides
|
||||
// fast iteration through the elements in the set and fast clearing
|
||||
// of the set.
|
||||
//
|
||||
// Insertion and deletion are constant time operations.
|
||||
//
|
||||
// Allocating the set is a constant time operation
|
||||
// when memory allocation is a constant time operation.
|
||||
//
|
||||
// Clearing the set is a constant time operation (unusual!).
|
||||
//
|
||||
// Iterating through the set is an O(n) operation, where n
|
||||
// is the number of items in the set (not O(m)).
|
||||
//
|
||||
// The set iterator visits entries in the order they were first
|
||||
// inserted into the set. It is safe to add items to the set while
|
||||
// using an iterator: the iterator will visit indices added to the set
|
||||
// during the iteration, but will not re-visit indices whose values
|
||||
// change after visiting. Thus SparseSet can be a convenient
|
||||
// implementation of a work queue.
|
||||
//
|
||||
// The SparseSet implementation is NOT thread-safe. It is up to the
|
||||
// caller to make sure only one thread is accessing the set. (Typically
|
||||
// these sets are temporary values and used in situations where speed is
|
||||
// important.)
|
||||
//
|
||||
// The SparseSet interface does not present all the usual STL bells and
|
||||
// whistles.
|
||||
//
|
||||
// Implemented with reference to Briggs & Torczon, An Efficient
|
||||
// Representation for Sparse Sets, ACM Letters on Programming Languages
|
||||
// and Systems, Volume 2, Issue 1-4 (March-Dec. 1993), pp. 59-69.
|
||||
//
|
||||
// This is a specialization of sparse array; see sparse_array.h.
|
||||
|
||||
// IMPLEMENTATION
|
||||
//
|
||||
// See sparse_array.h for implementation details.
|
||||
|
||||
// Doing this simplifies the logic below.
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#if __has_feature(memory_sanitizer)
|
||||
#include <sanitizer/msan_interface.h>
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "re2/pod_array.h"
|
||||
|
||||
namespace re2 {
|
||||
|
||||
template<typename Value>
|
||||
class SparseSetT {
|
||||
public:
|
||||
SparseSetT();
|
||||
explicit SparseSetT(int max_size);
|
||||
~SparseSetT();
|
||||
|
||||
typedef int* iterator;
|
||||
typedef const int* const_iterator;
|
||||
|
||||
// Return the number of entries in the set.
|
||||
int size() const {
|
||||
return size_;
|
||||
}
|
||||
|
||||
// Indicate whether the set is empty.
|
||||
int empty() const {
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
// Iterate over the set.
|
||||
iterator begin() {
|
||||
return dense_.data();
|
||||
}
|
||||
iterator end() {
|
||||
return dense_.data() + size_;
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return dense_.data();
|
||||
}
|
||||
const_iterator end() const {
|
||||
return dense_.data() + size_;
|
||||
}
|
||||
|
||||
// Change the maximum size of the set.
|
||||
// Invalidates all iterators.
|
||||
void resize(int new_max_size);
|
||||
|
||||
// Return the maximum size of the set.
|
||||
// Indices can be in the range [0, max_size).
|
||||
int max_size() const {
|
||||
if (dense_.data() != NULL)
|
||||
return dense_.size();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Clear the set.
|
||||
void clear() {
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
// Check whether index i is in the set.
|
||||
bool contains(int i) const;
|
||||
|
||||
// Comparison function for sorting.
|
||||
// Can sort the sparse set so that future iterations
|
||||
// will visit indices in increasing order using
|
||||
// std::sort(arr.begin(), arr.end(), arr.less);
|
||||
static bool less(int a, int b);
|
||||
|
||||
public:
|
||||
// Insert index i into the set.
|
||||
iterator insert(int i) {
|
||||
return InsertInternal(true, i);
|
||||
}
|
||||
|
||||
// Insert index i into the set.
|
||||
// Fast but unsafe: only use if contains(i) is false.
|
||||
iterator insert_new(int i) {
|
||||
return InsertInternal(false, i);
|
||||
}
|
||||
|
||||
private:
|
||||
iterator InsertInternal(bool allow_existing, int i) {
|
||||
DebugCheckInvariants();
|
||||
if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(max_size())) {
|
||||
assert(false && "illegal index");
|
||||
// Semantically, end() would be better here, but we already know
|
||||
// the user did something stupid, so begin() insulates them from
|
||||
// dereferencing an invalid pointer.
|
||||
return begin();
|
||||
}
|
||||
if (!allow_existing) {
|
||||
assert(!contains(i));
|
||||
create_index(i);
|
||||
} else {
|
||||
if (!contains(i))
|
||||
create_index(i);
|
||||
}
|
||||
DebugCheckInvariants();
|
||||
return dense_.data() + sparse_[i];
|
||||
}
|
||||
|
||||
// Add the index i to the set.
|
||||
// Only use if contains(i) is known to be false.
|
||||
// This function is private, only intended as a helper
|
||||
// for other methods.
|
||||
void create_index(int i);
|
||||
|
||||
// In debug mode, verify that some invariant properties of the class
|
||||
// are being maintained. This is called at the end of the constructor
|
||||
// and at the beginning and end of all public non-const member functions.
|
||||
void DebugCheckInvariants() const;
|
||||
|
||||
// Initializes memory for elements [min, max).
|
||||
void MaybeInitializeMemory(int min, int max) {
|
||||
#if __has_feature(memory_sanitizer)
|
||||
__msan_unpoison(sparse_.data() + min, (max - min) * sizeof sparse_[0]);
|
||||
#elif defined(RE2_ON_VALGRIND)
|
||||
for (int i = min; i < max; i++) {
|
||||
sparse_[i] = 0xababababU;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int size_ = 0;
|
||||
PODArray<int> sparse_;
|
||||
PODArray<int> dense_;
|
||||
};
|
||||
|
||||
template<typename Value>
|
||||
SparseSetT<Value>::SparseSetT() = default;
|
||||
|
||||
// Change the maximum size of the set.
|
||||
// Invalidates all iterators.
|
||||
template<typename Value>
|
||||
void SparseSetT<Value>::resize(int new_max_size) {
|
||||
DebugCheckInvariants();
|
||||
if (new_max_size > max_size()) {
|
||||
const int old_max_size = max_size();
|
||||
|
||||
// Construct these first for exception safety.
|
||||
PODArray<int> a(new_max_size);
|
||||
PODArray<int> b(new_max_size);
|
||||
|
||||
std::copy_n(sparse_.data(), old_max_size, a.data());
|
||||
std::copy_n(dense_.data(), old_max_size, b.data());
|
||||
|
||||
sparse_ = std::move(a);
|
||||
dense_ = std::move(b);
|
||||
|
||||
MaybeInitializeMemory(old_max_size, new_max_size);
|
||||
}
|
||||
if (size_ > new_max_size)
|
||||
size_ = new_max_size;
|
||||
DebugCheckInvariants();
|
||||
}
|
||||
|
||||
// Check whether index i is in the set.
|
||||
template<typename Value>
|
||||
bool SparseSetT<Value>::contains(int i) const {
|
||||
assert(i >= 0);
|
||||
assert(i < max_size());
|
||||
if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(max_size())) {
|
||||
return false;
|
||||
}
|
||||
// Unsigned comparison avoids checking sparse_[i] < 0.
|
||||
return (uint32_t)sparse_[i] < (uint32_t)size_ &&
|
||||
dense_[sparse_[i]] == i;
|
||||
}
|
||||
|
||||
template<typename Value>
|
||||
void SparseSetT<Value>::create_index(int i) {
|
||||
assert(!contains(i));
|
||||
assert(size_ < max_size());
|
||||
sparse_[i] = size_;
|
||||
dense_[size_] = i;
|
||||
size_++;
|
||||
}
|
||||
|
||||
template<typename Value> SparseSetT<Value>::SparseSetT(int max_size) :
|
||||
sparse_(max_size), dense_(max_size) {
|
||||
MaybeInitializeMemory(size_, max_size);
|
||||
DebugCheckInvariants();
|
||||
}
|
||||
|
||||
template<typename Value> SparseSetT<Value>::~SparseSetT() {
|
||||
DebugCheckInvariants();
|
||||
}
|
||||
|
||||
template<typename Value> void SparseSetT<Value>::DebugCheckInvariants() const {
|
||||
assert(0 <= size_);
|
||||
assert(size_ <= max_size());
|
||||
}
|
||||
|
||||
// Comparison function for sorting.
|
||||
template<typename Value> bool SparseSetT<Value>::less(int a, int b) {
|
||||
return a < b;
|
||||
}
|
||||
|
||||
typedef SparseSetT<void> SparseSet;
|
||||
|
||||
} // namespace re2
|
||||
|
||||
#endif // RE2_SPARSE_SET_H_
|
||||
213
Pods/gRPC-C++/third_party/re2/re2/stringpiece.h
generated
vendored
Normal file
213
Pods/gRPC-C++/third_party/re2/re2/stringpiece.h
generated
vendored
Normal file
@@ -0,0 +1,213 @@
|
||||
// Copyright 2001-2010 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RE2_STRINGPIECE_H_
|
||||
#define RE2_STRINGPIECE_H_
|
||||
|
||||
// A string-like object that points to a sized piece of memory.
|
||||
//
|
||||
// Functions or methods may use const StringPiece& parameters to accept either
|
||||
// a "const char*" or a "string" value that will be implicitly converted to
|
||||
// a StringPiece. The implicit conversion means that it is often appropriate
|
||||
// to include this .h file in other files rather than forward-declaring
|
||||
// StringPiece as would be appropriate for most other Google classes.
|
||||
//
|
||||
// Systematic usage of StringPiece is encouraged as it will reduce unnecessary
|
||||
// conversions from "const char*" to "string" and back again.
|
||||
//
|
||||
//
|
||||
// Arghh! I wish C++ literals were "string".
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <iosfwd>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#ifdef __cpp_lib_string_view
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
namespace re2 {
|
||||
|
||||
class StringPiece {
|
||||
public:
|
||||
typedef std::char_traits<char> traits_type;
|
||||
typedef char value_type;
|
||||
typedef char* pointer;
|
||||
typedef const char* const_pointer;
|
||||
typedef char& reference;
|
||||
typedef const char& const_reference;
|
||||
typedef const char* const_iterator;
|
||||
typedef const_iterator iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
typedef const_reverse_iterator reverse_iterator;
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
static const size_type npos = static_cast<size_type>(-1);
|
||||
|
||||
// We provide non-explicit singleton constructors so users can pass
|
||||
// in a "const char*" or a "string" wherever a "StringPiece" is
|
||||
// expected.
|
||||
StringPiece()
|
||||
: data_(NULL), size_(0) {}
|
||||
#ifdef __cpp_lib_string_view
|
||||
StringPiece(const std::string_view& str)
|
||||
: data_(str.data()), size_(str.size()) {}
|
||||
#endif
|
||||
StringPiece(const std::string& str)
|
||||
: data_(str.data()), size_(str.size()) {}
|
||||
StringPiece(const char* str)
|
||||
: data_(str), size_(str == NULL ? 0 : strlen(str)) {}
|
||||
StringPiece(const char* str, size_type len)
|
||||
: data_(str), size_(len) {}
|
||||
|
||||
const_iterator begin() const { return data_; }
|
||||
const_iterator end() const { return data_ + size_; }
|
||||
const_reverse_iterator rbegin() const {
|
||||
return const_reverse_iterator(data_ + size_);
|
||||
}
|
||||
const_reverse_iterator rend() const {
|
||||
return const_reverse_iterator(data_);
|
||||
}
|
||||
|
||||
size_type size() const { return size_; }
|
||||
size_type length() const { return size_; }
|
||||
bool empty() const { return size_ == 0; }
|
||||
|
||||
const_reference operator[](size_type i) const { return data_[i]; }
|
||||
const_pointer data() const { return data_; }
|
||||
|
||||
void remove_prefix(size_type n) {
|
||||
data_ += n;
|
||||
size_ -= n;
|
||||
}
|
||||
|
||||
void remove_suffix(size_type n) {
|
||||
size_ -= n;
|
||||
}
|
||||
|
||||
void set(const char* str) {
|
||||
data_ = str;
|
||||
size_ = str == NULL ? 0 : strlen(str);
|
||||
}
|
||||
|
||||
void set(const char* str, size_type len) {
|
||||
data_ = str;
|
||||
size_ = len;
|
||||
}
|
||||
|
||||
#ifdef __cpp_lib_string_view
|
||||
// Converts to `std::basic_string_view`.
|
||||
operator std::basic_string_view<char, traits_type>() const {
|
||||
if (!data_) return {};
|
||||
return std::basic_string_view<char, traits_type>(data_, size_);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Converts to `std::basic_string`.
|
||||
template <typename A>
|
||||
explicit operator std::basic_string<char, traits_type, A>() const {
|
||||
if (!data_) return {};
|
||||
return std::basic_string<char, traits_type, A>(data_, size_);
|
||||
}
|
||||
|
||||
std::string as_string() const {
|
||||
return std::string(data_, size_);
|
||||
}
|
||||
|
||||
// We also define ToString() here, since many other string-like
|
||||
// interfaces name the routine that converts to a C++ string
|
||||
// "ToString", and it's confusing to have the method that does that
|
||||
// for a StringPiece be called "as_string()". We also leave the
|
||||
// "as_string()" method defined here for existing code.
|
||||
std::string ToString() const {
|
||||
return std::string(data_, size_);
|
||||
}
|
||||
|
||||
void CopyToString(std::string* target) const {
|
||||
target->assign(data_, size_);
|
||||
}
|
||||
|
||||
void AppendToString(std::string* target) const {
|
||||
target->append(data_, size_);
|
||||
}
|
||||
|
||||
size_type copy(char* buf, size_type n, size_type pos = 0) const;
|
||||
StringPiece substr(size_type pos = 0, size_type n = npos) const;
|
||||
|
||||
int compare(const StringPiece& x) const {
|
||||
size_type min_size = std::min(size(), x.size());
|
||||
if (min_size > 0) {
|
||||
int r = memcmp(data(), x.data(), min_size);
|
||||
if (r < 0) return -1;
|
||||
if (r > 0) return 1;
|
||||
}
|
||||
if (size() < x.size()) return -1;
|
||||
if (size() > x.size()) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Does "this" start with "x"?
|
||||
bool starts_with(const StringPiece& x) const {
|
||||
return x.empty() ||
|
||||
(size() >= x.size() && memcmp(data(), x.data(), x.size()) == 0);
|
||||
}
|
||||
|
||||
// Does "this" end with "x"?
|
||||
bool ends_with(const StringPiece& x) const {
|
||||
return x.empty() ||
|
||||
(size() >= x.size() &&
|
||||
memcmp(data() + (size() - x.size()), x.data(), x.size()) == 0);
|
||||
}
|
||||
|
||||
bool contains(const StringPiece& s) const {
|
||||
return find(s) != npos;
|
||||
}
|
||||
|
||||
size_type find(const StringPiece& s, size_type pos = 0) const;
|
||||
size_type find(char c, size_type pos = 0) const;
|
||||
size_type rfind(const StringPiece& s, size_type pos = npos) const;
|
||||
size_type rfind(char c, size_type pos = npos) const;
|
||||
|
||||
private:
|
||||
const_pointer data_;
|
||||
size_type size_;
|
||||
};
|
||||
|
||||
inline bool operator==(const StringPiece& x, const StringPiece& y) {
|
||||
StringPiece::size_type len = x.size();
|
||||
if (len != y.size()) return false;
|
||||
return x.data() == y.data() || len == 0 ||
|
||||
memcmp(x.data(), y.data(), len) == 0;
|
||||
}
|
||||
|
||||
inline bool operator!=(const StringPiece& x, const StringPiece& y) {
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
inline bool operator<(const StringPiece& x, const StringPiece& y) {
|
||||
StringPiece::size_type min_size = std::min(x.size(), y.size());
|
||||
int r = min_size == 0 ? 0 : memcmp(x.data(), y.data(), min_size);
|
||||
return (r < 0) || (r == 0 && x.size() < y.size());
|
||||
}
|
||||
|
||||
inline bool operator>(const StringPiece& x, const StringPiece& y) {
|
||||
return y < x;
|
||||
}
|
||||
|
||||
inline bool operator<=(const StringPiece& x, const StringPiece& y) {
|
||||
return !(x > y);
|
||||
}
|
||||
|
||||
inline bool operator>=(const StringPiece& x, const StringPiece& y) {
|
||||
return !(x < y);
|
||||
}
|
||||
|
||||
// Allow StringPiece to be logged.
|
||||
std::ostream& operator<<(std::ostream& o, const StringPiece& p);
|
||||
|
||||
} // namespace re2
|
||||
|
||||
#endif // RE2_STRINGPIECE_H_
|
||||
78
Pods/gRPC-C++/third_party/re2/re2/unicode_casefold.h
generated
vendored
Normal file
78
Pods/gRPC-C++/third_party/re2/re2/unicode_casefold.h
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2008 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RE2_UNICODE_CASEFOLD_H_
|
||||
#define RE2_UNICODE_CASEFOLD_H_
|
||||
|
||||
// Unicode case folding tables.
|
||||
|
||||
// The Unicode case folding tables encode the mapping from one Unicode point
|
||||
// to the next largest Unicode point with equivalent folding. The largest
|
||||
// point wraps back to the first. For example, the tables map:
|
||||
//
|
||||
// 'A' -> 'a'
|
||||
// 'a' -> 'A'
|
||||
//
|
||||
// 'K' -> 'k'
|
||||
// 'k' -> 'K' (Kelvin symbol)
|
||||
// 'K' -> 'K'
|
||||
//
|
||||
// Like everything Unicode, these tables are big. If we represent the table
|
||||
// as a sorted list of uint32_t pairs, it has 2049 entries and is 16 kB.
|
||||
// Most table entries look like the ones around them:
|
||||
// 'A' maps to 'A'+32, 'B' maps to 'B'+32, etc.
|
||||
// Instead of listing all the pairs explicitly, we make a list of ranges
|
||||
// and deltas, so that the table entries for 'A' through 'Z' can be represented
|
||||
// as a single entry { 'A', 'Z', +32 }.
|
||||
//
|
||||
// In addition to blocks that map to each other (A-Z mapping to a-z)
|
||||
// there are blocks of pairs that individually map to each other
|
||||
// (for example, 0100<->0101, 0102<->0103, 0104<->0105, ...).
|
||||
// For those, the special delta value EvenOdd marks even/odd pairs
|
||||
// (if even, add 1; if odd, subtract 1), and OddEven marks odd/even pairs.
|
||||
//
|
||||
// In this form, the table has 274 entries, about 3kB. If we were to split
|
||||
// the table into one for 16-bit codes and an overflow table for larger ones,
|
||||
// we could get it down to about 1.5kB, but that's not worth the complexity.
|
||||
//
|
||||
// The grouped form also allows for efficient fold range calculations
|
||||
// rather than looping one character at a time.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "util/util.h"
|
||||
#include "util/utf.h"
|
||||
|
||||
namespace re2 {
|
||||
|
||||
enum {
|
||||
EvenOdd = 1,
|
||||
OddEven = -1,
|
||||
EvenOddSkip = 1<<30,
|
||||
OddEvenSkip,
|
||||
};
|
||||
|
||||
struct CaseFold {
|
||||
Rune lo;
|
||||
Rune hi;
|
||||
int32_t delta;
|
||||
};
|
||||
|
||||
extern const CaseFold unicode_casefold[];
|
||||
extern const int num_unicode_casefold;
|
||||
|
||||
extern const CaseFold unicode_tolower[];
|
||||
extern const int num_unicode_tolower;
|
||||
|
||||
// Returns the CaseFold* in the tables that contains rune.
|
||||
// If rune is not in the tables, returns the first CaseFold* after rune.
|
||||
// If rune is larger than any value in the tables, returns NULL.
|
||||
extern const CaseFold* LookupCaseFold(const CaseFold*, int, Rune rune);
|
||||
|
||||
// Returns the result of applying the fold f to the rune r.
|
||||
extern Rune ApplyFold(const CaseFold *f, Rune r);
|
||||
|
||||
} // namespace re2
|
||||
|
||||
#endif // RE2_UNICODE_CASEFOLD_H_
|
||||
67
Pods/gRPC-C++/third_party/re2/re2/unicode_groups.h
generated
vendored
Normal file
67
Pods/gRPC-C++/third_party/re2/re2/unicode_groups.h
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2008 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RE2_UNICODE_GROUPS_H_
|
||||
#define RE2_UNICODE_GROUPS_H_
|
||||
|
||||
// Unicode character groups.
|
||||
|
||||
// The codes get split into ranges of 16-bit codes
|
||||
// and ranges of 32-bit codes. It would be simpler
|
||||
// to use only 32-bit ranges, but these tables are large
|
||||
// enough to warrant extra care.
|
||||
//
|
||||
// Using just 32-bit ranges gives 27 kB of data.
|
||||
// Adding 16-bit ranges gives 18 kB of data.
|
||||
// Adding an extra table of 16-bit singletons would reduce
|
||||
// to 16.5 kB of data but make the data harder to use;
|
||||
// we don't bother.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "util/util.h"
|
||||
#include "util/utf.h"
|
||||
|
||||
namespace re2 {
|
||||
|
||||
struct URange16
|
||||
{
|
||||
uint16_t lo;
|
||||
uint16_t hi;
|
||||
};
|
||||
|
||||
struct URange32
|
||||
{
|
||||
Rune lo;
|
||||
Rune hi;
|
||||
};
|
||||
|
||||
struct UGroup
|
||||
{
|
||||
const char *name;
|
||||
int sign; // +1 for [abc], -1 for [^abc]
|
||||
const URange16 *r16;
|
||||
int nr16;
|
||||
const URange32 *r32;
|
||||
int nr32;
|
||||
};
|
||||
|
||||
// Named by property or script name (e.g., "Nd", "N", "Han").
|
||||
// Negated groups are not included.
|
||||
extern const UGroup unicode_groups[];
|
||||
extern const int num_unicode_groups;
|
||||
|
||||
// Named by POSIX name (e.g., "[:alpha:]", "[:^lower:]").
|
||||
// Negated groups are included.
|
||||
extern const UGroup posix_groups[];
|
||||
extern const int num_posix_groups;
|
||||
|
||||
// Named by Perl name (e.g., "\\d", "\\D").
|
||||
// Negated groups are included.
|
||||
extern const UGroup perl_groups[];
|
||||
extern const int num_perl_groups;
|
||||
|
||||
} // namespace re2
|
||||
|
||||
#endif // RE2_UNICODE_GROUPS_H_
|
||||
247
Pods/gRPC-C++/third_party/re2/re2/walker-inl.h
generated
vendored
Normal file
247
Pods/gRPC-C++/third_party/re2/re2/walker-inl.h
generated
vendored
Normal file
@@ -0,0 +1,247 @@
|
||||
// Copyright 2006 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RE2_WALKER_INL_H_
|
||||
#define RE2_WALKER_INL_H_
|
||||
|
||||
// Helper class for traversing Regexps without recursion.
|
||||
// Clients should declare their own subclasses that override
|
||||
// the PreVisit and PostVisit methods, which are called before
|
||||
// and after visiting the subexpressions.
|
||||
|
||||
// Not quite the Visitor pattern, because (among other things)
|
||||
// the Visitor pattern is recursive.
|
||||
|
||||
#include <stack>
|
||||
|
||||
#include "util/logging.h"
|
||||
#include "re2/regexp.h"
|
||||
|
||||
namespace re2 {
|
||||
|
||||
template<typename T> struct WalkState;
|
||||
|
||||
template<typename T> class Regexp::Walker {
|
||||
public:
|
||||
Walker();
|
||||
virtual ~Walker();
|
||||
|
||||
// Virtual method called before visiting re's children.
|
||||
// PreVisit passes ownership of its return value to its caller.
|
||||
// The Arg* that PreVisit returns will be passed to PostVisit as pre_arg
|
||||
// and passed to the child PreVisits and PostVisits as parent_arg.
|
||||
// At the top-most Regexp, parent_arg is arg passed to walk.
|
||||
// If PreVisit sets *stop to true, the walk does not recurse
|
||||
// into the children. Instead it behaves as though the return
|
||||
// value from PreVisit is the return value from PostVisit.
|
||||
// The default PreVisit returns parent_arg.
|
||||
virtual T PreVisit(Regexp* re, T parent_arg, bool* stop);
|
||||
|
||||
// Virtual method called after visiting re's children.
|
||||
// The pre_arg is the T that PreVisit returned.
|
||||
// The child_args is a vector of the T that the child PostVisits returned.
|
||||
// PostVisit takes ownership of pre_arg.
|
||||
// PostVisit takes ownership of the Ts
|
||||
// in *child_args, but not the vector itself.
|
||||
// PostVisit passes ownership of its return value
|
||||
// to its caller.
|
||||
// The default PostVisit simply returns pre_arg.
|
||||
virtual T PostVisit(Regexp* re, T parent_arg, T pre_arg,
|
||||
T* child_args, int nchild_args);
|
||||
|
||||
// Virtual method called to copy a T,
|
||||
// when Walk notices that more than one child is the same re.
|
||||
virtual T Copy(T arg);
|
||||
|
||||
// Virtual method called to do a "quick visit" of the re,
|
||||
// but not its children. Only called once the visit budget
|
||||
// has been used up and we're trying to abort the walk
|
||||
// as quickly as possible. Should return a value that
|
||||
// makes sense for the parent PostVisits still to be run.
|
||||
// This function is (hopefully) only called by
|
||||
// WalkExponential, but must be implemented by all clients,
|
||||
// just in case.
|
||||
virtual T ShortVisit(Regexp* re, T parent_arg) = 0;
|
||||
|
||||
// Walks over a regular expression.
|
||||
// Top_arg is passed as parent_arg to PreVisit and PostVisit of re.
|
||||
// Returns the T returned by PostVisit on re.
|
||||
T Walk(Regexp* re, T top_arg);
|
||||
|
||||
// Like Walk, but doesn't use Copy. This can lead to
|
||||
// exponential runtimes on cross-linked Regexps like the
|
||||
// ones generated by Simplify. To help limit this,
|
||||
// at most max_visits nodes will be visited and then
|
||||
// the walk will be cut off early.
|
||||
// If the walk *is* cut off early, ShortVisit(re)
|
||||
// will be called on regexps that cannot be fully
|
||||
// visited rather than calling PreVisit/PostVisit.
|
||||
T WalkExponential(Regexp* re, T top_arg, int max_visits);
|
||||
|
||||
// Clears the stack. Should never be necessary, since
|
||||
// Walk always enters and exits with an empty stack.
|
||||
// Logs DFATAL if stack is not already clear.
|
||||
void Reset();
|
||||
|
||||
// Returns whether walk was cut off.
|
||||
bool stopped_early() { return stopped_early_; }
|
||||
|
||||
private:
|
||||
// Walk state for the entire traversal.
|
||||
std::stack<WalkState<T>> stack_;
|
||||
bool stopped_early_;
|
||||
int max_visits_;
|
||||
|
||||
T WalkInternal(Regexp* re, T top_arg, bool use_copy);
|
||||
|
||||
Walker(const Walker&) = delete;
|
||||
Walker& operator=(const Walker&) = delete;
|
||||
};
|
||||
|
||||
template<typename T> T Regexp::Walker<T>::PreVisit(Regexp* re,
|
||||
T parent_arg,
|
||||
bool* stop) {
|
||||
return parent_arg;
|
||||
}
|
||||
|
||||
template<typename T> T Regexp::Walker<T>::PostVisit(Regexp* re,
|
||||
T parent_arg,
|
||||
T pre_arg,
|
||||
T* child_args,
|
||||
int nchild_args) {
|
||||
return pre_arg;
|
||||
}
|
||||
|
||||
template<typename T> T Regexp::Walker<T>::Copy(T arg) {
|
||||
return arg;
|
||||
}
|
||||
|
||||
// State about a single level in the traversal.
|
||||
template<typename T> struct WalkState {
|
||||
WalkState(Regexp* re, T parent)
|
||||
: re(re),
|
||||
n(-1),
|
||||
parent_arg(parent),
|
||||
child_args(NULL) { }
|
||||
|
||||
Regexp* re; // The regexp
|
||||
int n; // The index of the next child to process; -1 means need to PreVisit
|
||||
T parent_arg; // Accumulated arguments.
|
||||
T pre_arg;
|
||||
T child_arg; // One-element buffer for child_args.
|
||||
T* child_args;
|
||||
};
|
||||
|
||||
template<typename T> Regexp::Walker<T>::Walker() {
|
||||
stopped_early_ = false;
|
||||
}
|
||||
|
||||
template<typename T> Regexp::Walker<T>::~Walker() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
// Clears the stack. Should never be necessary, since
|
||||
// Walk always enters and exits with an empty stack.
|
||||
// Logs DFATAL if stack is not already clear.
|
||||
template<typename T> void Regexp::Walker<T>::Reset() {
|
||||
if (!stack_.empty()) {
|
||||
LOG(DFATAL) << "Stack not empty.";
|
||||
while (!stack_.empty()) {
|
||||
if (stack_.top().re->nsub_ > 1)
|
||||
delete[] stack_.top().child_args;
|
||||
stack_.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> T Regexp::Walker<T>::WalkInternal(Regexp* re, T top_arg,
|
||||
bool use_copy) {
|
||||
Reset();
|
||||
|
||||
if (re == NULL) {
|
||||
LOG(DFATAL) << "Walk NULL";
|
||||
return top_arg;
|
||||
}
|
||||
|
||||
stack_.push(WalkState<T>(re, top_arg));
|
||||
|
||||
WalkState<T>* s;
|
||||
for (;;) {
|
||||
T t;
|
||||
s = &stack_.top();
|
||||
re = s->re;
|
||||
switch (s->n) {
|
||||
case -1: {
|
||||
if (--max_visits_ < 0) {
|
||||
stopped_early_ = true;
|
||||
t = ShortVisit(re, s->parent_arg);
|
||||
break;
|
||||
}
|
||||
bool stop = false;
|
||||
s->pre_arg = PreVisit(re, s->parent_arg, &stop);
|
||||
if (stop) {
|
||||
t = s->pre_arg;
|
||||
break;
|
||||
}
|
||||
s->n = 0;
|
||||
s->child_args = NULL;
|
||||
if (re->nsub_ == 1)
|
||||
s->child_args = &s->child_arg;
|
||||
else if (re->nsub_ > 1)
|
||||
s->child_args = new T[re->nsub_];
|
||||
FALLTHROUGH_INTENDED;
|
||||
}
|
||||
default: {
|
||||
if (re->nsub_ > 0) {
|
||||
Regexp** sub = re->sub();
|
||||
if (s->n < re->nsub_) {
|
||||
if (use_copy && s->n > 0 && sub[s->n - 1] == sub[s->n]) {
|
||||
s->child_args[s->n] = Copy(s->child_args[s->n - 1]);
|
||||
s->n++;
|
||||
} else {
|
||||
stack_.push(WalkState<T>(sub[s->n], s->pre_arg));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
t = PostVisit(re, s->parent_arg, s->pre_arg, s->child_args, s->n);
|
||||
if (re->nsub_ > 1)
|
||||
delete[] s->child_args;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We've finished stack_.top().
|
||||
// Update next guy down.
|
||||
stack_.pop();
|
||||
if (stack_.empty())
|
||||
return t;
|
||||
s = &stack_.top();
|
||||
if (s->child_args != NULL)
|
||||
s->child_args[s->n] = t;
|
||||
else
|
||||
s->child_arg = t;
|
||||
s->n++;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> T Regexp::Walker<T>::Walk(Regexp* re, T top_arg) {
|
||||
// Without the exponential walking behavior,
|
||||
// this budget should be more than enough for any
|
||||
// regexp, and yet not enough to get us in trouble
|
||||
// as far as CPU time.
|
||||
max_visits_ = 1000000;
|
||||
return WalkInternal(re, top_arg, true);
|
||||
}
|
||||
|
||||
template<typename T> T Regexp::Walker<T>::WalkExponential(Regexp* re, T top_arg,
|
||||
int max_visits) {
|
||||
max_visits_ = max_visits;
|
||||
return WalkInternal(re, top_arg, false);
|
||||
}
|
||||
|
||||
} // namespace re2
|
||||
|
||||
#endif // RE2_WALKER_INL_H_
|
||||
109
Pods/gRPC-C++/third_party/re2/util/logging.h
generated
vendored
Normal file
109
Pods/gRPC-C++/third_party/re2/util/logging.h
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
// Copyright 2009 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_LOGGING_H_
|
||||
#define UTIL_LOGGING_H_
|
||||
|
||||
// Simplified version of Google's logging.
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "util/util.h"
|
||||
|
||||
// Debug-only checking.
|
||||
#define DCHECK(condition) assert(condition)
|
||||
#define DCHECK_EQ(val1, val2) assert((val1) == (val2))
|
||||
#define DCHECK_NE(val1, val2) assert((val1) != (val2))
|
||||
#define DCHECK_LE(val1, val2) assert((val1) <= (val2))
|
||||
#define DCHECK_LT(val1, val2) assert((val1) < (val2))
|
||||
#define DCHECK_GE(val1, val2) assert((val1) >= (val2))
|
||||
#define DCHECK_GT(val1, val2) assert((val1) > (val2))
|
||||
|
||||
// Always-on checking
|
||||
#define CHECK(x) if(x){}else LogMessageFatal(__FILE__, __LINE__).stream() << "Check failed: " #x
|
||||
#define CHECK_LT(x, y) CHECK((x) < (y))
|
||||
#define CHECK_GT(x, y) CHECK((x) > (y))
|
||||
#define CHECK_LE(x, y) CHECK((x) <= (y))
|
||||
#define CHECK_GE(x, y) CHECK((x) >= (y))
|
||||
#define CHECK_EQ(x, y) CHECK((x) == (y))
|
||||
#define CHECK_NE(x, y) CHECK((x) != (y))
|
||||
|
||||
#define LOG_INFO LogMessage(__FILE__, __LINE__)
|
||||
#define LOG_WARNING LogMessage(__FILE__, __LINE__)
|
||||
#define LOG_ERROR LogMessage(__FILE__, __LINE__)
|
||||
#define LOG_FATAL LogMessageFatal(__FILE__, __LINE__)
|
||||
#define LOG_QFATAL LOG_FATAL
|
||||
|
||||
// It seems that one of the Windows header files defines ERROR as 0.
|
||||
#ifdef _WIN32
|
||||
#define LOG_0 LOG_INFO
|
||||
#endif
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define LOG_DFATAL LOG_ERROR
|
||||
#else
|
||||
#define LOG_DFATAL LOG_FATAL
|
||||
#endif
|
||||
|
||||
#define LOG(severity) LOG_ ## severity.stream()
|
||||
|
||||
#define VLOG(x) if((x)>0){}else LOG_INFO.stream()
|
||||
|
||||
class LogMessage {
|
||||
public:
|
||||
LogMessage(const char* file, int line)
|
||||
: flushed_(false) {
|
||||
stream() << file << ":" << line << ": ";
|
||||
}
|
||||
void Flush() {
|
||||
stream() << "\n";
|
||||
std::string s = str_.str();
|
||||
size_t n = s.size();
|
||||
if (fwrite(s.data(), 1, n, stderr) < n) {} // shut up gcc
|
||||
flushed_ = true;
|
||||
}
|
||||
~LogMessage() {
|
||||
if (!flushed_) {
|
||||
Flush();
|
||||
}
|
||||
}
|
||||
std::ostream& stream() { return str_; }
|
||||
|
||||
private:
|
||||
bool flushed_;
|
||||
std::ostringstream str_;
|
||||
|
||||
LogMessage(const LogMessage&) = delete;
|
||||
LogMessage& operator=(const LogMessage&) = delete;
|
||||
};
|
||||
|
||||
// Silence "destructor never returns" warning for ~LogMessageFatal().
|
||||
// Since this is a header file, push and then pop to limit the scope.
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4722)
|
||||
#endif
|
||||
|
||||
class LogMessageFatal : public LogMessage {
|
||||
public:
|
||||
LogMessageFatal(const char* file, int line)
|
||||
: LogMessage(file, line) {}
|
||||
ATTRIBUTE_NORETURN ~LogMessageFatal() {
|
||||
Flush();
|
||||
abort();
|
||||
}
|
||||
private:
|
||||
LogMessageFatal(const LogMessageFatal&) = delete;
|
||||
LogMessageFatal& operator=(const LogMessageFatal&) = delete;
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // UTIL_LOGGING_H_
|
||||
41
Pods/gRPC-C++/third_party/re2/util/mix.h
generated
vendored
Normal file
41
Pods/gRPC-C++/third_party/re2/util/mix.h
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright 2016 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_MIX_H_
|
||||
#define UTIL_MIX_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <limits>
|
||||
|
||||
namespace re2 {
|
||||
|
||||
// Silence "truncation of constant value" warning for kMul in 32-bit mode.
|
||||
// Since this is a header file, push and then pop to limit the scope.
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4309)
|
||||
#endif
|
||||
|
||||
class HashMix {
|
||||
public:
|
||||
HashMix() : hash_(1) {}
|
||||
explicit HashMix(size_t val) : hash_(val + 83) {}
|
||||
void Mix(size_t val) {
|
||||
static const size_t kMul = static_cast<size_t>(0xdc3eb94af8ab4c93ULL);
|
||||
hash_ *= kMul;
|
||||
hash_ = ((hash_ << 19) |
|
||||
(hash_ >> (std::numeric_limits<size_t>::digits - 19))) + val;
|
||||
}
|
||||
size_t get() const { return hash_; }
|
||||
private:
|
||||
size_t hash_;
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace re2
|
||||
|
||||
#endif // UTIL_MIX_H_
|
||||
148
Pods/gRPC-C++/third_party/re2/util/mutex.h
generated
vendored
Normal file
148
Pods/gRPC-C++/third_party/re2/util/mutex.h
generated
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
// Copyright 2007 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_MUTEX_H_
|
||||
#define UTIL_MUTEX_H_
|
||||
|
||||
/*
|
||||
* A simple mutex wrapper, supporting locks and read-write locks.
|
||||
* You should assume the locks are *not* re-entrant.
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
// Requires Windows Vista or Windows Server 2008 at minimum.
|
||||
#include <windows.h>
|
||||
#if defined(WINVER) && WINVER >= 0x0600
|
||||
#define MUTEX_IS_WIN32_SRWLOCK
|
||||
#endif
|
||||
#else
|
||||
#ifndef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#if defined(_POSIX_READER_WRITER_LOCKS) && _POSIX_READER_WRITER_LOCKS > 0
|
||||
#define MUTEX_IS_PTHREAD_RWLOCK
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(MUTEX_IS_WIN32_SRWLOCK)
|
||||
typedef SRWLOCK MutexType;
|
||||
#elif defined(MUTEX_IS_PTHREAD_RWLOCK)
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
typedef pthread_rwlock_t MutexType;
|
||||
#else
|
||||
#include <shared_mutex>
|
||||
typedef std::shared_mutex MutexType;
|
||||
#endif
|
||||
|
||||
namespace re2 {
|
||||
|
||||
class Mutex {
|
||||
public:
|
||||
inline Mutex();
|
||||
inline ~Mutex();
|
||||
inline void Lock(); // Block if needed until free then acquire exclusively
|
||||
inline void Unlock(); // Release a lock acquired via Lock()
|
||||
// Note that on systems that don't support read-write locks, these may
|
||||
// be implemented as synonyms to Lock() and Unlock(). So you can use
|
||||
// these for efficiency, but don't use them anyplace where being able
|
||||
// to do shared reads is necessary to avoid deadlock.
|
||||
inline void ReaderLock(); // Block until free or shared then acquire a share
|
||||
inline void ReaderUnlock(); // Release a read share of this Mutex
|
||||
inline void WriterLock() { Lock(); } // Acquire an exclusive lock
|
||||
inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()
|
||||
|
||||
private:
|
||||
MutexType mutex_;
|
||||
|
||||
// Catch the error of writing Mutex when intending MutexLock.
|
||||
Mutex(Mutex *ignored);
|
||||
|
||||
Mutex(const Mutex&) = delete;
|
||||
Mutex& operator=(const Mutex&) = delete;
|
||||
};
|
||||
|
||||
#if defined(MUTEX_IS_WIN32_SRWLOCK)
|
||||
|
||||
Mutex::Mutex() : mutex_(SRWLOCK_INIT) { }
|
||||
Mutex::~Mutex() { }
|
||||
void Mutex::Lock() { AcquireSRWLockExclusive(&mutex_); }
|
||||
void Mutex::Unlock() { ReleaseSRWLockExclusive(&mutex_); }
|
||||
void Mutex::ReaderLock() { AcquireSRWLockShared(&mutex_); }
|
||||
void Mutex::ReaderUnlock() { ReleaseSRWLockShared(&mutex_); }
|
||||
|
||||
#elif defined(MUTEX_IS_PTHREAD_RWLOCK)
|
||||
|
||||
#define SAFE_PTHREAD(fncall) \
|
||||
do { \
|
||||
if ((fncall) != 0) abort(); \
|
||||
} while (0)
|
||||
|
||||
Mutex::Mutex() { SAFE_PTHREAD(pthread_rwlock_init(&mutex_, NULL)); }
|
||||
Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy(&mutex_)); }
|
||||
void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock(&mutex_)); }
|
||||
void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock(&mutex_)); }
|
||||
void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock(&mutex_)); }
|
||||
void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock(&mutex_)); }
|
||||
|
||||
#undef SAFE_PTHREAD
|
||||
|
||||
#else
|
||||
|
||||
Mutex::Mutex() { }
|
||||
Mutex::~Mutex() { }
|
||||
void Mutex::Lock() { mutex_.lock(); }
|
||||
void Mutex::Unlock() { mutex_.unlock(); }
|
||||
void Mutex::ReaderLock() { mutex_.lock_shared(); }
|
||||
void Mutex::ReaderUnlock() { mutex_.unlock_shared(); }
|
||||
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Some helper classes
|
||||
|
||||
// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
|
||||
class MutexLock {
|
||||
public:
|
||||
explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
|
||||
~MutexLock() { mu_->Unlock(); }
|
||||
private:
|
||||
Mutex * const mu_;
|
||||
|
||||
MutexLock(const MutexLock&) = delete;
|
||||
MutexLock& operator=(const MutexLock&) = delete;
|
||||
};
|
||||
|
||||
// ReaderMutexLock and WriterMutexLock do the same, for rwlocks
|
||||
class ReaderMutexLock {
|
||||
public:
|
||||
explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); }
|
||||
~ReaderMutexLock() { mu_->ReaderUnlock(); }
|
||||
private:
|
||||
Mutex * const mu_;
|
||||
|
||||
ReaderMutexLock(const ReaderMutexLock&) = delete;
|
||||
ReaderMutexLock& operator=(const ReaderMutexLock&) = delete;
|
||||
};
|
||||
|
||||
class WriterMutexLock {
|
||||
public:
|
||||
explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); }
|
||||
~WriterMutexLock() { mu_->WriterUnlock(); }
|
||||
private:
|
||||
Mutex * const mu_;
|
||||
|
||||
WriterMutexLock(const WriterMutexLock&) = delete;
|
||||
WriterMutexLock& operator=(const WriterMutexLock&) = delete;
|
||||
};
|
||||
|
||||
// Catch bug where variable name is omitted, e.g. MutexLock (&mu);
|
||||
#define MutexLock(x) static_assert(false, "MutexLock declaration missing variable name")
|
||||
#define ReaderMutexLock(x) static_assert(false, "ReaderMutexLock declaration missing variable name")
|
||||
#define WriterMutexLock(x) static_assert(false, "WriterMutexLock declaration missing variable name")
|
||||
|
||||
} // namespace re2
|
||||
|
||||
#endif // UTIL_MUTEX_H_
|
||||
21
Pods/gRPC-C++/third_party/re2/util/strutil.h
generated
vendored
Normal file
21
Pods/gRPC-C++/third_party/re2/util/strutil.h
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2016 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_STRUTIL_H_
|
||||
#define UTIL_STRUTIL_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "re2/stringpiece.h"
|
||||
#include "util/util.h"
|
||||
|
||||
namespace re2 {
|
||||
|
||||
std::string CEscape(const StringPiece& src);
|
||||
void PrefixSuccessor(std::string* prefix);
|
||||
std::string StringPrintf(const char* format, ...);
|
||||
|
||||
} // namespace re2
|
||||
|
||||
#endif // UTIL_STRUTIL_H_
|
||||
44
Pods/gRPC-C++/third_party/re2/util/utf.h
generated
vendored
Normal file
44
Pods/gRPC-C++/third_party/re2/util/utf.h
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* The authors of this software are Rob Pike and Ken Thompson.
|
||||
* Copyright (c) 2002 by Lucent Technologies.
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose without fee is hereby granted, provided that this entire notice
|
||||
* is included in all copies of any software which is or includes a copy
|
||||
* or modification of this software and in all copies of the supporting
|
||||
* documentation for such software.
|
||||
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
|
||||
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*
|
||||
* This file and rune.cc have been converted to compile as C++ code
|
||||
* in name space re2.
|
||||
*/
|
||||
|
||||
#ifndef UTIL_UTF_H_
|
||||
#define UTIL_UTF_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace re2 {
|
||||
|
||||
typedef signed int Rune; /* Code-point values in Unicode 4.0 are 21 bits wide.*/
|
||||
|
||||
enum
|
||||
{
|
||||
UTFmax = 4, /* maximum bytes per rune */
|
||||
Runesync = 0x80, /* cannot represent part of a UTF sequence (<) */
|
||||
Runeself = 0x80, /* rune and UTF sequences are the same (<) */
|
||||
Runeerror = 0xFFFD, /* decoding error in UTF */
|
||||
Runemax = 0x10FFFF, /* maximum rune value */
|
||||
};
|
||||
|
||||
int runetochar(char* s, const Rune* r);
|
||||
int chartorune(Rune* r, const char* s);
|
||||
int fullrune(const char* s, int n);
|
||||
int utflen(const char* s);
|
||||
char* utfrune(const char*, Rune);
|
||||
|
||||
} // namespace re2
|
||||
|
||||
#endif // UTIL_UTF_H_
|
||||
42
Pods/gRPC-C++/third_party/re2/util/util.h
generated
vendored
Normal file
42
Pods/gRPC-C++/third_party/re2/util/util.h
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright 2009 The RE2 Authors. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef UTIL_UTIL_H_
|
||||
#define UTIL_UTIL_H_
|
||||
|
||||
#define arraysize(array) (sizeof(array)/sizeof((array)[0]))
|
||||
|
||||
#ifndef ATTRIBUTE_NORETURN
|
||||
#if defined(__GNUC__)
|
||||
#define ATTRIBUTE_NORETURN __attribute__((noreturn))
|
||||
#elif defined(_MSC_VER)
|
||||
#define ATTRIBUTE_NORETURN __declspec(noreturn)
|
||||
#else
|
||||
#define ATTRIBUTE_NORETURN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ATTRIBUTE_UNUSED
|
||||
#if defined(__GNUC__)
|
||||
#define ATTRIBUTE_UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define ATTRIBUTE_UNUSED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef FALLTHROUGH_INTENDED
|
||||
#if defined(__clang__)
|
||||
#define FALLTHROUGH_INTENDED [[clang::fallthrough]]
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 7
|
||||
#define FALLTHROUGH_INTENDED [[gnu::fallthrough]]
|
||||
#else
|
||||
#define FALLTHROUGH_INTENDED do {} while (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NO_THREAD_SAFETY_ANALYSIS
|
||||
#define NO_THREAD_SAFETY_ANALYSIS
|
||||
#endif
|
||||
|
||||
#endif // UTIL_UTIL_H_
|
||||
Reference in New Issue
Block a user