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


livox_ros_driver
Author(s): Livox Dev Team
autogenerated on Mon Mar 15 2021 02:40:46