| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
1 |
// Tencent is pleased to support the open source community by making RapidJSON available. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
2 |
// |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
3 |
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
4 |
// |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
5 |
// Licensed under the MIT License (the "License"); you may not use this file except |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
6 |
// in compliance with the License. You may obtain a copy of the License at |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
7 |
// |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
8 |
// http://opensource.org/licenses/MIT |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
9 |
// |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
10 |
// Unless required by applicable law or agreed to in writing, software distributed |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
11 |
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
12 |
// CONDITIONS OF ANY KIND, either express or implied. See the License for the |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
13 |
// specific language governing permissions and limitations under the License. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
14 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
15 |
#ifndef CEREAL_RAPIDJSON_INTERNAL_REGEX_H_ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
16 |
#define CEREAL_RAPIDJSON_INTERNAL_REGEX_H_ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
17 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
18 |
#include "../allocators.h" |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
19 |
#include "../stream.h" |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
20 |
#include "stack.h" |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
21 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
22 |
#ifdef __clang__ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
23 |
CEREAL_RAPIDJSON_DIAG_PUSH |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
24 |
CEREAL_RAPIDJSON_DIAG_OFF(padded) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
25 |
CEREAL_RAPIDJSON_DIAG_OFF(switch-enum) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
26 |
CEREAL_RAPIDJSON_DIAG_OFF(implicit-fallthrough) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
27 |
#endif |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
28 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
29 |
#ifdef __GNUC__ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
30 |
CEREAL_RAPIDJSON_DIAG_PUSH |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
31 |
CEREAL_RAPIDJSON_DIAG_OFF(effc++) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
32 |
#endif |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
33 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
34 |
#ifdef _MSC_VER |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
35 |
CEREAL_RAPIDJSON_DIAG_PUSH |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
36 |
CEREAL_RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
37 |
#endif |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
38 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
39 |
#ifndef CEREAL_RAPIDJSON_REGEX_VERBOSE |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
40 |
#define CEREAL_RAPIDJSON_REGEX_VERBOSE 0 |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
41 |
#endif |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
42 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
43 |
CEREAL_RAPIDJSON_NAMESPACE_BEGIN |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
44 |
namespace internal { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
45 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
46 |
/////////////////////////////////////////////////////////////////////////////// |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
47 |
// GenericRegex |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
48 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
49 |
static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1 |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
50 |
static const SizeType kRegexInvalidRange = ~SizeType(0); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
51 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
52 |
//! Regular expression engine with subset of ECMAscript grammar. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
53 |
/*! |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
54 |
Supported regular expression syntax: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
55 |
- \c ab Concatenation |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
56 |
- \c a|b Alternation |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
57 |
- \c a? Zero or one |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
58 |
- \c a* Zero or more |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
59 |
- \c a+ One or more |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
60 |
- \c a{3} Exactly 3 times |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
61 |
- \c a{3,} At least 3 times |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
62 |
- \c a{3,5} 3 to 5 times |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
63 |
- \c (ab) Grouping |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
64 |
- \c ^a At the beginning |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
65 |
- \c a$ At the end |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
66 |
- \c . Any character |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
67 |
- \c [abc] Character classes |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
68 |
- \c [a-c] Character class range |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
69 |
- \c [a-z0-9_] Character class combination |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
70 |
- \c [^abc] Negated character classes |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
71 |
- \c [^a-c] Negated character class range |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
72 |
- \c [\b] Backspace (U+0008) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
73 |
- \c \\| \\\\ ... Escape characters |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
74 |
- \c \\f Form feed (U+000C) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
75 |
- \c \\n Line feed (U+000A) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
76 |
- \c \\r Carriage return (U+000D) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
77 |
- \c \\t Tab (U+0009) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
78 |
- \c \\v Vertical tab (U+000B) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
79 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
80 |
\note This is a Thompson NFA engine, implemented with reference to |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
81 |
Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).", |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
82 |
https://swtch.com/~rsc/regexp/regexp1.html |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
83 |
*/ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
84 |
template <typename Encoding, typename Allocator = CrtAllocator> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
85 |
class GenericRegex { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
86 |
public: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
87 |
typedef typename Encoding::Ch Ch; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
88 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
89 |
GenericRegex(const Ch* source, Allocator* allocator = 0) : |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
90 |
states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
91 |
stateSet_(), state0_(allocator, 0), state1_(allocator, 0), anchorBegin_(), anchorEnd_() |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
92 |
{ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
93 |
GenericStringStream<Encoding> ss(source); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
94 |
DecodedStream<GenericStringStream<Encoding> > ds(ss); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
95 |
Parse(ds); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
96 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
97 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
98 |
~GenericRegex() { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
99 |
Allocator::Free(stateSet_); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
100 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
101 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
102 |
bool IsValid() const { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
103 |
return root_ != kRegexInvalidState; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
104 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
105 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
106 |
template <typename InputStream> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
107 |
bool Match(InputStream& is) const { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
108 |
return SearchWithAnchoring(is, true, true); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
109 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
110 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
111 |
bool Match(const Ch* s) const { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
112 |
GenericStringStream<Encoding> is(s); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
113 |
return Match(is); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
114 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
115 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
116 |
template <typename InputStream> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
117 |
bool Search(InputStream& is) const { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
118 |
return SearchWithAnchoring(is, anchorBegin_, anchorEnd_); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
119 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
120 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
121 |
bool Search(const Ch* s) const { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
122 |
GenericStringStream<Encoding> is(s); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
123 |
return Search(is); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
124 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
125 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
126 |
private: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
127 |
enum Operator { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
128 |
kZeroOrOne, |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
129 |
kZeroOrMore, |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
130 |
kOneOrMore, |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
131 |
kConcatenation, |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
132 |
kAlternation, |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
133 |
kLeftParenthesis |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
134 |
}; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
135 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
136 |
static const unsigned kAnyCharacterClass = 0xFFFFFFFF; //!< For '.' |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
137 |
static const unsigned kRangeCharacterClass = 0xFFFFFFFE; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
138 |
static const unsigned kRangeNegationFlag = 0x80000000; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
139 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
140 |
struct Range { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
141 |
unsigned start; // |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
142 |
unsigned end; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
143 |
SizeType next; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
144 |
}; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
145 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
146 |
struct State { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
147 |
SizeType out; //!< Equals to kInvalid for matching state |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
148 |
SizeType out1; //!< Equals to non-kInvalid for split |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
149 |
SizeType rangeStart; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
150 |
unsigned codepoint; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
151 |
}; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
152 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
153 |
struct Frag { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
154 |
Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
155 |
SizeType start; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
156 |
SizeType out; //!< link-list of all output states |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
157 |
SizeType minIndex; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
158 |
}; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
159 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
160 |
template <typename SourceStream> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
161 |
class DecodedStream { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
162 |
public: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
163 |
DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); } |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
164 |
unsigned Peek() { return codepoint_; } |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
165 |
unsigned Take() { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
166 |
unsigned c = codepoint_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
167 |
if (c) // No further decoding when '\0' |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
168 |
Decode(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
169 |
return c; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
170 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
171 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
172 |
private: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
173 |
void Decode() { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
174 |
if (!Encoding::Decode(ss_, &codepoint_)) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
175 |
codepoint_ = 0; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
176 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
177 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
178 |
SourceStream& ss_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
179 |
unsigned codepoint_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
180 |
}; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
181 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
182 |
State& GetState(SizeType index) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
183 |
CEREAL_RAPIDJSON_ASSERT(index < stateCount_); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
184 |
return states_.template Bottom<State>()[index]; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
185 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
186 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
187 |
const State& GetState(SizeType index) const { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
188 |
CEREAL_RAPIDJSON_ASSERT(index < stateCount_); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
189 |
return states_.template Bottom<State>()[index]; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
190 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
191 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
192 |
Range& GetRange(SizeType index) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
193 |
CEREAL_RAPIDJSON_ASSERT(index < rangeCount_); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
194 |
return ranges_.template Bottom<Range>()[index]; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
195 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
196 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
197 |
const Range& GetRange(SizeType index) const { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
198 |
CEREAL_RAPIDJSON_ASSERT(index < rangeCount_); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
199 |
return ranges_.template Bottom<Range>()[index]; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
200 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
201 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
202 |
template <typename InputStream> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
203 |
void Parse(DecodedStream<InputStream>& ds) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
204 |
Allocator allocator; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
205 |
Stack<Allocator> operandStack(&allocator, 256); // Frag |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
206 |
Stack<Allocator> operatorStack(&allocator, 256); // Operator |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
207 |
Stack<Allocator> atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
208 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
209 |
*atomCountStack.template Push<unsigned>() = 0; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
210 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
211 |
unsigned codepoint; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
212 |
while (ds.Peek() != 0) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
213 |
switch (codepoint = ds.Take()) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
214 |
case '^': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
215 |
anchorBegin_ = true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
216 |
break; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
217 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
218 |
case '$': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
219 |
anchorEnd_ = true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
220 |
break; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
221 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
222 |
case '|': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
223 |
while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
224 |
if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1))) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
225 |
return; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
226 |
*operatorStack.template Push<Operator>() = kAlternation; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
227 |
*atomCountStack.template Top<unsigned>() = 0; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
228 |
break; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
229 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
230 |
case '(': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
231 |
*operatorStack.template Push<Operator>() = kLeftParenthesis; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
232 |
*atomCountStack.template Push<unsigned>() = 0; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
233 |
break; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
234 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
235 |
case ')': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
236 |
while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
237 |
if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1))) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
238 |
return; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
239 |
if (operatorStack.Empty()) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
240 |
return; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
241 |
operatorStack.template Pop<Operator>(1); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
242 |
atomCountStack.template Pop<unsigned>(1); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
243 |
ImplicitConcatenation(atomCountStack, operatorStack); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
244 |
break; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
245 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
246 |
case '?': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
247 |
if (!Eval(operandStack, kZeroOrOne)) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
248 |
return; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
249 |
break; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
250 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
251 |
case '*': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
252 |
if (!Eval(operandStack, kZeroOrMore)) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
253 |
return; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
254 |
break; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
255 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
256 |
case '+': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
257 |
if (!Eval(operandStack, kOneOrMore)) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
258 |
return; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
259 |
break; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
260 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
261 |
case '{': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
262 |
{ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
263 |
unsigned n, m; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
264 |
if (!ParseUnsigned(ds, &n)) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
265 |
return; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
266 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
267 |
if (ds.Peek() == ',') { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
268 |
ds.Take(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
269 |
if (ds.Peek() == '}') |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
270 |
m = kInfinityQuantifier; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
271 |
else if (!ParseUnsigned(ds, &m) || m < n) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
272 |
return; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
273 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
274 |
else |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
275 |
m = n; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
276 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
277 |
if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}') |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
278 |
return; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
279 |
ds.Take(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
280 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
281 |
break; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
282 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
283 |
case '.': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
284 |
PushOperand(operandStack, kAnyCharacterClass); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
285 |
ImplicitConcatenation(atomCountStack, operatorStack); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
286 |
break; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
287 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
288 |
case '[': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
289 |
{ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
290 |
SizeType range; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
291 |
if (!ParseRange(ds, &range)) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
292 |
return; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
293 |
SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
294 |
GetState(s).rangeStart = range; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
295 |
*operandStack.template Push<Frag>() = Frag(s, s, s); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
296 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
297 |
ImplicitConcatenation(atomCountStack, operatorStack); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
298 |
break; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
299 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
300 |
case '\\': // Escape character |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
301 |
if (!CharacterEscape(ds, &codepoint)) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
302 |
return; // Unsupported escape character |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
303 |
// fall through to default |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
304 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
305 |
default: // Pattern character |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
306 |
PushOperand(operandStack, codepoint); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
307 |
ImplicitConcatenation(atomCountStack, operatorStack); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
308 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
309 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
310 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
311 |
while (!operatorStack.Empty()) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
312 |
if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1))) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
313 |
return; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
314 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
315 |
// Link the operand to matching state. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
316 |
if (operandStack.GetSize() == sizeof(Frag)) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
317 |
Frag* e = operandStack.template Pop<Frag>(1); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
318 |
Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
319 |
root_ = e->start; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
320 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
321 |
#if CEREAL_RAPIDJSON_REGEX_VERBOSE |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
322 |
printf("root: %d\n", root_); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
323 |
for (SizeType i = 0; i < stateCount_ ; i++) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
324 |
State& s = GetState(i); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
325 |
printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
326 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
327 |
printf("\n"); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
328 |
#endif |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
329 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
330 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
331 |
// Preallocate buffer for SearchWithAnchoring() |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
332 |
CEREAL_RAPIDJSON_ASSERT(stateSet_ == 0); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
333 |
if (stateCount_ > 0) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
334 |
stateSet_ = static_cast<unsigned*>(states_.GetAllocator().Malloc(GetStateSetSize())); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
335 |
state0_.template Reserve<SizeType>(stateCount_); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
336 |
state1_.template Reserve<SizeType>(stateCount_); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
337 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
338 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
339 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
340 |
SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
341 |
State* s = states_.template Push<State>(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
342 |
s->out = out; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
343 |
s->out1 = out1; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
344 |
s->codepoint = codepoint; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
345 |
s->rangeStart = kRegexInvalidRange; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
346 |
return stateCount_++; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
347 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
348 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
349 |
void PushOperand(Stack<Allocator>& operandStack, unsigned codepoint) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
350 |
SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
351 |
*operandStack.template Push<Frag>() = Frag(s, s, s); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
352 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
353 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
354 |
void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
355 |
if (*atomCountStack.template Top<unsigned>()) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
356 |
*operatorStack.template Push<Operator>() = kConcatenation; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
357 |
(*atomCountStack.template Top<unsigned>())++; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
358 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
359 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
360 |
SizeType Append(SizeType l1, SizeType l2) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
361 |
SizeType old = l1; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
362 |
while (GetState(l1).out != kRegexInvalidState) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
363 |
l1 = GetState(l1).out; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
364 |
GetState(l1).out = l2; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
365 |
return old; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
366 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
367 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
368 |
void Patch(SizeType l, SizeType s) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
369 |
for (SizeType next; l != kRegexInvalidState; l = next) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
370 |
next = GetState(l).out; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
371 |
GetState(l).out = s; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
372 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
373 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
374 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
375 |
bool Eval(Stack<Allocator>& operandStack, Operator op) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
376 |
switch (op) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
377 |
case kConcatenation: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
378 |
CEREAL_RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
379 |
{ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
380 |
Frag e2 = *operandStack.template Pop<Frag>(1); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
381 |
Frag e1 = *operandStack.template Pop<Frag>(1); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
382 |
Patch(e1.out, e2.start); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
383 |
*operandStack.template Push<Frag>() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
384 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
385 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
386 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
387 |
case kAlternation: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
388 |
if (operandStack.GetSize() >= sizeof(Frag) * 2) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
389 |
Frag e2 = *operandStack.template Pop<Frag>(1); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
390 |
Frag e1 = *operandStack.template Pop<Frag>(1); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
391 |
SizeType s = NewState(e1.start, e2.start, 0); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
392 |
*operandStack.template Push<Frag>() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
393 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
394 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
395 |
return false; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
396 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
397 |
case kZeroOrOne: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
398 |
if (operandStack.GetSize() >= sizeof(Frag)) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
399 |
Frag e = *operandStack.template Pop<Frag>(1); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
400 |
SizeType s = NewState(kRegexInvalidState, e.start, 0); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
401 |
*operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
402 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
403 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
404 |
return false; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
405 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
406 |
case kZeroOrMore: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
407 |
if (operandStack.GetSize() >= sizeof(Frag)) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
408 |
Frag e = *operandStack.template Pop<Frag>(1); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
409 |
SizeType s = NewState(kRegexInvalidState, e.start, 0); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
410 |
Patch(e.out, s); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
411 |
*operandStack.template Push<Frag>() = Frag(s, s, e.minIndex); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
412 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
413 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
414 |
return false; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
415 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
416 |
default: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
417 |
CEREAL_RAPIDJSON_ASSERT(op == kOneOrMore); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
418 |
if (operandStack.GetSize() >= sizeof(Frag)) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
419 |
Frag e = *operandStack.template Pop<Frag>(1); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
420 |
SizeType s = NewState(kRegexInvalidState, e.start, 0); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
421 |
Patch(e.out, s); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
422 |
*operandStack.template Push<Frag>() = Frag(e.start, s, e.minIndex); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
423 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
424 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
425 |
return false; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
426 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
427 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
428 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
429 |
bool EvalQuantifier(Stack<Allocator>& operandStack, unsigned n, unsigned m) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
430 |
CEREAL_RAPIDJSON_ASSERT(n <= m); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
431 |
CEREAL_RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
432 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
433 |
if (n == 0) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
434 |
if (m == 0) // a{0} not support |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
435 |
return false; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
436 |
else if (m == kInfinityQuantifier) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
437 |
Eval(operandStack, kZeroOrMore); // a{0,} -> a* |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
438 |
else { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
439 |
Eval(operandStack, kZeroOrOne); // a{0,5} -> a? |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
440 |
for (unsigned i = 0; i < m - 1; i++) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
441 |
CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a? |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
442 |
for (unsigned i = 0; i < m - 1; i++) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
443 |
Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a? |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
444 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
445 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
446 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
447 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
448 |
for (unsigned i = 0; i < n - 1; i++) // a{3} -> a a a |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
449 |
CloneTopOperand(operandStack); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
450 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
451 |
if (m == kInfinityQuantifier) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
452 |
Eval(operandStack, kOneOrMore); // a{3,} -> a a a+ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
453 |
else if (m > n) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
454 |
CloneTopOperand(operandStack); // a{3,5} -> a a a a |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
455 |
Eval(operandStack, kZeroOrOne); // a{3,5} -> a a a a? |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
456 |
for (unsigned i = n; i < m - 1; i++) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
457 |
CloneTopOperand(operandStack); // a{3,5} -> a a a a? a? |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
458 |
for (unsigned i = n; i < m; i++) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
459 |
Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a? |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
460 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
461 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
462 |
for (unsigned i = 0; i < n - 1; i++) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
463 |
Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a? |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
464 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
465 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
466 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
467 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
468 |
static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; } |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
469 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
470 |
void CloneTopOperand(Stack<Allocator>& operandStack) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
471 |
const Frag src = *operandStack.template Top<Frag>(); // Copy constructor to prevent invalidation |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
472 |
SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
473 |
State* s = states_.template Push<State>(count); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
474 |
memcpy(s, &GetState(src.minIndex), count * sizeof(State)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
475 |
for (SizeType j = 0; j < count; j++) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
476 |
if (s[j].out != kRegexInvalidState) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
477 |
s[j].out += count; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
478 |
if (s[j].out1 != kRegexInvalidState) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
479 |
s[j].out1 += count; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
480 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
481 |
*operandStack.template Push<Frag>() = Frag(src.start + count, src.out + count, src.minIndex + count); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
482 |
stateCount_ += count; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
483 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
484 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
485 |
template <typename InputStream> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
486 |
bool ParseUnsigned(DecodedStream<InputStream>& ds, unsigned* u) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
487 |
unsigned r = 0; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
488 |
if (ds.Peek() < '0' || ds.Peek() > '9') |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
489 |
return false; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
490 |
while (ds.Peek() >= '0' && ds.Peek() <= '9') { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
491 |
if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295 |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
492 |
return false; // overflow |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
493 |
r = r * 10 + (ds.Take() - '0'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
494 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
495 |
*u = r; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
496 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
497 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
498 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
499 |
template <typename InputStream> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
500 |
bool ParseRange(DecodedStream<InputStream>& ds, SizeType* range) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
501 |
bool isBegin = true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
502 |
bool negate = false; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
503 |
int step = 0; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
504 |
SizeType start = kRegexInvalidRange; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
505 |
SizeType current = kRegexInvalidRange; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
506 |
unsigned codepoint; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
507 |
while ((codepoint = ds.Take()) != 0) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
508 |
if (isBegin) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
509 |
isBegin = false; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
510 |
if (codepoint == '^') { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
511 |
negate = true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
512 |
continue; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
513 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
514 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
515 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
516 |
switch (codepoint) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
517 |
case ']': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
518 |
if (start == kRegexInvalidRange) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
519 |
return false; // Error: nothing inside [] |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
520 |
if (step == 2) { // Add trailing '-' |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
521 |
SizeType r = NewRange('-'); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
522 |
CEREAL_RAPIDJSON_ASSERT(current != kRegexInvalidRange); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
523 |
GetRange(current).next = r; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
524 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
525 |
if (negate) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
526 |
GetRange(start).start |= kRangeNegationFlag; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
527 |
*range = start; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
528 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
529 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
530 |
case '\\': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
531 |
if (ds.Peek() == 'b') { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
532 |
ds.Take(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
533 |
codepoint = 0x0008; // Escape backspace character |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
534 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
535 |
else if (!CharacterEscape(ds, &codepoint)) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
536 |
return false; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
537 |
// fall through to default |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
538 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
539 |
default: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
540 |
switch (step) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
541 |
case 1: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
542 |
if (codepoint == '-') { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
543 |
step++; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
544 |
break; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
545 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
546 |
// fall through to step 0 for other characters |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
547 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
548 |
case 0: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
549 |
{ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
550 |
SizeType r = NewRange(codepoint); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
551 |
if (current != kRegexInvalidRange) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
552 |
GetRange(current).next = r; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
553 |
if (start == kRegexInvalidRange) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
554 |
start = r; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
555 |
current = r; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
556 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
557 |
step = 1; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
558 |
break; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
559 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
560 |
default: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
561 |
CEREAL_RAPIDJSON_ASSERT(step == 2); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
562 |
GetRange(current).end = codepoint; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
563 |
step = 0; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
564 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
565 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
566 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
567 |
return false; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
568 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
569 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
570 |
SizeType NewRange(unsigned codepoint) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
571 |
Range* r = ranges_.template Push<Range>(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
572 |
r->start = r->end = codepoint; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
573 |
r->next = kRegexInvalidRange; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
574 |
return rangeCount_++; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
575 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
576 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
577 |
template <typename InputStream> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
578 |
bool CharacterEscape(DecodedStream<InputStream>& ds, unsigned* escapedCodepoint) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
579 |
unsigned codepoint; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
580 |
switch (codepoint = ds.Take()) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
581 |
case '^': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
582 |
case '$': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
583 |
case '|': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
584 |
case '(': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
585 |
case ')': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
586 |
case '?': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
587 |
case '*': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
588 |
case '+': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
589 |
case '.': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
590 |
case '[': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
591 |
case ']': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
592 |
case '{': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
593 |
case '}': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
594 |
case '\\': |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
595 |
*escapedCodepoint = codepoint; return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
596 |
case 'f': *escapedCodepoint = 0x000C; return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
597 |
case 'n': *escapedCodepoint = 0x000A; return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
598 |
case 'r': *escapedCodepoint = 0x000D; return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
599 |
case 't': *escapedCodepoint = 0x0009; return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
600 |
case 'v': *escapedCodepoint = 0x000B; return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
601 |
default: |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
602 |
return false; // Unsupported escape character |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
603 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
604 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
605 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
606 |
template <typename InputStream> |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
607 |
bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
608 |
CEREAL_RAPIDJSON_ASSERT(IsValid()); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
609 |
DecodedStream<InputStream> ds(is); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
610 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
611 |
state0_.Clear(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
612 |
Stack<Allocator> *current = &state0_, *next = &state1_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
613 |
const size_t stateSetSize = GetStateSetSize(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
614 |
std::memset(stateSet_, 0, stateSetSize); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
615 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
616 |
bool matched = AddState(*current, root_); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
617 |
unsigned codepoint; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
618 |
while (!current->Empty() && (codepoint = ds.Take()) != 0) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
619 |
std::memset(stateSet_, 0, stateSetSize); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
620 |
next->Clear(); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
621 |
matched = false; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
622 |
for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
623 |
const State& sr = GetState(*s); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
624 |
if (sr.codepoint == codepoint || |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
625 |
sr.codepoint == kAnyCharacterClass || |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
626 |
(sr.codepoint == kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint))) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
627 |
{ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
628 |
matched = AddState(*next, sr.out) || matched; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
629 |
if (!anchorEnd && matched) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
630 |
return true; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
631 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
632 |
if (!anchorBegin) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
633 |
AddState(*next, root_); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
634 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
635 |
internal::Swap(current, next); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
636 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
637 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
638 |
return matched; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
639 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
640 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
641 |
size_t GetStateSetSize() const { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
642 |
return (stateCount_ + 31) / 32 * 4; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
643 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
644 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
645 |
// Return whether the added states is a match state |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
646 |
bool AddState(Stack<Allocator>& l, SizeType index) const { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
647 |
CEREAL_RAPIDJSON_ASSERT(index != kRegexInvalidState); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
648 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
649 |
const State& s = GetState(index); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
650 |
if (s.out1 != kRegexInvalidState) { // Split |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
651 |
bool matched = AddState(l, s.out); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
652 |
return AddState(l, s.out1) || matched; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
653 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
654 |
else if (!(stateSet_[index >> 5] & (1 << (index & 31)))) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
655 |
stateSet_[index >> 5] |= (1 << (index & 31)); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
656 |
*l.template PushUnsafe<SizeType>() = index; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
657 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
658 |
return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation. |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
659 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
660 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
661 |
bool MatchRange(SizeType rangeIndex, unsigned codepoint) const { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
662 |
bool yes = (GetRange(rangeIndex).start & kRangeNegationFlag) == 0; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
663 |
while (rangeIndex != kRegexInvalidRange) { |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
664 |
const Range& r = GetRange(rangeIndex); |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
665 |
if (codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end) |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
666 |
return yes; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
667 |
rangeIndex = r.next; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
668 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
669 |
return !yes; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
670 |
} |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
671 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
672 |
Stack<Allocator> states_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
673 |
Stack<Allocator> ranges_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
674 |
SizeType root_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
675 |
SizeType stateCount_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
676 |
SizeType rangeCount_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
677 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
678 |
static const unsigned kInfinityQuantifier = ~0u; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
679 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
680 |
// For SearchWithAnchoring() |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
681 |
uint32_t* stateSet_; // allocated by states_.GetAllocator() |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
682 |
mutable Stack<Allocator> state0_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
683 |
mutable Stack<Allocator> state1_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
684 |
bool anchorBegin_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
685 |
bool anchorEnd_; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
686 |
}; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
687 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
688 |
typedef GenericRegex<UTF8<> > Regex; |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
689 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
690 |
} // namespace internal |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
691 |
CEREAL_RAPIDJSON_NAMESPACE_END |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
692 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
693 |
#ifdef __clang__ |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
694 |
CEREAL_RAPIDJSON_DIAG_POP |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
695 |
#endif |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
696 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
697 |
#ifdef _MSC_VER |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
698 |
CEREAL_RAPIDJSON_DIAG_POP |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
699 |
#endif |
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
700 |
|
| 6c5f2c01 |
sago007 |
2017-03-15 17:56 |
701 |
#endif // CEREAL_RAPIDJSON_INTERNAL_REGEX_H_ |
|
|
1970-01-01 00:00 |
702 |
|