/home/docs/checkouts/readthedocs.org/user_builds/advanced-micro-devices-composable-kernel/checkouts/develop/include/rapidjson/internal/regex.h Source File

/home/docs/checkouts/readthedocs.org/user_builds/advanced-micro-devices-composable-kernel/checkouts/develop/include/rapidjson/internal/regex.h Source File#

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