regex.h 24 KB

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