bloaty/third_party/re2/re2/nfa.cc
Go to the documentation of this file.
1 // Copyright 2006-2007 The RE2 Authors. All Rights Reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 
5 // Tested by search_test.cc.
6 //
7 // Prog::SearchNFA, an NFA search.
8 // This is an actual NFA like the theorists talk about,
9 // not the pseudo-NFA found in backtracking regexp implementations.
10 //
11 // IMPLEMENTATION
12 //
13 // This algorithm is a variant of one that appeared in Rob Pike's sam editor,
14 // which is a variant of the one described in Thompson's 1968 CACM paper.
15 // See http://swtch.com/~rsc/regexp/ for various history. The main feature
16 // over the DFA implementation is that it tracks submatch boundaries.
17 //
18 // When the choice of submatch boundaries is ambiguous, this particular
19 // implementation makes the same choices that traditional backtracking
20 // implementations (in particular, Perl and PCRE) do.
21 // Note that unlike in Perl and PCRE, this algorithm *cannot* take exponential
22 // time in the length of the input.
23 //
24 // Like Thompson's original machine and like the DFA implementation, this
25 // implementation notices a match only once it is one byte past it.
26 
27 #include <stdio.h>
28 #include <string.h>
29 #include <algorithm>
30 #include <string>
31 #include <utility>
32 #include <vector>
33 
34 #include "re2/prog.h"
35 #include "re2/regexp.h"
36 #include "util/logging.h"
37 #include "util/pod_array.h"
38 #include "util/sparse_array.h"
39 #include "util/sparse_set.h"
40 #include "util/strutil.h"
41 
42 namespace re2 {
43 
44 static const bool ExtraDebug = false;
45 
46 class NFA {
47  public:
48  NFA(Prog* prog);
49  ~NFA();
50 
51  // Searches for a matching string.
52  // * If anchored is true, only considers matches starting at offset.
53  // Otherwise finds lefmost match at or after offset.
54  // * If longest is true, returns the longest match starting
55  // at the chosen start point. Otherwise returns the so-called
56  // left-biased match, the one traditional backtracking engines
57  // (like Perl and PCRE) find.
58  // Records submatch boundaries in submatch[1..nsubmatch-1].
59  // Submatch[0] is the entire match. When there is a choice in
60  // which text matches each subexpression, the submatch boundaries
61  // are chosen to match what a backtracking implementation would choose.
62  bool Search(const StringPiece& text, const StringPiece& context,
63  bool anchored, bool longest,
64  StringPiece* submatch, int nsubmatch);
65 
66  private:
67  struct Thread {
68  union {
69  int ref;
70  Thread* next; // when on free list
71  };
72  const char** capture;
73  };
74 
75  // State for explicit stack in AddToThreadq.
76  struct AddState {
77  int id; // Inst to process
78  Thread* t; // if not null, set t0 = t before processing id
79  };
80 
81  // Threadq is a list of threads. The list is sorted by the order
82  // in which Perl would explore that particular state -- the earlier
83  // choices appear earlier in the list.
85 
86  inline Thread* AllocThread();
87  inline Thread* Incref(Thread* t);
88  inline void Decref(Thread* t);
89 
90  // Follows all empty arrows from id0 and enqueues all the states reached.
91  // Enqueues only the ByteRange instructions that match byte c.
92  // context is used (with p) for evaluating empty-width specials.
93  // p is the current input position, and t0 is the current thread.
94  void AddToThreadq(Threadq* q, int id0, int c, const StringPiece& context,
95  const char* p, Thread* t0);
96 
97  // Run runq on byte c, appending new states to nextq.
98  // Updates matched_ and match_ as new, better matches are found.
99  // context is used (with p) for evaluating empty-width specials.
100  // p is the position of byte c in the input string for AddToThreadq;
101  // p-1 will be used when processing Match instructions.
102  // Frees all the threads on runq.
103  // If there is a shortcut to the end, returns that shortcut.
104  int Step(Threadq* runq, Threadq* nextq, int c, const StringPiece& context,
105  const char* p);
106 
107  // Returns text version of capture information, for debugging.
108  std::string FormatCapture(const char** capture);
109 
110  inline void CopyCapture(const char** dst, const char** src);
111 
112  Prog* prog_; // underlying program
113  int start_; // start instruction in program
114  int ncapture_; // number of submatches to track
115  bool longest_; // whether searching for longest match
116  bool endmatch_; // whether match must end at text.end()
117  const char* btext_; // beginning of text being matched (for FormatSubmatch)
118  const char* etext_; // end of text being matched (for endmatch_)
119  Threadq q0_, q1_; // pre-allocated for Search.
120  PODArray<AddState> stack_; // pre-allocated for AddToThreadq
121  Thread* free_threads_; // free list
122  const char** match_; // best match so far
123  bool matched_; // any match so far?
124 
125  NFA(const NFA&) = delete;
126  NFA& operator=(const NFA&) = delete;
127 };
128 
130  prog_ = prog;
131  start_ = prog_->start();
132  ncapture_ = 0;
133  longest_ = false;
134  endmatch_ = false;
135  btext_ = NULL;
136  etext_ = NULL;
137  q0_.resize(prog_->size());
138  q1_.resize(prog_->size());
139  // See NFA::AddToThreadq() for why this is so.
140  int nstack = 2*prog_->inst_count(kInstCapture) +
142  prog_->inst_count(kInstNop) + 1; // + 1 for start inst
144  free_threads_ = NULL;
145  match_ = NULL;
146  matched_ = false;
147 }
148 
150  delete[] match_;
151  Thread* next;
152  for (Thread* t = free_threads_; t; t = next) {
153  next = t->next;
154  delete[] t->capture;
155  delete t;
156  }
157 }
158 
160  Thread* t = free_threads_;
161  if (t == NULL) {
162  t = new Thread;
163  t->ref = 1;
164  t->capture = new const char*[ncapture_];
165  return t;
166  }
167  free_threads_ = t->next;
168  t->ref = 1;
169  return t;
170 }
171 
173  DCHECK(t != NULL);
174  t->ref++;
175  return t;
176 }
177 
178 void NFA::Decref(Thread* t) {
179  if (t == NULL)
180  return;
181  t->ref--;
182  if (t->ref > 0)
183  return;
184  DCHECK_EQ(t->ref, 0);
185  t->next = free_threads_;
186  free_threads_ = t;
187 }
188 
189 void NFA::CopyCapture(const char** dst, const char** src) {
190  for (int i = 0; i < ncapture_; i+=2) {
191  dst[i] = src[i];
192  dst[i+1] = src[i+1];
193  }
194 }
195 
196 // Follows all empty arrows from id0 and enqueues all the states reached.
197 // Enqueues only the ByteRange instructions that match byte c.
198 // context is used (with p) for evaluating empty-width specials.
199 // p is the current input position, and t0 is the current thread.
200 void NFA::AddToThreadq(Threadq* q, int id0, int c, const StringPiece& context,
201  const char* p, Thread* t0) {
202  if (id0 == 0)
203  return;
204 
205  // Use stack_ to hold our stack of instructions yet to process.
206  // It was preallocated as follows:
207  // two entries per Capture;
208  // one entry per EmptyWidth; and
209  // one entry per Nop.
210  // This reflects the maximum number of stack pushes that each can
211  // perform. (Each instruction can be processed at most once.)
212  AddState* stk = stack_.data();
213  int nstk = 0;
214 
215  stk[nstk++] = {id0, NULL};
216  while (nstk > 0) {
217  DCHECK_LE(nstk, stack_.size());
218  AddState a = stk[--nstk];
219 
220  Loop:
221  if (a.t != NULL) {
222  // t0 was a thread that we allocated and copied in order to
223  // record the capture, so we must now decref it.
224  Decref(t0);
225  t0 = a.t;
226  }
227 
228  int id = a.id;
229  if (id == 0)
230  continue;
231  if (q->has_index(id)) {
232  if (ExtraDebug)
233  fprintf(stderr, " [%d%s]\n", id, FormatCapture(t0->capture).c_str());
234  continue;
235  }
236 
237  // Create entry in q no matter what. We might fill it in below,
238  // or we might not. Even if not, it is necessary to have it,
239  // so that we don't revisit id0 during the recursion.
240  q->set_new(id, NULL);
241  Thread** tp = &q->get_existing(id);
242  int j;
243  Thread* t;
244  Prog::Inst* ip = prog_->inst(id);
245  switch (ip->opcode()) {
246  default:
247  LOG(DFATAL) << "unhandled " << ip->opcode() << " in AddToThreadq";
248  break;
249 
250  case kInstFail:
251  break;
252 
253  case kInstAltMatch:
254  // Save state; will pick up at next byte.
255  t = Incref(t0);
256  *tp = t;
257 
258  DCHECK(!ip->last());
259  a = {id+1, NULL};
260  goto Loop;
261 
262  case kInstNop:
263  if (!ip->last())
264  stk[nstk++] = {id+1, NULL};
265 
266  // Continue on.
267  a = {ip->out(), NULL};
268  goto Loop;
269 
270  case kInstCapture:
271  if (!ip->last())
272  stk[nstk++] = {id+1, NULL};
273 
274  if ((j=ip->cap()) < ncapture_) {
275  // Push a dummy whose only job is to restore t0
276  // once we finish exploring this possibility.
277  stk[nstk++] = {0, t0};
278 
279  // Record capture.
280  t = AllocThread();
281  CopyCapture(t->capture, t0->capture);
282  t->capture[j] = p;
283  t0 = t;
284  }
285  a = {ip->out(), NULL};
286  goto Loop;
287 
288  case kInstByteRange:
289  if (!ip->Matches(c))
290  goto Next;
291 
292  // Save state; will pick up at next byte.
293  t = Incref(t0);
294  *tp = t;
295  if (ExtraDebug)
296  fprintf(stderr, " + %d%s\n", id, FormatCapture(t0->capture).c_str());
297 
298  if (ip->hint() == 0)
299  break;
300  a = {id+ip->hint(), NULL};
301  goto Loop;
302 
303  case kInstMatch:
304  // Save state; will pick up at next byte.
305  t = Incref(t0);
306  *tp = t;
307  if (ExtraDebug)
308  fprintf(stderr, " ! %d%s\n", id, FormatCapture(t0->capture).c_str());
309 
310  Next:
311  if (ip->last())
312  break;
313  a = {id+1, NULL};
314  goto Loop;
315 
316  case kInstEmptyWidth:
317  if (!ip->last())
318  stk[nstk++] = {id+1, NULL};
319 
320  // Continue on if we have all the right flag bits.
321  if (ip->empty() & ~Prog::EmptyFlags(context, p))
322  break;
323  a = {ip->out(), NULL};
324  goto Loop;
325  }
326  }
327 }
328 
329 // Run runq on byte c, appending new states to nextq.
330 // Updates matched_ and match_ as new, better matches are found.
331 // context is used (with p) for evaluating empty-width specials.
332 // p is the position of byte c in the input string for AddToThreadq;
333 // p-1 will be used when processing Match instructions.
334 // Frees all the threads on runq.
335 // If there is a shortcut to the end, returns that shortcut.
336 int NFA::Step(Threadq* runq, Threadq* nextq, int c, const StringPiece& context,
337  const char* p) {
338  nextq->clear();
339 
340  for (Threadq::iterator i = runq->begin(); i != runq->end(); ++i) {
341  Thread* t = i->value();
342  if (t == NULL)
343  continue;
344 
345  if (longest_) {
346  // Can skip any threads started after our current best match.
347  if (matched_ && match_[0] < t->capture[0]) {
348  Decref(t);
349  continue;
350  }
351  }
352 
353  int id = i->index();
354  Prog::Inst* ip = prog_->inst(id);
355 
356  switch (ip->opcode()) {
357  default:
358  // Should only see the values handled below.
359  LOG(DFATAL) << "Unhandled " << ip->opcode() << " in step";
360  break;
361 
362  case kInstByteRange:
363  AddToThreadq(nextq, ip->out(), c, context, p, t);
364  break;
365 
366  case kInstAltMatch:
367  if (i != runq->begin())
368  break;
369  // The match is ours if we want it.
370  if (ip->greedy(prog_) || longest_) {
371  CopyCapture(match_, t->capture);
372  matched_ = true;
373 
374  Decref(t);
375  for (++i; i != runq->end(); ++i)
376  Decref(i->value());
377  runq->clear();
378  if (ip->greedy(prog_))
379  return ip->out1();
380  return ip->out();
381  }
382  break;
383 
384  case kInstMatch: {
385  // Avoid invoking undefined behavior when p happens
386  // to be null - and p-1 would be meaningless anyway.
387  if (p == NULL)
388  break;
389 
390  if (endmatch_ && p-1 != etext_)
391  break;
392 
393  if (longest_) {
394  // Leftmost-longest mode: save this match only if
395  // it is either farther to the left or at the same
396  // point but longer than an existing match.
397  if (!matched_ || t->capture[0] < match_[0] ||
398  (t->capture[0] == match_[0] && p-1 > match_[1])) {
399  CopyCapture(match_, t->capture);
400  match_[1] = p-1;
401  matched_ = true;
402  }
403  } else {
404  // Leftmost-biased mode: this match is by definition
405  // better than what we've already found (see next line).
406  CopyCapture(match_, t->capture);
407  match_[1] = p-1;
408  matched_ = true;
409 
410  // Cut off the threads that can only find matches
411  // worse than the one we just found: don't run the
412  // rest of the current Threadq.
413  Decref(t);
414  for (++i; i != runq->end(); ++i)
415  Decref(i->value());
416  runq->clear();
417  return 0;
418  }
419  break;
420  }
421  }
422  Decref(t);
423  }
424  runq->clear();
425  return 0;
426 }
427 
428 std::string NFA::FormatCapture(const char** capture) {
429  std::string s;
430  for (int i = 0; i < ncapture_; i+=2) {
431  if (capture[i] == NULL)
432  s += "(?,?)";
433  else if (capture[i+1] == NULL)
434  s += StringPrintf("(%d,?)",
435  (int)(capture[i] - btext_));
436  else
437  s += StringPrintf("(%d,%d)",
438  (int)(capture[i] - btext_),
439  (int)(capture[i+1] - btext_));
440  }
441  return s;
442 }
443 
444 bool NFA::Search(const StringPiece& text, const StringPiece& const_context,
445  bool anchored, bool longest,
446  StringPiece* submatch, int nsubmatch) {
447  if (start_ == 0)
448  return false;
449 
450  StringPiece context = const_context;
451  if (context.data() == NULL)
452  context = text;
453 
454  // Sanity check: make sure that text lies within context.
455  if (text.begin() < context.begin() || text.end() > context.end()) {
456  LOG(DFATAL) << "context does not contain text";
457  return false;
458  }
459 
460  if (prog_->anchor_start() && context.begin() != text.begin())
461  return false;
462  if (prog_->anchor_end() && context.end() != text.end())
463  return false;
464  anchored |= prog_->anchor_start();
465  if (prog_->anchor_end()) {
466  longest = true;
467  endmatch_ = true;
468  }
469 
470  if (nsubmatch < 0) {
471  LOG(DFATAL) << "Bad args: nsubmatch=" << nsubmatch;
472  return false;
473  }
474 
475  // Save search parameters.
476  ncapture_ = 2*nsubmatch;
477  longest_ = longest;
478 
479  if (nsubmatch == 0) {
480  // We need to maintain match[0], both to distinguish the
481  // longest match (if longest is true) and also to tell
482  // whether we've seen any matches at all.
483  ncapture_ = 2;
484  }
485 
486  match_ = new const char*[ncapture_];
487  matched_ = false;
488 
489  // For debugging prints.
490  btext_ = context.data();
491  // For convenience.
492  etext_ = text.data() + text.size();
493 
494  if (ExtraDebug)
495  fprintf(stderr, "NFA::Search %s (context: %s) anchored=%d longest=%d\n",
496  std::string(text).c_str(), std::string(context).c_str(), anchored,
497  longest);
498 
499  // Set up search.
500  Threadq* runq = &q0_;
501  Threadq* nextq = &q1_;
502  runq->clear();
503  nextq->clear();
504  memset(&match_[0], 0, ncapture_*sizeof match_[0]);
505 
506  // Loop over the text, stepping the machine.
507  for (const char* p = text.data();; p++) {
508  if (ExtraDebug) {
509  int c = 0;
510  if (p == btext_)
511  c = '^';
512  else if (p > etext_)
513  c = '$';
514  else if (p < etext_)
515  c = p[0] & 0xFF;
516 
517  fprintf(stderr, "%c:", c);
518  for (Threadq::iterator i = runq->begin(); i != runq->end(); ++i) {
519  Thread* t = i->value();
520  if (t == NULL)
521  continue;
522  fprintf(stderr, " %d%s", i->index(), FormatCapture(t->capture).c_str());
523  }
524  fprintf(stderr, "\n");
525  }
526 
527  // This is a no-op the first time around the loop because runq is empty.
528  int id = Step(runq, nextq, p < etext_ ? p[0] & 0xFF : -1, context, p);
529  DCHECK_EQ(runq->size(), 0);
530  using std::swap;
531  swap(nextq, runq);
532  nextq->clear();
533  if (id != 0) {
534  // We're done: full match ahead.
535  p = etext_;
536  for (;;) {
537  Prog::Inst* ip = prog_->inst(id);
538  switch (ip->opcode()) {
539  default:
540  LOG(DFATAL) << "Unexpected opcode in short circuit: " << ip->opcode();
541  break;
542 
543  case kInstCapture:
544  if (ip->cap() < ncapture_)
545  match_[ip->cap()] = p;
546  id = ip->out();
547  continue;
548 
549  case kInstNop:
550  id = ip->out();
551  continue;
552 
553  case kInstMatch:
554  match_[1] = p;
555  matched_ = true;
556  break;
557  }
558  break;
559  }
560  break;
561  }
562 
563  if (p > etext_)
564  break;
565 
566  // Start a new thread if there have not been any matches.
567  // (No point in starting a new thread if there have been
568  // matches, since it would be to the right of the match
569  // we already found.)
570  if (!matched_ && (!anchored || p == text.data())) {
571  // If there's a required first byte for an unanchored search
572  // and we're not in the middle of any possible matches,
573  // use memchr to search for the byte quickly.
574  int fb = prog_->first_byte();
575  if (!anchored && runq->size() == 0 &&
576  fb >= 0 && p < etext_ && (p[0] & 0xFF) != fb) {
577  p = reinterpret_cast<const char*>(memchr(p, fb, etext_ - p));
578  if (p == NULL) {
579  p = etext_;
580  }
581  }
582 
583  Thread* t = AllocThread();
584  CopyCapture(t->capture, match_);
585  t->capture[0] = p;
586  AddToThreadq(runq, start_, p < etext_ ? p[0] & 0xFF : -1, context, p,
587  t);
588  Decref(t);
589  }
590 
591  // If all the threads have died, stop early.
592  if (runq->size() == 0) {
593  if (ExtraDebug)
594  fprintf(stderr, "dead\n");
595  break;
596  }
597  }
598 
599  for (Threadq::iterator i = runq->begin(); i != runq->end(); ++i)
600  Decref(i->value());
601 
602  if (matched_) {
603  for (int i = 0; i < nsubmatch; i++)
604  submatch[i] =
605  StringPiece(match_[2 * i],
606  static_cast<size_t>(match_[2 * i + 1] - match_[2 * i]));
607  if (ExtraDebug)
608  fprintf(stderr, "match (%td,%td)\n",
609  match_[0] - btext_, match_[1] - btext_);
610  return true;
611  }
612  return false;
613 }
614 
615 // Computes whether all successful matches have a common first byte,
616 // and if so, returns that byte. If not, returns -1.
618  int b = -1;
619  SparseSet q(size());
620  q.insert(start());
621  for (SparseSet::iterator it = q.begin(); it != q.end(); ++it) {
622  int id = *it;
623  Prog::Inst* ip = inst(id);
624  switch (ip->opcode()) {
625  default:
626  LOG(DFATAL) << "unhandled " << ip->opcode() << " in ComputeFirstByte";
627  break;
628 
629  case kInstMatch:
630  // The empty string matches: no first byte.
631  return -1;
632 
633  case kInstByteRange:
634  if (!ip->last())
635  q.insert(id+1);
636 
637  // Must match only a single byte
638  if (ip->lo() != ip->hi())
639  return -1;
640  if (ip->foldcase() && 'a' <= ip->lo() && ip->lo() <= 'z')
641  return -1;
642  // If we haven't seen any bytes yet, record it;
643  // otherwise must match the one we saw before.
644  if (b == -1)
645  b = ip->lo();
646  else if (b != ip->lo())
647  return -1;
648  break;
649 
650  case kInstNop:
651  case kInstCapture:
652  case kInstEmptyWidth:
653  if (!ip->last())
654  q.insert(id+1);
655 
656  // Continue on.
657  // Ignore ip->empty() flags for kInstEmptyWidth
658  // in order to be as conservative as possible
659  // (assume all possible empty-width flags are true).
660  if (ip->out())
661  q.insert(ip->out());
662  break;
663 
664  case kInstAltMatch:
665  DCHECK(!ip->last());
666  q.insert(id+1);
667  break;
668 
669  case kInstFail:
670  break;
671  }
672  }
673  return b;
674 }
675 
676 bool
678  Anchor anchor, MatchKind kind,
679  StringPiece* match, int nmatch) {
680  if (ExtraDebug)
681  Dump();
682 
683  NFA nfa(this);
684  StringPiece sp;
685  if (kind == kFullMatch) {
686  anchor = kAnchored;
687  if (nmatch == 0) {
688  match = &sp;
689  nmatch = 1;
690  }
691  }
692  if (!nfa.Search(text, context, anchor == kAnchored, kind != kFirstMatch, match, nmatch))
693  return false;
694  if (kind == kFullMatch && match[0].end() != text.end())
695  return false;
696  return true;
697 }
698 
699 // For each instruction i in the program reachable from the start, compute the
700 // number of instructions reachable from i by following only empty transitions
701 // and record that count as fanout[i].
702 //
703 // fanout holds the results and is also the work queue for the outer iteration.
704 // reachable holds the reached nodes for the inner iteration.
706  DCHECK_EQ(fanout->max_size(), size());
707  SparseSet reachable(size());
708  fanout->clear();
709  fanout->set_new(start(), 0);
710  for (SparseArray<int>::iterator i = fanout->begin(); i != fanout->end(); ++i) {
711  int* count = &i->value();
712  reachable.clear();
713  reachable.insert(i->index());
714  for (SparseSet::iterator j = reachable.begin(); j != reachable.end(); ++j) {
715  int id = *j;
716  Prog::Inst* ip = inst(id);
717  switch (ip->opcode()) {
718  default:
719  LOG(DFATAL) << "unhandled " << ip->opcode() << " in Prog::Fanout()";
720  break;
721 
722  case kInstByteRange:
723  if (!ip->last())
724  reachable.insert(id+1);
725 
726  (*count)++;
727  if (!fanout->has_index(ip->out())) {
728  fanout->set_new(ip->out(), 0);
729  }
730  break;
731 
732  case kInstAltMatch:
733  DCHECK(!ip->last());
734  reachable.insert(id+1);
735  break;
736 
737  case kInstCapture:
738  case kInstEmptyWidth:
739  case kInstNop:
740  if (!ip->last())
741  reachable.insert(id+1);
742 
743  reachable.insert(ip->out());
744  break;
745 
746  case kInstMatch:
747  if (!ip->last())
748  reachable.insert(id+1);
749  break;
750 
751  case kInstFail:
752  break;
753  }
754  }
755  }
756 }
757 
758 } // namespace re2
re2::Prog::Inst::Matches
bool Matches(int c)
Definition: bloaty/third_party/re2/re2/prog.h:102
re2::Prog::Inst::greedy
bool greedy(Prog *p)
Definition: bloaty/third_party/re2/re2/prog.h:94
re2::NFA::operator=
NFA & operator=(const NFA &)=delete
re2::kInstFail
@ kInstFail
Definition: bloaty/third_party/re2/re2/prog.h:37
dst
static const char dst[]
Definition: test-fs-copyfile.c:37
re2::NFA::stack_
PODArray< AddState > stack_
Definition: bloaty/third_party/re2/re2/nfa.cc:120
re2::Prog::Inst::hi
int hi()
Definition: bloaty/third_party/re2/re2/prog.h:88
regen-readme.it
it
Definition: regen-readme.py:15
prog
char * prog
Definition: bloaty/third_party/zlib/contrib/untgz/untgz.c:125
re2::Prog::ComputeFirstByte
int ComputeFirstByte()
Definition: bloaty/third_party/re2/re2/nfa.cc:617
re2::NFA::CopyCapture
void CopyCapture(const char **dst, const char **src)
Definition: bloaty/third_party/re2/re2/nfa.cc:189
re2::NFA::NFA
NFA(Prog *prog)
Definition: bloaty/third_party/re2/re2/nfa.cc:129
re2::Prog::Inst::out1
int out1()
Definition: bloaty/third_party/re2/re2/prog.h:85
pod_array.h
memset
return memset(p, 0, total)
re2::Prog::kFullMatch
@ kFullMatch
Definition: bloaty/third_party/re2/re2/prog.h:195
DCHECK_LE
#define DCHECK_LE(val1, val2)
Definition: bloaty/third_party/re2/util/logging.h:22
re2::NFA::longest_
bool longest_
Definition: bloaty/third_party/re2/re2/nfa.cc:115
re2::NFA::AddState::id
int id
Definition: bloaty/third_party/re2/re2/nfa.cc:77
re2::NFA::Thread
Definition: bloaty/third_party/re2/re2/nfa.cc:67
re2::Prog::Inst
Definition: bloaty/third_party/re2/re2/prog.h:62
re2::Prog::Anchor
Anchor
Definition: bloaty/third_party/re2/re2/prog.h:175
re2::SparseArray::max_size
int max_size() const
Definition: bloaty/third_party/re2/util/sparse_array.h:159
match
unsigned char match[65280+2]
Definition: bloaty/third_party/zlib/examples/gun.c:165
string.h
re2::NFA::match_
const char ** match_
Definition: bloaty/third_party/re2/re2/nfa.cc:122
re2::SparseArray::clear
void clear()
Definition: bloaty/third_party/re2/util/sparse_array.h:167
re2::SparseArray::IndexValue
Definition: bloaty/third_party/re2/util/sparse_array.h:310
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
re2::NFA::AddState
Definition: bloaty/third_party/re2/re2/nfa.cc:76
re2::Prog::Inst::empty
EmptyOp empty()
Definition: bloaty/third_party/re2/re2/prog.h:92
re2::SparseArray::resize
void resize(int new_max_size)
Definition: bloaty/third_party/re2/util/sparse_array.h:325
re2
Definition: bloaty/third_party/re2/re2/bitmap256.h:17
re2::SparseArray< Thread * >::iterator
IndexValue * iterator
Definition: bloaty/third_party/re2/util/sparse_array.h:117
re2::NFA::FormatCapture
std::string FormatCapture(const char **capture)
Definition: bloaty/third_party/re2/re2/nfa.cc:428
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
re2::SparseArray::end
iterator end()
Definition: bloaty/third_party/re2/util/sparse_array.h:142
re2::NFA::q0_
Threadq q0_
Definition: bloaty/third_party/re2/re2/nfa.cc:119
re2::NFA::etext_
const char * etext_
Definition: bloaty/third_party/re2/re2/nfa.cc:118
re2::Prog::Inst::cap
int cap()
Definition: bloaty/third_party/re2/re2/prog.h:86
re2::NFA::Decref
void Decref(Thread *t)
Definition: bloaty/third_party/re2/re2/nfa.cc:178
absl::base_internal::Next
static AllocList * Next(int i, AllocList *prev, LowLevelAlloc::Arena *arena)
Definition: abseil-cpp/absl/base/internal/low_level_alloc.cc:453
re2::kInstEmptyWidth
@ kInstEmptyWidth
Definition: bloaty/third_party/re2/re2/prog.h:34
re2::Prog::inst_count
int inst_count(InstOp op)
Definition: bloaty/third_party/re2/re2/prog.h:208
sparse_set.h
python_utils.port_server.stderr
stderr
Definition: port_server.py:51
re2::Prog::MatchKind
MatchKind
Definition: bloaty/third_party/re2/re2/prog.h:192
sparse_array.h
re2::SparseSetT::clear
void clear()
Definition: bloaty/third_party/re2/util/sparse_set.h:117
re2::SparseSetT
Definition: bloaty/third_party/re2/util/sparse_set.h:69
re2::kInstCapture
@ kInstCapture
Definition: bloaty/third_party/re2/re2/prog.h:33
gen_server_registered_method_bad_client_test_body.text
def text
Definition: gen_server_registered_method_bad_client_test_body.py:50
re2::NFA::matched_
bool matched_
Definition: bloaty/third_party/re2/re2/nfa.cc:123
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
swap
#define swap(a, b)
Definition: qsort.h:111
gen_stats_data.c_str
def c_str(s, encoding='ascii')
Definition: gen_stats_data.py:38
t0
static int64_t t0
Definition: bloaty/third_party/re2/util/benchmark.cc:44
re2::Prog::anchor_end
bool anchor_end()
Definition: bloaty/third_party/re2/re2/prog.h:216
LOG
#define LOG(severity)
Definition: bloaty/third_party/re2/util/logging.h:53
re2::SparseArray< Thread * >
re2::NFA::Step
int Step(Threadq *runq, Threadq *nextq, int c, const StringPiece &context, const char *p)
Definition: bloaty/third_party/re2/re2/nfa.cc:336
re2::NFA::q1_
Threadq q1_
Definition: bloaty/third_party/re2/re2/nfa.cc:119
re2::NFA::AddState::t
Thread * t
Definition: bloaty/third_party/re2/re2/nfa.cc:78
nstack
int nstack
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:287
re2::StringPrintf
std::string StringPrintf(const char *format,...)
Definition: bloaty/third_party/re2/util/strutil.cc:140
re2::Prog::inst
Inst * inst(int id)
Definition: bloaty/third_party/re2/re2/prog.h:199
re2::NFA::Incref
Thread * Incref(Thread *t)
Definition: bloaty/third_party/re2/re2/nfa.cc:172
re2::Prog::kAnchored
@ kAnchored
Definition: bloaty/third_party/re2/re2/prog.h:177
std::swap
void swap(Json::Value &a, Json::Value &b)
Specialize std::swap() for Json::Value.
Definition: third_party/bloaty/third_party/protobuf/conformance/third_party/jsoncpp/json.h:1226
re2::NFA::ncapture_
int ncapture_
Definition: bloaty/third_party/re2/re2/nfa.cc:114
re2::Prog::Inst::last
int last()
Definition: bloaty/third_party/re2/re2/prog.h:83
re2::Prog::size
int size()
Definition: bloaty/third_party/re2/re2/prog.h:204
re2::NFA::~NFA
~NFA()
Definition: bloaty/third_party/re2/re2/nfa.cc:149
re2::NFA::AddToThreadq
void AddToThreadq(Threadq *q, int id0, int c, const StringPiece &context, const char *p, Thread *t0)
Definition: bloaty/third_party/re2/re2/nfa.cc:200
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
re2::SparseArray::set_new
iterator set_new(int i, const Value &v)
Definition: bloaty/third_party/re2/util/sparse_array.h:188
re2::NFA::endmatch_
bool endmatch_
Definition: bloaty/third_party/re2/re2/nfa.cc:116
re2::Prog::Inst::opcode
InstOp opcode()
Definition: bloaty/third_party/re2/re2/prog.h:82
re2::SparseArray::size
int size() const
Definition: bloaty/third_party/re2/util/sparse_array.h:129
grpc_core::Loop
promise_detail::Loop< F > Loop(F f)
Definition: loop.h:130
re2::NFA
Definition: bloaty/third_party/re2/re2/nfa.cc:46
re2::SparseSetT::begin
iterator begin()
Definition: bloaty/third_party/re2/util/sparse_set.h:89
re2::NFA::Thread::next
Thread * next
Definition: bloaty/third_party/re2/re2/nfa.cc:70
re2::Prog::Fanout
void Fanout(SparseArray< int > *fanout)
Definition: bloaty/third_party/re2/re2/nfa.cc:705
re2::NFA::Search
bool Search(const StringPiece &text, const StringPiece &context, bool anchored, bool longest, StringPiece *submatch, int nsubmatch)
Definition: bloaty/third_party/re2/re2/nfa.cc:444
re2::Prog::Inst::foldcase
int foldcase()
Definition: bloaty/third_party/re2/re2/prog.h:89
re2::kInstNop
@ kInstNop
Definition: bloaty/third_party/re2/re2/prog.h:36
re2::NFA::btext_
const char * btext_
Definition: bloaty/third_party/re2/re2/nfa.cc:117
re2::kInstMatch
@ kInstMatch
Definition: bloaty/third_party/re2/re2/prog.h:35
re2::kInstAltMatch
@ kInstAltMatch
Definition: bloaty/third_party/re2/re2/prog.h:31
count
int * count
Definition: bloaty/third_party/googletest/googlemock/test/gmock_stress_test.cc:96
re2::Prog::first_byte
int first_byte()
Definition: bloaty/third_party/re2/re2/prog.cc:188
re2::Prog
Definition: bloaty/third_party/re2/re2/prog.h:56
re2::SparseArray::begin
iterator begin()
Definition: bloaty/third_party/re2/util/sparse_array.h:139
DCHECK_EQ
#define DCHECK_EQ(val1, val2)
Definition: bloaty/third_party/re2/util/logging.h:20
re2::SparseSetT::iterator
int * iterator
Definition: bloaty/third_party/re2/util/sparse_set.h:75
re2::NFA::Thread::capture
const char ** capture
Definition: bloaty/third_party/re2/re2/nfa.cc:72
re2::Prog::anchor_start
bool anchor_start()
Definition: bloaty/third_party/re2/re2/prog.h:214
next
AllocList * next[kMaxLevel]
Definition: abseil-cpp/absl/base/internal/low_level_alloc.cc:100
re2::Prog::Inst::out
int out()
Definition: bloaty/third_party/re2/re2/prog.h:84
re2::NFA::Threadq
SparseArray< Thread * > Threadq
Definition: bloaty/third_party/re2/re2/nfa.cc:84
re2::NFA::start_
int start_
Definition: bloaty/third_party/re2/re2/nfa.cc:113
re2::ExtraDebug
static const bool ExtraDebug
Definition: bloaty/third_party/re2/re2/dfa.cc:71
re2::SparseArray::has_index
bool has_index(int i) const
Definition: bloaty/third_party/re2/util/sparse_array.h:349
re2::NFA::AllocThread
Thread * AllocThread()
Definition: bloaty/third_party/re2/re2/nfa.cc:159
re2::Prog::kFirstMatch
@ kFirstMatch
Definition: bloaty/third_party/re2/re2/prog.h:193
re2::Prog::Inst::lo
int lo()
Definition: bloaty/third_party/re2/re2/prog.h:87
context
grpc::ClientContext context
Definition: istio_echo_server_lib.cc:61
DCHECK
#define DCHECK(condition)
Definition: bloaty/third_party/re2/util/logging.h:19
re2::Prog::Inst::hint
int hint()
Definition: bloaty/third_party/re2/re2/prog.h:90
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
re2::NFA::free_threads_
Thread * free_threads_
Definition: bloaty/third_party/re2/re2/nfa.cc:121
re2::NFA::Thread::ref
int ref
Definition: bloaty/third_party/re2/re2/nfa.cc:69
re2::StringPiece
Definition: bloaty/third_party/re2/re2/stringpiece.h:39
re2::SparseSetT::end
iterator end()
Definition: bloaty/third_party/re2/util/sparse_set.h:92
re2::PODArray
Definition: bloaty/third_party/re2/util/pod_array.h:14
re2::kInstByteRange
@ kInstByteRange
Definition: bloaty/third_party/re2/re2/prog.h:32
re2::Prog::EmptyFlags
static uint32_t EmptyFlags(const StringPiece &context, const char *p)
Definition: bloaty/third_party/re2/re2/prog.cc:287
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
re2::Prog::start
int start()
Definition: bloaty/third_party/re2/re2/prog.h:200
re2::Prog::Dump
std::string Dump()
Definition: bloaty/third_party/re2/re2/prog.cc:157
re2::SparseSetT::insert
iterator insert(int i)
Definition: bloaty/third_party/re2/util/sparse_set.h:132
re2::Prog::SearchNFA
bool SearchNFA(const StringPiece &text, const StringPiece &context, Anchor anchor, MatchKind kind, StringPiece *match, int nmatch)
Definition: bloaty/third_party/re2/re2/nfa.cc:677
re2::NFA::prog_
Prog * prog_
Definition: bloaty/third_party/re2/re2/nfa.cc:112


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:31