/src/duckdb/third_party/re2/re2/walker-inl.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2006 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 | | #ifndef RE2_WALKER_INL_H_ |
6 | | #define RE2_WALKER_INL_H_ |
7 | | |
8 | | // Helper class for traversing Regexps without recursion. |
9 | | // Clients should declare their own subclasses that override |
10 | | // the PreVisit and PostVisit methods, which are called before |
11 | | // and after visiting the subexpressions. |
12 | | |
13 | | // Not quite the Visitor pattern, because (among other things) |
14 | | // the Visitor pattern is recursive. |
15 | | |
16 | | #include <stack> |
17 | | |
18 | | #include "util/logging.h" |
19 | | #include "re2/regexp.h" |
20 | | |
21 | | namespace duckdb_re2 { |
22 | | |
23 | | template<typename T> struct WalkState; |
24 | | |
25 | | template<typename T> class Regexp::Walker { |
26 | | public: |
27 | | Walker(); |
28 | | virtual ~Walker(); |
29 | | |
30 | | // Virtual method called before visiting re's children. |
31 | | // PreVisit passes ownership of its return value to its caller. |
32 | | // The Arg* that PreVisit returns will be passed to PostVisit as pre_arg |
33 | | // and passed to the child PreVisits and PostVisits as parent_arg. |
34 | | // At the top-most Regexp, parent_arg is arg passed to walk. |
35 | | // If PreVisit sets *stop to true, the walk does not recurse |
36 | | // into the children. Instead it behaves as though the return |
37 | | // value from PreVisit is the return value from PostVisit. |
38 | | // The default PreVisit returns parent_arg. |
39 | | virtual T PreVisit(Regexp* re, T parent_arg, bool* stop); |
40 | | |
41 | | // Virtual method called after visiting re's children. |
42 | | // The pre_arg is the T that PreVisit returned. |
43 | | // The child_args is a vector of the T that the child PostVisits returned. |
44 | | // PostVisit takes ownership of pre_arg. |
45 | | // PostVisit takes ownership of the Ts |
46 | | // in *child_args, but not the vector itself. |
47 | | // PostVisit passes ownership of its return value |
48 | | // to its caller. |
49 | | // The default PostVisit simply returns pre_arg. |
50 | | virtual T PostVisit(Regexp* re, T parent_arg, T pre_arg, |
51 | | T* child_args, int nchild_args); |
52 | | |
53 | | // Virtual method called to copy a T, |
54 | | // when Walk notices that more than one child is the same re. |
55 | | virtual T Copy(T arg); |
56 | | |
57 | | // Virtual method called to do a "quick visit" of the re, |
58 | | // but not its children. Only called once the visit budget |
59 | | // has been used up and we're trying to abort the walk |
60 | | // as quickly as possible. Should return a value that |
61 | | // makes sense for the parent PostVisits still to be run. |
62 | | // This function is (hopefully) only called by |
63 | | // WalkExponential, but must be implemented by all clients, |
64 | | // just in case. |
65 | | virtual T ShortVisit(Regexp* re, T parent_arg) = 0; |
66 | | |
67 | | // Walks over a regular expression. |
68 | | // Top_arg is passed as parent_arg to PreVisit and PostVisit of re. |
69 | | // Returns the T returned by PostVisit on re. |
70 | | T Walk(Regexp* re, T top_arg); |
71 | | |
72 | | // Like Walk, but doesn't use Copy. This can lead to |
73 | | // exponential runtimes on cross-linked Regexps like the |
74 | | // ones generated by Simplify. To help limit this, |
75 | | // at most max_visits nodes will be visited and then |
76 | | // the walk will be cut off early. |
77 | | // If the walk *is* cut off early, ShortVisit(re) |
78 | | // will be called on regexps that cannot be fully |
79 | | // visited rather than calling PreVisit/PostVisit. |
80 | | T WalkExponential(Regexp* re, T top_arg, int max_visits); |
81 | | |
82 | | // Clears the stack. Should never be necessary, since |
83 | | // Walk always enters and exits with an empty stack. |
84 | | // Logs DFATAL if stack is not already clear. |
85 | | void Reset(); |
86 | | |
87 | | // Returns whether walk was cut off. |
88 | 7.43k | bool stopped_early() { return stopped_early_; } duckdb_re2::Regexp::Walker<duckdb_re2::Regexp*>::stopped_early() Line | Count | Source | 88 | 7.43k | bool stopped_early() { return stopped_early_; } |
Unexecuted instantiation: duckdb_re2::Regexp::Walker<int>::stopped_early() |
89 | | |
90 | | private: |
91 | | // Walk state for the entire traversal. |
92 | | std::stack<WalkState<T>> stack_; |
93 | | bool stopped_early_; |
94 | | int max_visits_; |
95 | | |
96 | | T WalkInternal(Regexp* re, T top_arg, bool use_copy); |
97 | | |
98 | | Walker(const Walker&) = delete; |
99 | | Walker& operator=(const Walker&) = delete; |
100 | | }; |
101 | | |
102 | | template<typename T> T Regexp::Walker<T>::PreVisit(Regexp* re, |
103 | | T parent_arg, |
104 | 1.30M | bool* stop) { |
105 | 1.30M | return parent_arg; |
106 | 1.30M | } Unexecuted instantiation: duckdb_re2::Regexp::Walker<int>::PreVisit(duckdb_re2::Regexp*, int, bool*) Unexecuted instantiation: duckdb_re2::Regexp::Walker<duckdb_re2::Frag>::PreVisit(duckdb_re2::Regexp*, duckdb_re2::Frag, bool*) duckdb_re2::Regexp::Walker<duckdb_re2::Regexp*>::PreVisit(duckdb_re2::Regexp*, duckdb_re2::Regexp*, bool*) Line | Count | Source | 104 | 1.30M | bool* stop) { | 105 | 1.30M | return parent_arg; | 106 | 1.30M | } |
|
107 | | |
108 | | template<typename T> T Regexp::Walker<T>::PostVisit(Regexp* re, |
109 | | T parent_arg, |
110 | | T pre_arg, |
111 | | T* child_args, |
112 | 1.22M | int nchild_args) { |
113 | 1.22M | return pre_arg; |
114 | 1.22M | } duckdb_re2::Regexp::Walker<int>::PostVisit(duckdb_re2::Regexp*, int, int, int*, int) Line | Count | Source | 112 | 1.22M | int nchild_args) { | 113 | 1.22M | return pre_arg; | 114 | 1.22M | } |
Unexecuted instantiation: duckdb_re2::Regexp::Walker<duckdb_re2::Frag>::PostVisit(duckdb_re2::Regexp*, duckdb_re2::Frag, duckdb_re2::Frag, duckdb_re2::Frag*, int) Unexecuted instantiation: duckdb_re2::Regexp::Walker<duckdb_re2::Regexp*>::PostVisit(duckdb_re2::Regexp*, duckdb_re2::Regexp*, duckdb_re2::Regexp*, duckdb_re2::Regexp**, int) |
115 | | |
116 | 0 | template<typename T> T Regexp::Walker<T>::Copy(T arg) { |
117 | 0 | return arg; |
118 | 0 | } Unexecuted instantiation: duckdb_re2::Regexp::Walker<int>::Copy(int) Unexecuted instantiation: duckdb_re2::Regexp::Walker<duckdb_re2::Frag>::Copy(duckdb_re2::Frag) Unexecuted instantiation: duckdb_re2::Regexp::Walker<duckdb_re2::Regexp*>::Copy(duckdb_re2::Regexp*) |
119 | | |
120 | | // State about a single level in the traversal. |
121 | | template<typename T> struct WalkState { |
122 | | WalkState(Regexp* re, T parent) |
123 | 5.23M | : re(re), |
124 | 5.23M | n(-1), |
125 | 3.64M | parent_arg(parent), |
126 | 5.23M | child_args(NULL) { } duckdb_re2::WalkState<int>::WalkState(duckdb_re2::Regexp*, int) Line | Count | Source | 123 | 1.22M | : re(re), | 124 | 1.22M | n(-1), | 125 | 1.22M | parent_arg(parent), | 126 | 1.22M | child_args(NULL) { } |
duckdb_re2::WalkState<duckdb_re2::Frag>::WalkState(duckdb_re2::Regexp*, duckdb_re2::Frag) Line | Count | Source | 123 | 1.59M | : re(re), | 124 | 1.59M | n(-1), | 125 | 1.59M | parent_arg(parent), | 126 | 1.59M | child_args(NULL) { } |
duckdb_re2::WalkState<duckdb_re2::Regexp*>::WalkState(duckdb_re2::Regexp*, duckdb_re2::Regexp*) Line | Count | Source | 123 | 2.41M | : re(re), | 124 | 2.41M | n(-1), | 125 | 2.41M | parent_arg(parent), | 126 | 2.41M | child_args(NULL) { } |
|
127 | | |
128 | | Regexp* re; // The regexp |
129 | | int n; // The index of the next child to process; -1 means need to PreVisit |
130 | | T parent_arg; // Accumulated arguments. |
131 | | T pre_arg; |
132 | | T child_arg; // One-element buffer for child_args. |
133 | | T* child_args; |
134 | | }; |
135 | | |
136 | 14.8k | template<typename T> Regexp::Walker<T>::Walker() { |
137 | 14.8k | stopped_early_ = false; |
138 | 14.8k | } duckdb_re2::Regexp::Walker<int>::Walker() Line | Count | Source | 136 | 3.73k | template<typename T> Regexp::Walker<T>::Walker() { | 137 | 3.73k | stopped_early_ = false; | 138 | 3.73k | } |
duckdb_re2::Regexp::Walker<duckdb_re2::Frag>::Walker() Line | Count | Source | 136 | 3.71k | template<typename T> Regexp::Walker<T>::Walker() { | 137 | 3.71k | stopped_early_ = false; | 138 | 3.71k | } |
duckdb_re2::Regexp::Walker<duckdb_re2::Regexp*>::Walker() Line | Count | Source | 136 | 7.43k | template<typename T> Regexp::Walker<T>::Walker() { | 137 | 7.43k | stopped_early_ = false; | 138 | 7.43k | } |
|
139 | | |
140 | 14.8k | template<typename T> Regexp::Walker<T>::~Walker() { |
141 | 14.8k | Reset(); |
142 | 14.8k | } duckdb_re2::Regexp::Walker<int>::~Walker() Line | Count | Source | 140 | 3.73k | template<typename T> Regexp::Walker<T>::~Walker() { | 141 | 3.73k | Reset(); | 142 | 3.73k | } |
duckdb_re2::Regexp::Walker<duckdb_re2::Frag>::~Walker() Line | Count | Source | 140 | 3.71k | template<typename T> Regexp::Walker<T>::~Walker() { | 141 | 3.71k | Reset(); | 142 | 3.71k | } |
duckdb_re2::Regexp::Walker<duckdb_re2::Regexp*>::~Walker() Line | Count | Source | 140 | 7.43k | template<typename T> Regexp::Walker<T>::~Walker() { | 141 | 7.43k | Reset(); | 142 | 7.43k | } |
|
143 | | |
144 | | // Clears the stack. Should never be necessary, since |
145 | | // Walk always enters and exits with an empty stack. |
146 | | // Logs DFATAL if stack is not already clear. |
147 | 29.7k | template<typename T> void Regexp::Walker<T>::Reset() { |
148 | 29.7k | if (!stack_.empty()) { |
149 | 0 | LOG(DFATAL) << "Stack not empty."; |
150 | 0 | while (!stack_.empty()) { |
151 | 0 | if (stack_.top().re->nsub_ > 1) |
152 | 0 | delete[] stack_.top().child_args; |
153 | 0 | stack_.pop(); |
154 | 0 | } |
155 | 0 | } |
156 | 29.7k | } duckdb_re2::Regexp::Walker<int>::Reset() Line | Count | Source | 147 | 7.47k | template<typename T> void Regexp::Walker<T>::Reset() { | 148 | 7.47k | if (!stack_.empty()) { | 149 | 0 | LOG(DFATAL) << "Stack not empty."; | 150 | 0 | while (!stack_.empty()) { | 151 | 0 | if (stack_.top().re->nsub_ > 1) | 152 | 0 | delete[] stack_.top().child_args; | 153 | 0 | stack_.pop(); | 154 | 0 | } | 155 | 0 | } | 156 | 7.47k | } |
duckdb_re2::Regexp::Walker<duckdb_re2::Frag>::Reset() Line | Count | Source | 147 | 7.43k | template<typename T> void Regexp::Walker<T>::Reset() { | 148 | 7.43k | if (!stack_.empty()) { | 149 | 0 | LOG(DFATAL) << "Stack not empty."; | 150 | 0 | while (!stack_.empty()) { | 151 | 0 | if (stack_.top().re->nsub_ > 1) | 152 | 0 | delete[] stack_.top().child_args; | 153 | 0 | stack_.pop(); | 154 | 0 | } | 155 | 0 | } | 156 | 7.43k | } |
duckdb_re2::Regexp::Walker<duckdb_re2::Regexp*>::Reset() Line | Count | Source | 147 | 14.8k | template<typename T> void Regexp::Walker<T>::Reset() { | 148 | 14.8k | if (!stack_.empty()) { | 149 | 0 | LOG(DFATAL) << "Stack not empty."; | 150 | 0 | while (!stack_.empty()) { | 151 | 0 | if (stack_.top().re->nsub_ > 1) | 152 | 0 | delete[] stack_.top().child_args; | 153 | 0 | stack_.pop(); | 154 | 0 | } | 155 | 0 | } | 156 | 14.8k | } |
|
157 | | |
158 | | template<typename T> T Regexp::Walker<T>::WalkInternal(Regexp* re, T top_arg, |
159 | 14.8k | bool use_copy) { |
160 | 14.8k | Reset(); |
161 | | |
162 | 14.8k | if (re == NULL) { |
163 | 0 | LOG(DFATAL) << "Walk NULL"; |
164 | 0 | return top_arg; |
165 | 0 | } |
166 | | |
167 | 14.8k | stack_.push(WalkState<T>(re, top_arg)); |
168 | | |
169 | 14.8k | WalkState<T>* s; |
170 | 10.4M | for (;;) { |
171 | 10.4M | T t; |
172 | 10.4M | s = &stack_.top(); |
173 | 10.4M | re = s->re; |
174 | 10.4M | switch (s->n) { |
175 | 5.23M | case -1: { |
176 | 5.23M | if (--max_visits_ < 0) { |
177 | 0 | stopped_early_ = true; |
178 | 0 | t = ShortVisit(re, s->parent_arg); |
179 | 0 | break; |
180 | 0 | } |
181 | 5.23M | bool stop = false; |
182 | 5.23M | s->pre_arg = PreVisit(re, s->parent_arg, &stop); |
183 | 5.23M | if (stop) { |
184 | 973k | t = s->pre_arg; |
185 | 973k | break; |
186 | 973k | } |
187 | 4.26M | s->n = 0; |
188 | 4.26M | s->child_args = NULL; |
189 | 4.26M | if (re->nsub_ == 1) |
190 | 274k | s->child_args = &s->child_arg; |
191 | 3.98M | else if (re->nsub_ > 1) |
192 | 266k | s->child_args = new T[re->nsub_]; |
193 | 4.26M | FALLTHROUGH_INTENDED; |
194 | 4.26M | } |
195 | 9.48M | default: { |
196 | 9.48M | if (re->nsub_ > 0) { |
197 | 5.76M | Regexp** sub = re->sub(); |
198 | 5.76M | if (s->n < re->nsub_) { |
199 | 5.22M | if (use_copy && s->n > 0 && sub[s->n - 1] == sub[s->n]) { |
200 | 0 | s->child_args[s->n] = Copy(s->child_args[s->n - 1]); |
201 | 0 | s->n++; |
202 | 5.22M | } else { |
203 | 5.22M | stack_.push(WalkState<T>(sub[s->n], s->pre_arg)); |
204 | 5.22M | } |
205 | 5.22M | continue; |
206 | 5.22M | } |
207 | 5.76M | } |
208 | | |
209 | 4.26M | t = PostVisit(re, s->parent_arg, s->pre_arg, s->child_args, s->n); |
210 | 4.26M | if (re->nsub_ > 1) |
211 | 266k | delete[] s->child_args; |
212 | 4.26M | break; |
213 | 9.48M | } |
214 | 10.4M | } |
215 | | |
216 | | // We've finished stack_.top(). |
217 | | // Update next guy down. |
218 | 5.23M | stack_.pop(); |
219 | 5.23M | if (stack_.empty()) |
220 | 14.8k | return t; |
221 | 5.22M | s = &stack_.top(); |
222 | 5.22M | if (s->child_args != NULL) |
223 | 5.22M | s->child_args[s->n] = t; |
224 | 0 | else |
225 | 0 | s->child_arg = t; |
226 | 5.22M | s->n++; |
227 | 5.22M | } |
228 | 14.8k | } duckdb_re2::Regexp::Walker<int>::WalkInternal(duckdb_re2::Regexp*, int, bool) Line | Count | Source | 159 | 3.73k | bool use_copy) { | 160 | 3.73k | Reset(); | 161 | | | 162 | 3.73k | if (re == NULL) { | 163 | 0 | LOG(DFATAL) << "Walk NULL"; | 164 | 0 | return top_arg; | 165 | 0 | } | 166 | | | 167 | 3.73k | stack_.push(WalkState<T>(re, top_arg)); | 168 | | | 169 | 3.73k | WalkState<T>* s; | 170 | 2.45M | for (;;) { | 171 | 2.45M | T t; | 172 | 2.45M | s = &stack_.top(); | 173 | 2.45M | re = s->re; | 174 | 2.45M | switch (s->n) { | 175 | 1.22M | case -1: { | 176 | 1.22M | if (--max_visits_ < 0) { | 177 | 0 | stopped_early_ = true; | 178 | 0 | t = ShortVisit(re, s->parent_arg); | 179 | 0 | break; | 180 | 0 | } | 181 | 1.22M | bool stop = false; | 182 | 1.22M | s->pre_arg = PreVisit(re, s->parent_arg, &stop); | 183 | 1.22M | if (stop) { | 184 | 0 | t = s->pre_arg; | 185 | 0 | break; | 186 | 0 | } | 187 | 1.22M | s->n = 0; | 188 | 1.22M | s->child_args = NULL; | 189 | 1.22M | if (re->nsub_ == 1) | 190 | 72.7k | s->child_args = &s->child_arg; | 191 | 1.15M | else if (re->nsub_ > 1) | 192 | 47.5k | s->child_args = new T[re->nsub_]; | 193 | 1.22M | FALLTHROUGH_INTENDED; | 194 | 1.22M | } | 195 | 2.45M | default: { | 196 | 2.45M | if (re->nsub_ > 0) { | 197 | 1.34M | Regexp** sub = re->sub(); | 198 | 1.34M | if (s->n < re->nsub_) { | 199 | 1.22M | if (use_copy && s->n > 0 && sub[s->n - 1] == sub[s->n]) { | 200 | 0 | s->child_args[s->n] = Copy(s->child_args[s->n - 1]); | 201 | 0 | s->n++; | 202 | 1.22M | } else { | 203 | 1.22M | stack_.push(WalkState<T>(sub[s->n], s->pre_arg)); | 204 | 1.22M | } | 205 | 1.22M | continue; | 206 | 1.22M | } | 207 | 1.34M | } | 208 | | | 209 | 1.22M | t = PostVisit(re, s->parent_arg, s->pre_arg, s->child_args, s->n); | 210 | 1.22M | if (re->nsub_ > 1) | 211 | 47.5k | delete[] s->child_args; | 212 | 1.22M | break; | 213 | 2.45M | } | 214 | 2.45M | } | 215 | | | 216 | | // We've finished stack_.top(). | 217 | | // Update next guy down. | 218 | 1.22M | stack_.pop(); | 219 | 1.22M | if (stack_.empty()) | 220 | 3.73k | return t; | 221 | 1.22M | s = &stack_.top(); | 222 | 1.22M | if (s->child_args != NULL) | 223 | 1.22M | s->child_args[s->n] = t; | 224 | 0 | else | 225 | 0 | s->child_arg = t; | 226 | 1.22M | s->n++; | 227 | 1.22M | } | 228 | 3.73k | } |
duckdb_re2::Regexp::Walker<duckdb_re2::Frag>::WalkInternal(duckdb_re2::Regexp*, duckdb_re2::Frag, bool) Line | Count | Source | 159 | 3.71k | bool use_copy) { | 160 | 3.71k | Reset(); | 161 | | | 162 | 3.71k | if (re == NULL) { | 163 | 0 | LOG(DFATAL) << "Walk NULL"; | 164 | 0 | return top_arg; | 165 | 0 | } | 166 | | | 167 | 3.71k | stack_.push(WalkState<T>(re, top_arg)); | 168 | | | 169 | 3.71k | WalkState<T>* s; | 170 | 3.17M | for (;;) { | 171 | 3.17M | T t; | 172 | 3.17M | s = &stack_.top(); | 173 | 3.17M | re = s->re; | 174 | 3.17M | switch (s->n) { | 175 | 1.59M | case -1: { | 176 | 1.59M | if (--max_visits_ < 0) { | 177 | 0 | stopped_early_ = true; | 178 | 0 | t = ShortVisit(re, s->parent_arg); | 179 | 0 | break; | 180 | 0 | } | 181 | 1.59M | bool stop = false; | 182 | 1.59M | s->pre_arg = PreVisit(re, s->parent_arg, &stop); | 183 | 1.59M | if (stop) { | 184 | 12.6k | t = s->pre_arg; | 185 | 12.6k | break; | 186 | 12.6k | } | 187 | 1.57M | s->n = 0; | 188 | 1.57M | s->child_args = NULL; | 189 | 1.57M | if (re->nsub_ == 1) | 190 | 73.5k | s->child_args = &s->child_arg; | 191 | 1.50M | else if (re->nsub_ > 1) | 192 | 120k | s->child_args = new T[re->nsub_]; | 193 | 1.57M | FALLTHROUGH_INTENDED; | 194 | 1.57M | } | 195 | 3.16M | default: { | 196 | 3.16M | if (re->nsub_ > 0) { | 197 | 1.78M | Regexp** sub = re->sub(); | 198 | 1.78M | if (s->n < re->nsub_) { | 199 | 1.58M | if (use_copy && s->n > 0 && sub[s->n - 1] == sub[s->n]) { | 200 | 0 | s->child_args[s->n] = Copy(s->child_args[s->n - 1]); | 201 | 0 | s->n++; | 202 | 1.58M | } else { | 203 | 1.58M | stack_.push(WalkState<T>(sub[s->n], s->pre_arg)); | 204 | 1.58M | } | 205 | 1.58M | continue; | 206 | 1.58M | } | 207 | 1.78M | } | 208 | | | 209 | 1.57M | t = PostVisit(re, s->parent_arg, s->pre_arg, s->child_args, s->n); | 210 | 1.57M | if (re->nsub_ > 1) | 211 | 120k | delete[] s->child_args; | 212 | 1.57M | break; | 213 | 3.16M | } | 214 | 3.17M | } | 215 | | | 216 | | // We've finished stack_.top(). | 217 | | // Update next guy down. | 218 | 1.59M | stack_.pop(); | 219 | 1.59M | if (stack_.empty()) | 220 | 3.71k | return t; | 221 | 1.58M | s = &stack_.top(); | 222 | 1.58M | if (s->child_args != NULL) | 223 | 1.58M | s->child_args[s->n] = t; | 224 | 0 | else | 225 | 0 | s->child_arg = t; | 226 | 1.58M | s->n++; | 227 | 1.58M | } | 228 | 3.71k | } |
duckdb_re2::Regexp::Walker<duckdb_re2::Regexp*>::WalkInternal(duckdb_re2::Regexp*, duckdb_re2::Regexp*, bool) Line | Count | Source | 159 | 7.43k | bool use_copy) { | 160 | 7.43k | Reset(); | 161 | | | 162 | 7.43k | if (re == NULL) { | 163 | 0 | LOG(DFATAL) << "Walk NULL"; | 164 | 0 | return top_arg; | 165 | 0 | } | 166 | | | 167 | 7.43k | stack_.push(WalkState<T>(re, top_arg)); | 168 | | | 169 | 7.43k | WalkState<T>* s; | 170 | 4.82M | for (;;) { | 171 | 4.82M | T t; | 172 | 4.82M | s = &stack_.top(); | 173 | 4.82M | re = s->re; | 174 | 4.82M | switch (s->n) { | 175 | 2.41M | case -1: { | 176 | 2.41M | if (--max_visits_ < 0) { | 177 | 0 | stopped_early_ = true; | 178 | 0 | t = ShortVisit(re, s->parent_arg); | 179 | 0 | break; | 180 | 0 | } | 181 | 2.41M | bool stop = false; | 182 | 2.41M | s->pre_arg = PreVisit(re, s->parent_arg, &stop); | 183 | 2.41M | if (stop) { | 184 | 960k | t = s->pre_arg; | 185 | 960k | break; | 186 | 960k | } | 187 | 1.45M | s->n = 0; | 188 | 1.45M | s->child_args = NULL; | 189 | 1.45M | if (re->nsub_ == 1) | 190 | 128k | s->child_args = &s->child_arg; | 191 | 1.32M | else if (re->nsub_ > 1) | 192 | 98.0k | s->child_args = new T[re->nsub_]; | 193 | 1.45M | FALLTHROUGH_INTENDED; | 194 | 1.45M | } | 195 | 3.86M | default: { | 196 | 3.86M | if (re->nsub_ > 0) { | 197 | 2.63M | Regexp** sub = re->sub(); | 198 | 2.63M | if (s->n < re->nsub_) { | 199 | 2.40M | if (use_copy && s->n > 0 && sub[s->n - 1] == sub[s->n]) { | 200 | 0 | s->child_args[s->n] = Copy(s->child_args[s->n - 1]); | 201 | 0 | s->n++; | 202 | 2.40M | } else { | 203 | 2.40M | stack_.push(WalkState<T>(sub[s->n], s->pre_arg)); | 204 | 2.40M | } | 205 | 2.40M | continue; | 206 | 2.40M | } | 207 | 2.63M | } | 208 | | | 209 | 1.45M | t = PostVisit(re, s->parent_arg, s->pre_arg, s->child_args, s->n); | 210 | 1.45M | if (re->nsub_ > 1) | 211 | 98.0k | delete[] s->child_args; | 212 | 1.45M | break; | 213 | 3.86M | } | 214 | 4.82M | } | 215 | | | 216 | | // We've finished stack_.top(). | 217 | | // Update next guy down. | 218 | 2.41M | stack_.pop(); | 219 | 2.41M | if (stack_.empty()) | 220 | 7.43k | return t; | 221 | 2.40M | s = &stack_.top(); | 222 | 2.40M | if (s->child_args != NULL) | 223 | 2.40M | s->child_args[s->n] = t; | 224 | 0 | else | 225 | 0 | s->child_arg = t; | 226 | 2.40M | s->n++; | 227 | 2.40M | } | 228 | 7.43k | } |
|
229 | | |
230 | 11.1k | template<typename T> T Regexp::Walker<T>::Walk(Regexp* re, T top_arg) { |
231 | | // Without the exponential walking behavior, |
232 | | // this budget should be more than enough for any |
233 | | // regexp, and yet not enough to get us in trouble |
234 | | // as far as CPU time. |
235 | 11.1k | max_visits_ = 1000000; |
236 | 11.1k | return WalkInternal(re, top_arg, true); |
237 | 11.1k | } duckdb_re2::Regexp::Walker<int>::Walk(duckdb_re2::Regexp*, int) Line | Count | Source | 230 | 3.73k | template<typename T> T Regexp::Walker<T>::Walk(Regexp* re, T top_arg) { | 231 | | // Without the exponential walking behavior, | 232 | | // this budget should be more than enough for any | 233 | | // regexp, and yet not enough to get us in trouble | 234 | | // as far as CPU time. | 235 | 3.73k | max_visits_ = 1000000; | 236 | 3.73k | return WalkInternal(re, top_arg, true); | 237 | 3.73k | } |
duckdb_re2::Regexp::Walker<duckdb_re2::Regexp*>::Walk(duckdb_re2::Regexp*, duckdb_re2::Regexp*) Line | Count | Source | 230 | 7.43k | template<typename T> T Regexp::Walker<T>::Walk(Regexp* re, T top_arg) { | 231 | | // Without the exponential walking behavior, | 232 | | // this budget should be more than enough for any | 233 | | // regexp, and yet not enough to get us in trouble | 234 | | // as far as CPU time. | 235 | 7.43k | max_visits_ = 1000000; | 236 | 7.43k | return WalkInternal(re, top_arg, true); | 237 | 7.43k | } |
|
238 | | |
239 | | template<typename T> T Regexp::Walker<T>::WalkExponential(Regexp* re, T top_arg, |
240 | 3.71k | int max_visits) { |
241 | 3.71k | max_visits_ = max_visits; |
242 | 3.71k | return WalkInternal(re, top_arg, false); |
243 | 3.71k | } duckdb_re2::Regexp::Walker<duckdb_re2::Frag>::WalkExponential(duckdb_re2::Regexp*, duckdb_re2::Frag, int) Line | Count | Source | 240 | 3.71k | int max_visits) { | 241 | 3.71k | max_visits_ = max_visits; | 242 | 3.71k | return WalkInternal(re, top_arg, false); | 243 | 3.71k | } |
Unexecuted instantiation: duckdb_re2::Regexp::Walker<int>::WalkExponential(duckdb_re2::Regexp*, int, int) |
244 | | |
245 | | } // namespace re2 |
246 | | |
247 | | #endif // RE2_WALKER_INL_H_ |