regex.h 25 KB

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