Monero
Loading...
Searching...
No Matches
regex.h
Go to the documentation of this file.
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
15#ifndef RAPIDJSON_INTERNAL_REGEX_H_
16#define RAPIDJSON_INTERNAL_REGEX_H_
17
18#include "../allocators.h"
19#include "../stream.h"
20#include "stack.h"
21
22#ifdef __clang__
23RAPIDJSON_DIAG_PUSH
24RAPIDJSON_DIAG_OFF(padded)
25RAPIDJSON_DIAG_OFF(switch-enum)
26RAPIDJSON_DIAG_OFF(implicit-fallthrough)
27#elif defined(_MSC_VER)
28RAPIDJSON_DIAG_PUSH
29RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
30#endif
31
32#ifdef __GNUC__
33RAPIDJSON_DIAG_PUSH
34RAPIDJSON_DIAG_OFF(effc++)
35#if __GNUC__ >= 7
36RAPIDJSON_DIAG_OFF(implicit-fallthrough)
37#endif
38#endif
39
40#ifndef RAPIDJSON_REGEX_VERBOSE
41#define RAPIDJSON_REGEX_VERBOSE 0
42#endif
43
45namespace internal {
46
48// DecodedStream
49
50template <typename SourceStream, typename Encoding>
52public:
53 DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
54 unsigned Peek() { return codepoint_; }
55 unsigned Take() {
56 unsigned c = codepoint_;
57 if (c) // No further decoding when '\0'
58 Decode();
59 return c;
60 }
61
62private:
63 void Decode() {
64 if (!Encoding::Decode(ss_, &codepoint_))
65 codepoint_ = 0;
66 }
67
68 SourceStream& ss_;
69 unsigned codepoint_;
70};
71
73// GenericRegex
74
77
78template <typename Encoding, typename Allocator>
80
82
113template <typename Encoding, typename Allocator = CrtAllocator>
115public:
117 typedef typename Encoding::Ch Ch;
118 template <typename, typename> friend class GenericRegexSearch;
119
120 GenericRegex(const Ch* source, Allocator* allocator = 0) :
121 states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
123 {
126 Parse(ds);
127 }
128
130
131 bool IsValid() const {
132 return root_ != kRegexInvalidState;
133 }
134
135private:
144
145 static const unsigned kAnyCharacterClass = 0xFFFFFFFF;
146 static const unsigned kRangeCharacterClass = 0xFFFFFFFE;
147 static const unsigned kRangeNegationFlag = 0x80000000;
148
149 struct Range {
150 unsigned start; //
151 unsigned end;
153 };
154
161
168
169 State& GetState(SizeType index) {
171 return states_.template Bottom<State>()[index];
172 }
173
174 const State& GetState(SizeType index) const {
176 return states_.template Bottom<State>()[index];
177 }
178
179 Range& GetRange(SizeType index) {
181 return ranges_.template Bottom<Range>()[index];
182 }
183
184 const Range& GetRange(SizeType index) const {
186 return ranges_.template Bottom<Range>()[index];
187 }
188
189 template <typename InputStream>
191 Allocator allocator;
192 Stack<Allocator> operandStack(&allocator, 256); // Frag
193 Stack<Allocator> operatorStack(&allocator, 256); // Operator
194 Stack<Allocator> atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis)
195
196 *atomCountStack.template Push<unsigned>() = 0;
197
198 unsigned codepoint;
199 while (ds.Peek() != 0) {
200 switch (codepoint = ds.Take()) {
201 case '^':
202 anchorBegin_ = true;
203 break;
204
205 case '$':
206 anchorEnd_ = true;
207 break;
208
209 case '|':
210 while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation)
211 if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
212 return;
213 *operatorStack.template Push<Operator>() = kAlternation;
214 *atomCountStack.template Top<unsigned>() = 0;
215 break;
216
217 case '(':
218 *operatorStack.template Push<Operator>() = kLeftParenthesis;
219 *atomCountStack.template Push<unsigned>() = 0;
220 break;
221
222 case ')':
223 while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis)
224 if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
225 return;
226 if (operatorStack.Empty())
227 return;
228 operatorStack.template Pop<Operator>(1);
229 atomCountStack.template Pop<unsigned>(1);
230 ImplicitConcatenation(atomCountStack, operatorStack);
231 break;
232
233 case '?':
234 if (!Eval(operandStack, kZeroOrOne))
235 return;
236 break;
237
238 case '*':
239 if (!Eval(operandStack, kZeroOrMore))
240 return;
241 break;
242
243 case '+':
244 if (!Eval(operandStack, kOneOrMore))
245 return;
246 break;
247
248 case '{':
249 {
250 unsigned n, m;
251 if (!ParseUnsigned(ds, &n))
252 return;
253
254 if (ds.Peek() == ',') {
255 ds.Take();
256 if (ds.Peek() == '}')
258 else if (!ParseUnsigned(ds, &m) || m < n)
259 return;
260 }
261 else
262 m = n;
263
264 if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}')
265 return;
266 ds.Take();
267 }
268 break;
269
270 case '.':
271 PushOperand(operandStack, kAnyCharacterClass);
272 ImplicitConcatenation(atomCountStack, operatorStack);
273 break;
274
275 case '[':
276 {
277 SizeType range;
278 if (!ParseRange(ds, &range))
279 return;
281 GetState(s).rangeStart = range;
282 *operandStack.template Push<Frag>() = Frag(s, s, s);
283 }
284 ImplicitConcatenation(atomCountStack, operatorStack);
285 break;
286
287 case '\\': // Escape character
288 if (!CharacterEscape(ds, &codepoint))
289 return; // Unsupported escape character
290 // fall through to default
291
292 default: // Pattern character
293 PushOperand(operandStack, codepoint);
294 ImplicitConcatenation(atomCountStack, operatorStack);
295 }
296 }
297
298 while (!operatorStack.Empty())
299 if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
300 return;
301
302 // Link the operand to matching state.
303 if (operandStack.GetSize() == sizeof(Frag)) {
304 Frag* e = operandStack.template Pop<Frag>(1);
306 root_ = e->start;
307
308#if RAPIDJSON_REGEX_VERBOSE
309 printf("root: %d\n", root_);
310 for (SizeType i = 0; i < stateCount_ ; i++) {
311 State& s = GetState(i);
312 printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint);
313 }
314 printf("\n");
315#endif
316 }
317 }
318
319 SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) {
320 State* s = states_.template Push<State>();
321 s->out = out;
322 s->out1 = out1;
323 s->codepoint = codepoint;
324 s->rangeStart = kRegexInvalidRange;
325 return stateCount_++;
326 }
327
328 void PushOperand(Stack<Allocator>& operandStack, unsigned codepoint) {
330 *operandStack.template Push<Frag>() = Frag(s, s, s);
331 }
332
333 void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) {
334 if (*atomCountStack.template Top<unsigned>())
335 *operatorStack.template Push<Operator>() = kConcatenation;
336 (*atomCountStack.template Top<unsigned>())++;
337 }
338
340 SizeType old = l1;
341 while (GetState(l1).out != kRegexInvalidState)
342 l1 = GetState(l1).out;
343 GetState(l1).out = l2;
344 return old;
345 }
346
348 for (SizeType next; l != kRegexInvalidState; l = next) {
349 next = GetState(l).out;
350 GetState(l).out = s;
351 }
352 }
353
354 bool Eval(Stack<Allocator>& operandStack, Operator op) {
355 switch (op) {
356 case kConcatenation:
357 RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2);
358 {
359 Frag e2 = *operandStack.template Pop<Frag>(1);
360 Frag e1 = *operandStack.template Pop<Frag>(1);
361 Patch(e1.out, e2.start);
362 *operandStack.template Push<Frag>() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex));
363 }
364 return true;
365
366 case kAlternation:
367 if (operandStack.GetSize() >= sizeof(Frag) * 2) {
368 Frag e2 = *operandStack.template Pop<Frag>(1);
369 Frag e1 = *operandStack.template Pop<Frag>(1);
370 SizeType s = NewState(e1.start, e2.start, 0);
371 *operandStack.template Push<Frag>() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex));
372 return true;
373 }
374 return false;
375
376 case kZeroOrOne:
377 if (operandStack.GetSize() >= sizeof(Frag)) {
378 Frag e = *operandStack.template Pop<Frag>(1);
379 SizeType s = NewState(kRegexInvalidState, e.start, 0);
380 *operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex);
381 return true;
382 }
383 return false;
384
385 case kZeroOrMore:
386 if (operandStack.GetSize() >= sizeof(Frag)) {
387 Frag e = *operandStack.template Pop<Frag>(1);
388 SizeType s = NewState(kRegexInvalidState, e.start, 0);
389 Patch(e.out, s);
390 *operandStack.template Push<Frag>() = Frag(s, s, e.minIndex);
391 return true;
392 }
393 return false;
394
395 default:
397 if (operandStack.GetSize() >= sizeof(Frag)) {
398 Frag e = *operandStack.template Pop<Frag>(1);
399 SizeType s = NewState(kRegexInvalidState, e.start, 0);
400 Patch(e.out, s);
401 *operandStack.template Push<Frag>() = Frag(e.start, s, e.minIndex);
402 return true;
403 }
404 return false;
405 }
406 }
407
408 bool EvalQuantifier(Stack<Allocator>& operandStack, unsigned n, unsigned m) {
409 RAPIDJSON_ASSERT(n <= m);
410 RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag));
411
412 if (n == 0) {
413 if (m == 0) // a{0} not support
414 return false;
415 else if (m == kInfinityQuantifier)
416 Eval(operandStack, kZeroOrMore); // a{0,} -> a*
417 else {
418 Eval(operandStack, kZeroOrOne); // a{0,5} -> a?
419 for (unsigned i = 0; i < m - 1; i++)
420 CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a?
421 for (unsigned i = 0; i < m - 1; i++)
422 Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a?
423 }
424 return true;
425 }
426
427 for (unsigned i = 0; i < n - 1; i++) // a{3} -> a a a
428 CloneTopOperand(operandStack);
429
430 if (m == kInfinityQuantifier)
431 Eval(operandStack, kOneOrMore); // a{3,} -> a a a+
432 else if (m > n) {
433 CloneTopOperand(operandStack); // a{3,5} -> a a a a
434 Eval(operandStack, kZeroOrOne); // a{3,5} -> a a a a?
435 for (unsigned i = n; i < m - 1; i++)
436 CloneTopOperand(operandStack); // a{3,5} -> a a a a? a?
437 for (unsigned i = n; i < m; i++)
438 Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a?
439 }
440
441 for (unsigned i = 0; i < n - 1; i++)
442 Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a?
443
444 return true;
445 }
446
447 static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; }
448
449 void CloneTopOperand(Stack<Allocator>& operandStack) {
450 const Frag src = *operandStack.template Top<Frag>(); // Copy constructor to prevent invalidation
451 SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_)
452 State* s = states_.template Push<State>(count);
453 memcpy(s, &GetState(src.minIndex), count * sizeof(State));
454 for (SizeType j = 0; j < count; j++) {
455 if (s[j].out != kRegexInvalidState)
456 s[j].out += count;
457 if (s[j].out1 != kRegexInvalidState)
458 s[j].out1 += count;
459 }
460 *operandStack.template Push<Frag>() = Frag(src.start + count, src.out + count, src.minIndex + count);
461 stateCount_ += count;
462 }
463
464 template <typename InputStream>
466 unsigned r = 0;
467 if (ds.Peek() < '0' || ds.Peek() > '9')
468 return false;
469 while (ds.Peek() >= '0' && ds.Peek() <= '9') {
470 if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295
471 return false; // overflow
472 r = r * 10 + (ds.Take() - '0');
473 }
474 *u = r;
475 return true;
476 }
477
478 template <typename InputStream>
480 bool isBegin = true;
481 bool negate = false;
482 int step = 0;
485 unsigned codepoint;
486 while ((codepoint = ds.Take()) != 0) {
487 if (isBegin) {
488 isBegin = false;
489 if (codepoint == '^') {
490 negate = true;
491 continue;
492 }
493 }
494
495 switch (codepoint) {
496 case ']':
498 return false; // Error: nothing inside []
499 if (step == 2) { // Add trailing '-'
500 SizeType r = NewRange('-');
502 GetRange(current).next = r;
503 }
504 if (negate)
506 *range = start;
507 return true;
508
509 case '\\':
510 if (ds.Peek() == 'b') {
511 ds.Take();
512 codepoint = 0x0008; // Escape backspace character
513 }
514 else if (!CharacterEscape(ds, &codepoint))
515 return false;
516 // fall through to default
517
518 default:
519 switch (step) {
520 case 1:
521 if (codepoint == '-') {
522 step++;
523 break;
524 }
525 // fall through to step 0 for other characters
526
527 case 0:
528 {
529 SizeType r = NewRange(codepoint);
530 if (current != kRegexInvalidRange)
531 GetRange(current).next = r;
533 start = r;
534 current = r;
535 }
536 step = 1;
537 break;
538
539 default:
540 RAPIDJSON_ASSERT(step == 2);
541 GetRange(current).end = codepoint;
542 step = 0;
543 }
544 }
545 }
546 return false;
547 }
548
549 SizeType NewRange(unsigned codepoint) {
550 Range* r = ranges_.template Push<Range>();
551 r->start = r->end = codepoint;
552 r->next = kRegexInvalidRange;
553 return rangeCount_++;
554 }
555
556 template <typename InputStream>
557 bool CharacterEscape(DecodedStream<InputStream, Encoding>& ds, unsigned* escapedCodepoint) {
558 unsigned codepoint;
559 switch (codepoint = ds.Take()) {
560 case '^':
561 case '$':
562 case '|':
563 case '(':
564 case ')':
565 case '?':
566 case '*':
567 case '+':
568 case '.':
569 case '[':
570 case ']':
571 case '{':
572 case '}':
573 case '\\':
574 *escapedCodepoint = codepoint; return true;
575 case 'f': *escapedCodepoint = 0x000C; return true;
576 case 'n': *escapedCodepoint = 0x000A; return true;
577 case 'r': *escapedCodepoint = 0x000D; return true;
578 case 't': *escapedCodepoint = 0x0009; return true;
579 case 'v': *escapedCodepoint = 0x000B; return true;
580 default:
581 return false; // Unsupported escape character
582 }
583 }
584
590
591 static const unsigned kInfinityQuantifier = ~0u;
592
593 // For SearchWithAnchoring()
596};
597
598template <typename RegexType, typename Allocator = CrtAllocator>
600public:
601 typedef typename RegexType::EncodingType Encoding;
602 typedef typename Encoding::Ch Ch;
603
604 GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) :
605 regex_(regex), allocator_(allocator), ownAllocator_(0),
606 state0_(allocator, 0), state1_(allocator, 0), stateSet_()
607 {
608 RAPIDJSON_ASSERT(regex_.IsValid());
609 if (!allocator_)
611 stateSet_ = static_cast<unsigned*>(allocator_->Malloc(GetStateSetSize()));
612 state0_.template Reserve<SizeType>(regex_.stateCount_);
613 state1_.template Reserve<SizeType>(regex_.stateCount_);
614 }
615
617 Allocator::Free(stateSet_);
619 }
620
621 template <typename InputStream>
622 bool Match(InputStream& is) {
623 return SearchWithAnchoring(is, true, true);
624 }
625
626 bool Match(const Ch* s) {
628 return Match(is);
629 }
630
631 template <typename InputStream>
632 bool Search(InputStream& is) {
633 return SearchWithAnchoring(is, regex_.anchorBegin_, regex_.anchorEnd_);
634 }
635
636 bool Search(const Ch* s) {
638 return Search(is);
639 }
640
641private:
642 typedef typename RegexType::State State;
643 typedef typename RegexType::Range Range;
644
645 template <typename InputStream>
646 bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) {
648
649 state0_.Clear();
650 Stack<Allocator> *current = &state0_, *next = &state1_;
651 const size_t stateSetSize = GetStateSetSize();
652 std::memset(stateSet_, 0, stateSetSize);
653
654 bool matched = AddState(*current, regex_.root_);
655 unsigned codepoint;
656 while (!current->Empty() && (codepoint = ds.Take()) != 0) {
657 std::memset(stateSet_, 0, stateSetSize);
658 next->Clear();
659 matched = false;
660 for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
661 const State& sr = regex_.GetState(*s);
662 if (sr.codepoint == codepoint ||
663 sr.codepoint == RegexType::kAnyCharacterClass ||
664 (sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
665 {
666 matched = AddState(*next, sr.out) || matched;
667 if (!anchorEnd && matched)
668 return true;
669 }
670 if (!anchorBegin)
671 AddState(*next, regex_.root_);
672 }
673 internal::Swap(current, next);
674 }
675
676 return matched;
677 }
678
679 size_t GetStateSetSize() const {
680 return (regex_.stateCount_ + 31) / 32 * 4;
681 }
682
683 // Return whether the added states is a match state
686
687 const State& s = regex_.GetState(index);
688 if (s.out1 != kRegexInvalidState) { // Split
689 bool matched = AddState(l, s.out);
690 return AddState(l, s.out1) || matched;
691 }
692 else if (!(stateSet_[index >> 5] & (1u << (index & 31)))) {
693 stateSet_[index >> 5] |= (1u << (index & 31));
694 *l.template PushUnsafe<SizeType>() = index;
695 }
696 return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
697 }
698
699 bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
700 bool yes = (regex_.GetRange(rangeIndex).start & RegexType::kRangeNegationFlag) == 0;
701 while (rangeIndex != kRegexInvalidRange) {
702 const Range& r = regex_.GetRange(rangeIndex);
703 if (codepoint >= (r.start & ~RegexType::kRangeNegationFlag) && codepoint <= r.end)
704 return yes;
705 rangeIndex = r.next;
706 }
707 return !yes;
708 }
709
710 const RegexType& regex_;
716};
717
720
721} // namespace internal
723
724#ifdef __GNUC__
725RAPIDJSON_DIAG_POP
726#endif
727
728#if defined(__clang__) || defined(_MSC_VER)
729RAPIDJSON_DIAG_POP
730#endif
731
732#endif // RAPIDJSON_INTERNAL_REGEX_H_
#define s(x, c)
Definition aesb.c:47
cryptonote::block b
Definition block.cpp:40
Definition regex.h:51
DecodedStream(SourceStream &ss)
Definition regex.h:53
unsigned Take()
Definition regex.h:55
unsigned codepoint_
Definition regex.h:69
unsigned Peek()
Definition regex.h:54
SourceStream & ss_
Definition regex.h:68
void Decode()
Definition regex.h:63
Definition regex.h:599
Stack< CrtAllocator > state1_
Definition regex.h:714
RegexType::State State
Definition regex.h:642
size_t GetStateSetSize() const
Definition regex.h:679
bool MatchRange(SizeType rangeIndex, unsigned codepoint) const
Definition regex.h:699
uint32_t * stateSet_
Definition regex.h:715
Stack< CrtAllocator > state0_
Definition regex.h:713
GenericRegexSearch(const RegexType &regex, Allocator *allocator=0)
Definition regex.h:604
bool Search(InputStream &is)
Definition regex.h:632
RegexType::EncodingType Encoding
Definition regex.h:601
CrtAllocator * ownAllocator_
Definition regex.h:712
bool SearchWithAnchoring(InputStream &is, bool anchorBegin, bool anchorEnd)
Definition regex.h:646
Encoding::Ch Ch
Definition regex.h:602
bool Search(const Ch *s)
Definition regex.h:636
bool Match(const Ch *s)
Definition regex.h:626
bool AddState(Stack< Allocator > &l, SizeType index)
Definition regex.h:684
CrtAllocator * allocator_
Definition regex.h:711
RegexType::Range Range
Definition regex.h:643
const Regex & regex_
Definition regex.h:710
~GenericRegexSearch()
Definition regex.h:616
bool Match(InputStream &is)
Definition regex.h:622
Regular expression engine with subset of ECMAscript grammar.
Definition regex.h:114
void Parse(DecodedStream< InputStream, Encoding > &ds)
Definition regex.h:190
static SizeType Min(SizeType a, SizeType b)
Definition regex.h:447
bool Eval(Stack< Allocator > &operandStack, Operator op)
Definition regex.h:354
static const unsigned kInfinityQuantifier
Definition regex.h:591
bool ParseUnsigned(DecodedStream< InputStream, Encoding > &ds, unsigned *u)
Definition regex.h:465
void PushOperand(Stack< Allocator > &operandStack, unsigned codepoint)
Definition regex.h:328
static const unsigned kAnyCharacterClass
Definition regex.h:145
SizeType root_
Definition regex.h:587
bool IsValid() const
Definition regex.h:131
GenericRegex(const Ch *source, Allocator *allocator=0)
Definition regex.h:120
void ImplicitConcatenation(Stack< Allocator > &atomCountStack, Stack< Allocator > &operatorStack)
Definition regex.h:333
void CloneTopOperand(Stack< Allocator > &operandStack)
Definition regex.h:449
Encoding::Ch Ch
Definition regex.h:117
Stack< CrtAllocator > states_
Definition regex.h:585
~GenericRegex()
Definition regex.h:129
bool EvalQuantifier(Stack< Allocator > &operandStack, unsigned n, unsigned m)
Definition regex.h:408
const Range & GetRange(SizeType index) const
Definition regex.h:184
Range & GetRange(SizeType index)
Definition regex.h:179
SizeType NewRange(unsigned codepoint)
Definition regex.h:549
Encoding EncodingType
Definition regex.h:116
void Patch(SizeType l, SizeType s)
Definition regex.h:347
friend class GenericRegexSearch
Definition regex.h:118
SizeType Append(SizeType l1, SizeType l2)
Definition regex.h:339
bool ParseRange(DecodedStream< InputStream, Encoding > &ds, SizeType *range)
Definition regex.h:479
bool anchorBegin_
Definition regex.h:594
Operator
Definition regex.h:136
@ kOneOrMore
Definition regex.h:139
@ kAlternation
Definition regex.h:141
@ kConcatenation
Definition regex.h:140
@ kZeroOrMore
Definition regex.h:138
@ kZeroOrOne
Definition regex.h:137
@ kLeftParenthesis
Definition regex.h:142
SizeType NewState(SizeType out, SizeType out1, unsigned codepoint)
Definition regex.h:319
SizeType rangeCount_
Definition regex.h:589
const State & GetState(SizeType index) const
Definition regex.h:174
bool anchorEnd_
Definition regex.h:595
static const unsigned kRangeNegationFlag
Definition regex.h:147
bool CharacterEscape(DecodedStream< InputStream, Encoding > &ds, unsigned *escapedCodepoint)
Definition regex.h:557
State & GetState(SizeType index)
Definition regex.h:169
static const unsigned kRangeCharacterClass
Definition regex.h:146
SizeType stateCount_
Definition regex.h:588
Stack< CrtAllocator > ranges_
Definition regex.h:586
A type-unsafe stack for storing different types of data.
Definition stack.h:36
bool Empty() const
Definition stack.h:176
size_t GetSize() const
Definition stack.h:177
Concept for allocating, resizing and freeing memory block.
Concept for encoding of Unicode characters.
conn start()
void * memcpy(void *a, const void *b, size_t c)
Definition glibc_compat.cpp:16
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition rapidjson.h:411
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition rapidjson.h:121
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition rapidjson.h:124
Definition document.h:406
GenericRegexSearch< Regex > RegexSearch
Definition regex.h:719
void Swap(T &a, T &b) RAPIDJSON_NOEXCEPT
Custom swap() to avoid dependency on C++ <algorithm> header.
Definition swap.h:33
static const SizeType kRegexInvalidState
Represents an invalid index in GenericRegex::State::out, out1.
Definition regex.h:75
GenericRegex< UTF8<> > Regex
Definition regex.h:718
static const SizeType kRegexInvalidRange
Definition regex.h:76
const CharType(& source)[N]
Definition pointer.h:1147
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1124
#define RAPIDJSON_DELETE(x)
! customization point for global delete
Definition rapidjson.h:610
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.).
Definition rapidjson.h:389
#define RAPIDJSON_NEW(TypeName)
! customization point for global new
Definition rapidjson.h:606
unsigned int uint32_t
Definition stdint.h:126
Read-only string stream.
Definition stream.h:154
Frag(SizeType s, SizeType o, SizeType m)
Definition regex.h:163
SizeType out
link-list of all output states
Definition regex.h:165
SizeType minIndex
Definition regex.h:166
SizeType start
Definition regex.h:164
Definition regex.h:149
unsigned end
Definition regex.h:151
unsigned start
Definition regex.h:150
SizeType next
Definition regex.h:152
Definition regex.h:155
SizeType out1
Equals to non-kInvalid for split.
Definition regex.h:157
SizeType out
Equals to kInvalid for matching state.
Definition regex.h:156
SizeType rangeStart
Definition regex.h:158
unsigned codepoint
Definition regex.h:159