LLVM: include/llvm/ADT/RadixTree.h Source File (original) (raw)
71template <typename KeyType, typename T> class RadixTree {
72public:
75 using value_type = std::pair<const KeyType, mapped_type>;
76
77private:
78 using KeyConstIteratorType =
79 decltype(adl_begin(std::declval<const key_type &>()));
81 using KeyValueType =
83 using ContainerType = std::list<value_type>;
84
85
86 struct Node {
87 KeyConstIteratorRangeType Key{KeyConstIteratorType{},
88 KeyConstIteratorType{}};
89 std::vector Children;
90
91
92
93
94
95
96 std::optional Value;
97
98
99 KeyValueType KeyFront;
100
101 Node() = default;
102 Node(const KeyConstIteratorRangeType &Key)
103 : Key(Key), KeyFront(*Key.begin()) {
105 }
106
107 Node(Node &&) = default;
108 Node &operator=(Node &&) = default;
109
110 Node(const Node &) = delete;
111 Node &operator=(const Node &) = delete;
112
113 const Node *findChild(const KeyConstIteratorRangeType &Key) const {
114 if (Key.empty())
115 return nullptr;
116 for (const Node &Child : Children) {
117 assert(!Child.Key.empty());
118 if (Child.KeyFront == *Key.begin())
119 return &Child;
120 }
121 return nullptr;
122 }
123
124 Node *findChild(const KeyConstIteratorRangeType &Query) {
125 const Node *This = this;
126 return const_cast<Node *>(This->findChild(Query));
127 }
128
130 size_t R = 1;
131 for (const Node &C : Children)
132 R += C.countNodes();
133 return R;
134 }
135
136
137
138
139
140
141
142
143
144
145
146 void split(KeyConstIteratorType SplitPoint) {
149
150 Children.swap(Child.Children);
152
153 Children.emplace_back(std::move(Child));
154 }
155 };
156
157
158
160 ContainerType KeyValuePairs;
161
162
163 Node &findOrCreate(KeyConstIteratorRangeType Key) {
164 Node *Curr = &Root;
165 if (Key.empty())
166 return *Curr;
167
168 for (;;) {
171
172 if (I2 != Curr->Key.end()) {
173
174
175
176 Curr->split(I2);
177
178
179 break;
180 }
181
182 Node *Child = Curr->findChild(Key);
183 if (!Child)
184 break;
185
186
187 Curr = Child;
188 }
189
190 if (Key.empty()) {
191
192 return *Curr;
193 }
194
195
196
197
198 return Curr->Children.emplace_back(Key);
199 }
200
201
202
203
204
205
206
207
208
209
210 template
211 class IteratorImpl
212 : public iterator_facade_base<IteratorImpl,
213 std::forward_iterator_tag, MappedType> {
214 const Node *Curr = nullptr;
215 KeyConstIteratorRangeType Query{KeyConstIteratorType{},
216 KeyConstIteratorType{}};
217
218 void findNextValid() {
219 while (Curr && !Curr->Value.has_value())
220 advance();
221 }
222
223 void advance() {
225 if (Query.empty()) {
226 Curr = nullptr;
227 return;
228 }
229
230 Curr = Curr->findChild(Query);
231 if (!Curr) {
232 Curr = nullptr;
233 return;
234 }
235
237 if (I2 != Curr->Key.end()) {
238 Curr = nullptr;
239 return;
240 }
242 }
243
244 friend class RadixTree;
245 IteratorImpl(const Node *C, const KeyConstIteratorRangeType &Q)
246 : Curr(C), Query(Q) {
247 findNextValid();
248 }
249
250 public:
251 IteratorImpl() = default;
252
253 MappedType &operator*() const { return **Curr->Value; }
254
256 advance();
257 findNextValid();
258 return *this;
259 }
260
262 return Curr == Other.Curr;
263 }
264 };
265
266public:
270
273
274 using iterator = typename ContainerType::iterator;
276
277
278 bool empty() const { return KeyValuePairs.empty(); }
279
280
281 size_t size() const { return KeyValuePairs.size(); }
282
283
284
285
286
287 size_t countNodes() const { return Root.countNodes(); }
288
289
292
293
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310 template <typename... Ts>
312
313
314
315
316 const value_type &NewValue = KeyValuePairs.emplace_front(
317 std::move(Key), T(std::forward(Args)...));
318 Node &Node = findOrCreate(NewValue.first);
319 bool HasValue = Node.Value.has_value();
321 Node.Value = KeyValuePairs.begin();
322 else
323 KeyValuePairs.pop_front();
324 return {*Node.Value, };
325 }
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
347};