Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
regex.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2// Tencent is pleased to support the open source community by making RapidJSON available.
3//
4// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
5//
6// Licensed under the MIT License (the "License"); you may not use this file except
7// in compliance with the License. You may obtain a copy of the License at
8//
9// http://opensource.org/licenses/MIT
10//
11// Unless required by applicable law or agreed to in writing, software distributed
12// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
13// CONDITIONS OF ANY KIND, either express or implied. See the License for the
14// specific language governing permissions and limitations under the License.
15
16#ifndef RAPIDJSON_INTERNAL_REGEX_H_
17#define RAPIDJSON_INTERNAL_REGEX_H_
18
19#include "../allocators.h"
20#include "../stream.h"
21#include "stack.h"
22
23#ifdef __clang__
24RAPIDJSON_DIAG_PUSH
25RAPIDJSON_DIAG_OFF(padded)
26RAPIDJSON_DIAG_OFF(switch-enum)
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#endif
36
37#ifndef RAPIDJSON_REGEX_VERBOSE
38#define RAPIDJSON_REGEX_VERBOSE 0
39#endif
40
42namespace internal {
43
45// DecodedStream
46
47template <typename SourceStream, typename Encoding>
49public:
50 DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
51 unsigned Peek() { return codepoint_; }
52 unsigned Take() {
53 unsigned c = codepoint_;
54 if (c) // No further decoding when '\0'
55 Decode();
56 return c;
57 }
58
59private:
60 void Decode() {
61 if (!Encoding::Decode(ss_, &codepoint_))
62 codepoint_ = 0;
63 }
64
65 SourceStream& ss_;
66 unsigned codepoint_;
67};
68
70// GenericRegex
71
72static const SizeType kRegexInvalidState = ~SizeType(0);
73static const SizeType kRegexInvalidRange = ~SizeType(0);
74
75template <typename Encoding, typename Allocator>
77
79
110template <typename Encoding, typename Allocator = CrtAllocator>
112public:
113 typedef Encoding EncodingType;
114 typedef typename Encoding::Ch Ch;
115 template <typename, typename> friend class GenericRegexSearch;
116
117 GenericRegex(const Ch* source, Allocator* allocator = 0) :
118 ownAllocator_(allocator ? 0 : RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_),
119 states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
120 anchorBegin_(), anchorEnd_()
121 {
124 Parse(ds);
125 }
126
128 {
129 RAPIDJSON_DELETE(ownAllocator_);
130 }
131
132 bool IsValid() const {
133 return root_ != kRegexInvalidState;
134 }
135
136private:
137 enum Operator {
138 kZeroOrOne,
139 kZeroOrMore,
140 kOneOrMore,
141 kConcatenation,
142 kAlternation,
143 kLeftParenthesis
144 };
145
146 static const unsigned kAnyCharacterClass = 0xFFFFFFFF;
147 static const unsigned kRangeCharacterClass = 0xFFFFFFFE;
148 static const unsigned kRangeNegationFlag = 0x80000000;
149
150 struct Range {
151 unsigned start; //
152 unsigned end;
153 SizeType next;
154 };
155
156 struct State {
159 SizeType rangeStart;
160 unsigned codepoint;
161 };
162
163 struct Frag {
164 Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {}
165 SizeType start;
167 SizeType minIndex;
168 };
169
170 State& GetState(SizeType index) {
171 RAPIDJSON_ASSERT(index < stateCount_);
172 return states_.template Bottom<State>()[index];
173 }
174
175 const State& GetState(SizeType index) const {
176 RAPIDJSON_ASSERT(index < stateCount_);
177 return states_.template Bottom<State>()[index];
178 }
179
180 Range& GetRange(SizeType index) {
181 RAPIDJSON_ASSERT(index < rangeCount_);
182 return ranges_.template Bottom<Range>()[index];
183 }
184
185 const Range& GetRange(SizeType index) const {
186 RAPIDJSON_ASSERT(index < rangeCount_);
187 return ranges_.template Bottom<Range>()[index];
188 }
189
190 template <typename InputStream>
191 void Parse(DecodedStream<InputStream, Encoding>& ds) {
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() == '}')
257 m = kInfinityQuantifier;
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;
280 SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass);
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 RAPIDJSON_DELIBERATE_FALLTHROUGH;
292
293 default: // Pattern character
294 PushOperand(operandStack, codepoint);
295 ImplicitConcatenation(atomCountStack, operatorStack);
296 }
297 }
298
299 while (!operatorStack.Empty())
300 if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
301 return;
302
303 // Link the operand to matching state.
304 if (operandStack.GetSize() == sizeof(Frag)) {
305 Frag* e = operandStack.template Pop<Frag>(1);
306 Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0));
307 root_ = e->start;
308
309#if RAPIDJSON_REGEX_VERBOSE
310 printf("root: %d\n", root_);
311 for (SizeType i = 0; i < stateCount_ ; i++) {
312 State& s = GetState(i);
313 printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint);
314 }
315 printf("\n");
316#endif
317 }
318 }
319
320 SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) {
321 State* s = states_.template Push<State>();
322 s->out = out;
323 s->out1 = out1;
324 s->codepoint = codepoint;
325 s->rangeStart = kRegexInvalidRange;
326 return stateCount_++;
327 }
328
329 void PushOperand(Stack<Allocator>& operandStack, unsigned codepoint) {
330 SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint);
331 *operandStack.template Push<Frag>() = Frag(s, s, s);
332 }
333
334 void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) {
335 if (*atomCountStack.template Top<unsigned>())
336 *operatorStack.template Push<Operator>() = kConcatenation;
337 (*atomCountStack.template Top<unsigned>())++;
338 }
339
340 SizeType Append(SizeType l1, SizeType l2) {
341 SizeType old = l1;
342 while (GetState(l1).out != kRegexInvalidState)
343 l1 = GetState(l1).out;
344 GetState(l1).out = l2;
345 return old;
346 }
347
348 void Patch(SizeType l, SizeType s) {
349 for (SizeType next; l != kRegexInvalidState; l = next) {
350 next = GetState(l).out;
351 GetState(l).out = s;
352 }
353 }
354
355 bool Eval(Stack<Allocator>& operandStack, Operator op) {
356 switch (op) {
357 case kConcatenation:
358 RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2);
359 {
360 Frag e2 = *operandStack.template Pop<Frag>(1);
361 Frag e1 = *operandStack.template Pop<Frag>(1);
362 Patch(e1.out, e2.start);
363 *operandStack.template Push<Frag>() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex));
364 }
365 return true;
366
367 case kAlternation:
368 if (operandStack.GetSize() >= sizeof(Frag) * 2) {
369 Frag e2 = *operandStack.template Pop<Frag>(1);
370 Frag e1 = *operandStack.template Pop<Frag>(1);
371 SizeType s = NewState(e1.start, e2.start, 0);
372 *operandStack.template Push<Frag>() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex));
373 return true;
374 }
375 return false;
376
377 case kZeroOrOne:
378 if (operandStack.GetSize() >= sizeof(Frag)) {
379 Frag e = *operandStack.template Pop<Frag>(1);
380 SizeType s = NewState(kRegexInvalidState, e.start, 0);
381 *operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex);
382 return true;
383 }
384 return false;
385
386 case kZeroOrMore:
387 if (operandStack.GetSize() >= sizeof(Frag)) {
388 Frag e = *operandStack.template Pop<Frag>(1);
389 SizeType s = NewState(kRegexInvalidState, e.start, 0);
390 Patch(e.out, s);
391 *operandStack.template Push<Frag>() = Frag(s, s, e.minIndex);
392 return true;
393 }
394 return false;
395
396 case kOneOrMore:
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 default:
407 // syntax error (e.g. unclosed kLeftParenthesis)
408 return false;
409 }
410 }
411
412 bool EvalQuantifier(Stack<Allocator>& operandStack, unsigned n, unsigned m) {
413 RAPIDJSON_ASSERT(n <= m);
414 RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag));
415
416 if (n == 0) {
417 if (m == 0) // a{0} not support
418 return false;
419 else if (m == kInfinityQuantifier)
420 Eval(operandStack, kZeroOrMore); // a{0,} -> a*
421 else {
422 Eval(operandStack, kZeroOrOne); // a{0,5} -> a?
423 for (unsigned i = 0; i < m - 1; i++)
424 CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a?
425 for (unsigned i = 0; i < m - 1; i++)
426 Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a?
427 }
428 return true;
429 }
430
431 for (unsigned i = 0; i < n - 1; i++) // a{3} -> a a a
432 CloneTopOperand(operandStack);
433
434 if (m == kInfinityQuantifier)
435 Eval(operandStack, kOneOrMore); // a{3,} -> a a a+
436 else if (m > n) {
437 CloneTopOperand(operandStack); // a{3,5} -> a a a a
438 Eval(operandStack, kZeroOrOne); // a{3,5} -> a a a a?
439 for (unsigned i = n; i < m - 1; i++)
440 CloneTopOperand(operandStack); // a{3,5} -> a a a a? a?
441 for (unsigned i = n; i < m; i++)
442 Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a?
443 }
444
445 for (unsigned i = 0; i < n - 1; i++)
446 Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a?
447
448 return true;
449 }
450
451 static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; }
452
453 void CloneTopOperand(Stack<Allocator>& operandStack) {
454 const Frag src = *operandStack.template Top<Frag>(); // Copy constructor to prevent invalidation
455 SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_)
456 State* s = states_.template Push<State>(count);
457 memcpy(s, &GetState(src.minIndex), count * sizeof(State));
458 for (SizeType j = 0; j < count; j++) {
459 if (s[j].out != kRegexInvalidState)
460 s[j].out += count;
461 if (s[j].out1 != kRegexInvalidState)
462 s[j].out1 += count;
463 }
464 *operandStack.template Push<Frag>() = Frag(src.start + count, src.out + count, src.minIndex + count);
465 stateCount_ += count;
466 }
467
468 template <typename InputStream>
469 bool ParseUnsigned(DecodedStream<InputStream, Encoding>& ds, unsigned* u) {
470 unsigned r = 0;
471 if (ds.Peek() < '0' || ds.Peek() > '9')
472 return false;
473 while (ds.Peek() >= '0' && ds.Peek() <= '9') {
474 if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295
475 return false; // overflow
476 r = r * 10 + (ds.Take() - '0');
477 }
478 *u = r;
479 return true;
480 }
481
482 template <typename InputStream>
483 bool ParseRange(DecodedStream<InputStream, Encoding>& ds, SizeType* range) {
484 bool isBegin = true;
485 bool negate = false;
486 int step = 0;
487 SizeType start = kRegexInvalidRange;
488 SizeType current = kRegexInvalidRange;
489 unsigned codepoint;
490 while ((codepoint = ds.Take()) != 0) {
491 if (isBegin) {
492 isBegin = false;
493 if (codepoint == '^') {
494 negate = true;
495 continue;
496 }
497 }
498
499 switch (codepoint) {
500 case ']':
501 if (start == kRegexInvalidRange)
502 return false; // Error: nothing inside []
503 if (step == 2) { // Add trailing '-'
504 SizeType r = NewRange('-');
505 RAPIDJSON_ASSERT(current != kRegexInvalidRange);
506 GetRange(current).next = r;
507 }
508 if (negate)
509 GetRange(start).start |= kRangeNegationFlag;
510 *range = start;
511 return true;
512
513 case '\\':
514 if (ds.Peek() == 'b') {
515 ds.Take();
516 codepoint = 0x0008; // Escape backspace character
517 }
518 else if (!CharacterEscape(ds, &codepoint))
519 return false;
520 // fall through to default
521 RAPIDJSON_DELIBERATE_FALLTHROUGH;
522
523 default:
524 switch (step) {
525 case 1:
526 if (codepoint == '-') {
527 step++;
528 break;
529 }
530 // fall through to step 0 for other characters
531 RAPIDJSON_DELIBERATE_FALLTHROUGH;
532
533 case 0:
534 {
535 SizeType r = NewRange(codepoint);
536 if (current != kRegexInvalidRange)
537 GetRange(current).next = r;
538 if (start == kRegexInvalidRange)
539 start = r;
540 current = r;
541 }
542 step = 1;
543 break;
544
545 default:
546 RAPIDJSON_ASSERT(step == 2);
547 GetRange(current).end = codepoint;
548 step = 0;
549 }
550 }
551 }
552 return false;
553 }
554
555 SizeType NewRange(unsigned codepoint) {
556 Range* r = ranges_.template Push<Range>();
557 r->start = r->end = codepoint;
558 r->next = kRegexInvalidRange;
559 return rangeCount_++;
560 }
561
562 template <typename InputStream>
563 bool CharacterEscape(DecodedStream<InputStream, Encoding>& ds, unsigned* escapedCodepoint) {
564 unsigned codepoint;
565 switch (codepoint = ds.Take()) {
566 case '^':
567 case '$':
568 case '|':
569 case '(':
570 case ')':
571 case '?':
572 case '*':
573 case '+':
574 case '.':
575 case '[':
576 case ']':
577 case '{':
578 case '}':
579 case '\\':
580 *escapedCodepoint = codepoint; return true;
581 case 'f': *escapedCodepoint = 0x000C; return true;
582 case 'n': *escapedCodepoint = 0x000A; return true;
583 case 'r': *escapedCodepoint = 0x000D; return true;
584 case 't': *escapedCodepoint = 0x0009; return true;
585 case 'v': *escapedCodepoint = 0x000B; return true;
586 default:
587 return false; // Unsupported escape character
588 }
589 }
590
591 Allocator* ownAllocator_;
592 Allocator* allocator_;
593 Stack<Allocator> states_;
594 Stack<Allocator> ranges_;
595 SizeType root_;
596 SizeType stateCount_;
597 SizeType rangeCount_;
598
599 static const unsigned kInfinityQuantifier = ~0u;
600
601 // For SearchWithAnchoring()
602 bool anchorBegin_;
603 bool anchorEnd_;
604};
605
606template <typename RegexType, typename Allocator = CrtAllocator>
608public:
609 typedef typename RegexType::EncodingType Encoding;
610 typedef typename Encoding::Ch Ch;
611
612 GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) :
613 regex_(regex), allocator_(allocator), ownAllocator_(0),
614 state0_(allocator, 0), state1_(allocator, 0), stateSet_()
615 {
616 RAPIDJSON_ASSERT(regex_.IsValid());
617 if (!allocator_)
618 ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
619 stateSet_ = static_cast<unsigned*>(allocator_->Malloc(GetStateSetSize()));
620 state0_.template Reserve<SizeType>(regex_.stateCount_);
621 state1_.template Reserve<SizeType>(regex_.stateCount_);
622 }
623
625 Allocator::Free(stateSet_);
626 RAPIDJSON_DELETE(ownAllocator_);
627 }
628
629 template <typename InputStream>
630 bool Match(InputStream& is) {
631 return SearchWithAnchoring(is, true, true);
632 }
633
634 bool Match(const Ch* s) {
636 return Match(is);
637 }
638
639 template <typename InputStream>
640 bool Search(InputStream& is) {
641 return SearchWithAnchoring(is, regex_.anchorBegin_, regex_.anchorEnd_);
642 }
643
644 bool Search(const Ch* s) {
646 return Search(is);
647 }
648
649private:
650 typedef typename RegexType::State State;
651 typedef typename RegexType::Range Range;
652
653 template <typename InputStream>
654 bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) {
656
657 state0_.Clear();
658 Stack<Allocator> *current = &state0_, *next = &state1_;
659 const size_t stateSetSize = GetStateSetSize();
660 std::memset(stateSet_, 0, stateSetSize);
661
662 bool matched = AddState(*current, regex_.root_);
663 unsigned codepoint;
664 while (!current->Empty() && (codepoint = ds.Take()) != 0) {
665 std::memset(stateSet_, 0, stateSetSize);
666 next->Clear();
667 matched = false;
668 for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
669 const State& sr = regex_.GetState(*s);
670 if (sr.codepoint == codepoint ||
671 sr.codepoint == RegexType::kAnyCharacterClass ||
672 (sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
673 {
674 matched = AddState(*next, sr.out) || matched;
675 if (!anchorEnd && matched)
676 return true;
677 }
678 if (!anchorBegin)
679 AddState(*next, regex_.root_);
680 }
681 internal::Swap(current, next);
682 }
683
684 return matched;
685 }
686
687 size_t GetStateSetSize() const {
688 return (regex_.stateCount_ + 31) / 32 * 4;
689 }
690
691 // Return whether the added states is a match state
692 bool AddState(Stack<Allocator>& l, SizeType index) {
693 RAPIDJSON_ASSERT(index != kRegexInvalidState);
694
695 const State& s = regex_.GetState(index);
696 if (s.out1 != kRegexInvalidState) { // Split
697 bool matched = AddState(l, s.out);
698 return AddState(l, s.out1) || matched;
699 }
700 else if (!(stateSet_[index >> 5] & (1u << (index & 31)))) {
701 stateSet_[index >> 5] |= (1u << (index & 31));
702 *l.template PushUnsafe<SizeType>() = index;
703 }
704 return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
705 }
706
707 bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
708 bool yes = (regex_.GetRange(rangeIndex).start & RegexType::kRangeNegationFlag) == 0;
709 while (rangeIndex != kRegexInvalidRange) {
710 const Range& r = regex_.GetRange(rangeIndex);
711 if (codepoint >= (r.start & ~RegexType::kRangeNegationFlag) && codepoint <= r.end)
712 return yes;
713 rangeIndex = r.next;
714 }
715 return !yes;
716 }
717
718 const RegexType& regex_;
719 Allocator* allocator_;
720 Allocator* ownAllocator_;
721 Stack<Allocator> state0_;
722 Stack<Allocator> state1_;
723 uint32_t* stateSet_;
724};
725
726typedef GenericRegex<UTF8<> > Regex;
728
729} // namespace internal
731
732#ifdef __GNUC__
733RAPIDJSON_DIAG_POP
734#endif
735
736#if defined(__clang__) || defined(_MSC_VER)
737RAPIDJSON_DIAG_POP
738#endif
739
740#endif // RAPIDJSON_INTERNAL_REGEX_H_
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Regular expression engine with subset of ECMAscript grammar.
Definition regex.h:111
static const unsigned kAnyCharacterClass
For '.'.
Definition regex.h:146
A type-unsafe stack for storing different types of data.
Definition stack.h:38
Concept for allocating, resizing and freeing memory block.
Concept for encoding of Unicode characters.
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition rapidjson.h:407
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition rapidjson.h:122
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition rapidjson.h:125
#define RAPIDJSON_DELETE(x)
! customization point for global delete
Definition rapidjson.h:652
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition rapidjson.h:385
#define RAPIDJSON_NEW(TypeName)
! customization point for global new
Definition rapidjson.h:648
Read-only string stream.
Definition stream.h:155
SizeType out
link-list of all output states
Definition regex.h:166
SizeType out1
Equals to non-kInvalid for split.
Definition regex.h:158
SizeType out
Equals to kInvalid for matching state.
Definition regex.h:157