BDE 4.39.x Production Release
Loading...
Searching...
No Matches
ball_categorymanager_radixtree_cpp03.h
Go to the documentation of this file.
1/// @file ball_categorymanager_radixtree_cpp03.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// ball_categorymanager_radixtree_cpp03.h -*-C++-*-
8
9// Automatically generated file. **DO NOT EDIT**
10
11#ifndef INCLUDED_BALL_CATEGORYMANAGER_RADIXTREE_CPP03
12#define INCLUDED_BALL_CATEGORYMANAGER_RADIXTREE_CPP03
13
14/// @defgroup ball_categorymanager_radixtree_cpp03 ball_categorymanager_radixtree_cpp03
15/// @brief Provide C++03 implementation for ball_categorymanager_radixtree.h
16/// @addtogroup bal
17/// @{
18/// @addtogroup ball
19/// @{
20/// @addtogroup ball_categorymanager_radixtree_cpp03
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#ball_categorymanager_radixtree_cpp03-purpose"> Purpose</a>
25/// * <a href="#ball_categorymanager_radixtree_cpp03-classes"> Classes </a>
26/// * <a href="#ball_categorymanager_radixtree_cpp03-description"> Description </a>
27///
28/// # Purpose {#ball_categorymanager_radixtree_cpp03-purpose}
29/// Provide C++03 implementation for ball_categorymanager_radixtree.h
30///
31/// # Classes {#ball_categorymanager_radixtree_cpp03-classes}
32/// See ball_categorymanager_radixtree.h for list of classes
33///
34/// @see ball_categorymanager_radixtree
35///
36/// # Description {#ball_categorymanager_radixtree_cpp03-description}
37/// This component is the C++03 translation of a C++11 component,
38/// generated by the 'sim_cpp11_features.pl' program. If the original header
39/// contains any specially delimited regions of C++11 code, then this generated
40/// file contains the C++03 equivalent, i.e., with variadic templates expanded
41/// and rvalue-references replaced by 'bslmf::MovableRef' objects. The header
42/// code in this file is designed to be '#include'd into the original header
43/// when compiling with a C++03 compiler. If there are no specially delimited
44/// regions of C++11 code, then this header contains no code and is not
45/// '#include'd in the original header.
46///
47/// Generated on Fri May 29 20:18:26 2026
48/// Command line: sim_cpp11_features.pl ball_categorymanager_radixtree.h
49/// @}
50/** @} */
51/** @} */
52
53/** @addtogroup bal
54 * @{
55 */
56/** @addtogroup ball
57 * @{
58 */
59/** @addtogroup ball_categorymanager_radixtree_cpp03
60 * @{
61 */
62
63#ifdef COMPILING_BALL_CATEGORYMANAGER_RADIXTREE_H
64
65
66namespace ball {
67
68 // ====================================
69 // class CategoryManager_RadixTree_Node
70 // ====================================
71
72/// This class template represents a node in the radix tree. Each node stores
73/// a prefix string, an optional value, and child nodes mapped with their
74/// prefix-part starting character. As the second underscore in the class name
75/// indicates, this is a component-local class not intended for use outside of
76///
77/// See @ref ball_categorymanager_radixtree_cpp03
78// the radix tree implementation.
79template <class t_VALUE>
80class CategoryManager_RadixTree_Node {
81 public:
82 // PUBLIC TYPES
83
84 /// Child nodes mapped by the starting their starting character of their
85 /// prefix-part.
87
88 private:
89 // PRIVATE TYPES
91
92 private:
93 // DATA
94 bsl::string d_prefix; // prefix-part of this node
95 ValueProxy d_value; // optional value
96 Children d_children; // child nodes mapped by prefix part 1st character
97
98 public:
99 // PUBLIC TYPES
101
102 // CREATORS
103
104 /// Create a `CategoryManager_RadixTree_Node` object with the specified
105 /// `prefix` and no value. Optionally specify an `allocator` (e.g., the
106 /// address of a `bslma::Allocator` object) to supply memory; otherwise,
107 /// the default allocator is used.
110 const allocator_type& allocator = allocator_type());
111
112 /// Create a `CategoryManager_RadixTree_Node` object having the same value
113 /// as the specified `original` object. Use the default allocator to
114 /// supply memory for this object.
116 const CategoryManager_RadixTree_Node& original);
117
118 /// Create a `CategoryManager_RadixTree_Node` object having the same value
119 /// as the specified `original` object, and use the specified `allocator`
120 /// to supply memory for this new object.
122 const CategoryManager_RadixTree_Node& original,
123 const allocator_type& allocator);
124
125 /// Create a `CategoryManager_RadixTree_Node` object having the same value
126 /// as the specified `original` object by moving (in amortized constant
127 /// time) the contents of `original` to the newly-created object. The
128 /// allocator associated with `original` is propagated for use in the
129 /// newly-created object. `original` is left in a valid but unspecified
130 /// state.
134
135 /// Create a `CategoryManager_RadixTree_Node` object having the same value
136 /// as the specified `original` object, and use the specified `allocator`
137 /// to supply memory for this new object. The contents of `original` are
138 /// moved (in amortized constant time) to the newly-created object if
139 /// `allocator == original.get_allocator()`, and are move-inserted (in
140 /// linear time) using `allocator` otherwise. `original` is left in a
141 /// valid but unspecified state.
144 const allocator_type& allocator);
145
146 // MANIPULATORS
147
148 /// Assign to this object the value of the specified `rhs` object, and
149 /// return a reference providing modifiable access to this object.
151 const CategoryManager_RadixTree_Node& rhs);
152
153 /// Assign to this object the value of the specified `rhs` object, and
154 /// return a reference providing modifiable access to this object. The
155 /// contents of `rhs` are moved (in amortized constant time) to this object
156 /// if `get_allocator() == rhs.get_allocator()`; otherwise, all elements in
157 /// this object are either destroyed or move-assigned to, and each
158 /// additional element in `rhs` is move-inserted into this object. `rhs`
159 /// is left in a valid but unspecified state.
162
163 /// Return a reference providing modifiable access to the child nodes of
164 /// this node.
166
167 /// Return a reference providing modifiable access to the prefix string of this node.
168 ///
169 /// \note Note that only a part of the prefix is stored in a node;
170 /// the full key is obtained by concatenating the prefixes of all nodes.
172
173 /// Efficiently exchange the value of this object with the value of the
174 /// specified `other` object. This method provides the no-throw
175 /// exception-safety guarantee if the two objects were created with the
176 /// same allocator; otherwise, it provides the strong guarantee.
177 void swap(CategoryManager_RadixTree_Node& other);
178
179 /// Return a reference providing modifiable access to the optional value of
180 /// this node.
182
183 // ACCESSORS
184
185 /// Return a reference providing non-modifiable access to the child nodes
186 /// of this node.
187 const Children& children() const;
188
189 /// Return a reference providing non-modifiable access to the prefix string
190 /// of this node.
191 const bsl::string& prefix() const;
192
193 /// Return a reference providing non-modifiable access to the optional
194 /// value of this node.
195 const bsl::optional<t_VALUE>& value() const;
196
197 // Aspects
198
199 /// Return the allocator used by this object to supply memory.
201};
202
203// FREE OPERATORS
204
205/// Return `true` if the specified `lhs` and `rhs` nodes have the same value,
206/// and `false` otherwise. Two nodes have the same value if they have the same
207/// prefix, the same value (or both have no value), and the same children.
208template <class t_VALUE>
209bool operator==(const CategoryManager_RadixTree_Node<t_VALUE>& lhs,
210 const CategoryManager_RadixTree_Node<t_VALUE>& rhs);
211
212/// Return `true` if the specified `lhs` and `rhs` nodes do not have the same
213/// value, and `false` otherwise.
214template <class t_VALUE>
215bool operator!=(const CategoryManager_RadixTree_Node<t_VALUE>& lhs,
216 const CategoryManager_RadixTree_Node<t_VALUE>& rhs);
217
218 // ==============================================
219 // class CategoryManager_RadixTree_ChildNodeGuard
220 // ==============================================
221
222/// RAII guard to remove a child node when an exception is thrown during value
223/// emplacement in a `CategoryManager_RadixTree_Node`. This guard ensures
224/// exception safety by automatically removing a newly created child node from
225/// its parent if the value construction throws an exception.
226///
227/// See @ref ball_categorymanager_radixtree_cpp03
228template <class t_VALUE>
229class CategoryManager_RadixTree_ChildNodeGuard {
230 // TYPES
231 public:
232 typedef CategoryManager_RadixTree_Node<t_VALUE> Node;
233 typedef typename Node::Children::iterator ChildIterator;
234
235 private:
236 // DATA
237 Node *d_parent_p;
238 ChildIterator d_child;
239 bool d_released;
240
241 private:
242 // NOT IMPLEMENTED
243 CategoryManager_RadixTree_ChildNodeGuard(
244 const CategoryManager_RadixTree_ChildNodeGuard&)
246 CategoryManager_RadixTree_ChildNodeGuard& operator=(
247 const CategoryManager_RadixTree_ChildNodeGuard&)
249
250 public:
251 // CREATORS
252
253 /// Create a guard managing the specified `child` iterator in the
254 /// specified `parent` node. The guard will erase the child from the
255 /// parent upon destruction unless `release()` is called.
256 CategoryManager_RadixTree_ChildNodeGuard(Node *parent,
257 ChildIterator child);
258
259 /// Destroy this guard. If `release()` has not been called, erase the
260 /// child node from the parent (specified at construction).
262
263 // MANIPULATORS
264
265 /// Release this guard, preventing the child node from being erased upon
266 /// destruction. This method should be called after the value has been
267 /// successfully emplaced in the child node.
268 void release();
269};
270
271 // ===============================
272 // class CategoryManager_RadixTree
273 // ===============================
274
275/// This class template implements a space-efficient associative container that
276/// maps string keys to values of the specified `t_VALUE` type. The container
277/// uses a radix tree (compressed trie) data structure, which shares common
278/// prefixes among keys. The container provides O(k) insertion, lookup, and
279/// removal operations, where k is the key length.
280///
281/// See @ref ball_categorymanager_radixtree_cpp03
282template <class t_VALUE>
283class CategoryManager_RadixTree {
284 public:
285 // PUBLIC TYPES
287 typedef t_VALUE value_type;
288 typedef bsl::size_t size_type;
289
290 /// Type for mutable access to the optional value. Used also as return
291 /// type for mutable finders where empty optional signifies "not found".
293
294 /// Type for immutable access to the optional value. Used also as return
295 /// type for immutable finders where empty optional signifies "not found".
297
298 /// The return type of adding a value to the tree with `emplace()`. It is
299 /// *not* the usual `insert` return type, because this data structure does
300 /// not provide an iterator. The `.first` boolean is `true` if an element
301 /// was inserted, and the `.second` data member is a reference to the
302 /// (possibly newly created) value. Notice that if the value existed
303 /// (`.first == false`) the reference wrapper will still give access to the
304 /// value of that node; the `.second` is always a valid mutable reference
305 /// to the value belonging to the key used in the `emplace` call.
307
308 private:
309 // PRIVATE TYPES
310 typedef CategoryManager_RadixTree_Node<t_VALUE> Node;
311 typedef CategoryManager_RadixTree_ChildNodeGuard<t_VALUE> ChildNodeGuard;
312
313 // PRIVATE MANIPULATORS
314#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
315// {{{ BEGIN GENERATED CODE
316// Command line: sim_cpp11_features.pl ball_categorymanager_radixtree.h
317#ifndef BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT
318#define BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT 10
319#endif
320#ifndef BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A
321#define BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT
322#endif
323#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 0
324 EmplaceResult emplaceImp(Node *node,
325 const bsl::string_view& remainingKey);
326#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 0
327
328#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 1
329 template <class Args_01>
330 EmplaceResult emplaceImp(Node *node,
331 const bsl::string_view& remainingKey,
332 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01);
333#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 1
334
335#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 2
336 template <class Args_01,
337 class Args_02>
338 EmplaceResult emplaceImp(Node *node,
339 const bsl::string_view& remainingKey,
340 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
341 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02);
342#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 2
343
344#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 3
345 template <class Args_01,
346 class Args_02,
347 class Args_03>
348 EmplaceResult emplaceImp(Node *node,
349 const bsl::string_view& remainingKey,
350 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
351 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
352 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03);
353#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 3
354
355#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 4
356 template <class Args_01,
357 class Args_02,
358 class Args_03,
359 class Args_04>
360 EmplaceResult emplaceImp(Node *node,
361 const bsl::string_view& remainingKey,
362 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
363 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
364 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
365 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04);
366#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 4
367
368#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 5
369 template <class Args_01,
370 class Args_02,
371 class Args_03,
372 class Args_04,
373 class Args_05>
374 EmplaceResult emplaceImp(Node *node,
375 const bsl::string_view& remainingKey,
376 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
377 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
378 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
379 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
380 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05);
381#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 5
382
383#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 6
384 template <class Args_01,
385 class Args_02,
386 class Args_03,
387 class Args_04,
388 class Args_05,
389 class Args_06>
390 EmplaceResult emplaceImp(Node *node,
391 const bsl::string_view& remainingKey,
392 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
393 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
394 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
395 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
396 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
397 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06);
398#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 6
399
400#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 7
401 template <class Args_01,
402 class Args_02,
403 class Args_03,
404 class Args_04,
405 class Args_05,
406 class Args_06,
407 class Args_07>
408 EmplaceResult emplaceImp(Node *node,
409 const bsl::string_view& remainingKey,
410 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
411 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
412 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
413 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
414 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
415 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06,
416 BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07);
417#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 7
418
419#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 8
420 template <class Args_01,
421 class Args_02,
422 class Args_03,
423 class Args_04,
424 class Args_05,
425 class Args_06,
426 class Args_07,
427 class Args_08>
428 EmplaceResult emplaceImp(Node *node,
429 const bsl::string_view& remainingKey,
430 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
431 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
432 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
433 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
434 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
435 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06,
436 BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07,
437 BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08);
438#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 8
439
440#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 9
441 template <class Args_01,
442 class Args_02,
443 class Args_03,
444 class Args_04,
445 class Args_05,
446 class Args_06,
447 class Args_07,
448 class Args_08,
449 class Args_09>
450 EmplaceResult emplaceImp(Node *node,
451 const bsl::string_view& remainingKey,
452 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
453 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
454 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
455 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
456 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
457 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06,
458 BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07,
459 BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08,
460 BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) args_09);
461#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 9
462
463#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 10
464 template <class Args_01,
465 class Args_02,
466 class Args_03,
467 class Args_04,
468 class Args_05,
469 class Args_06,
470 class Args_07,
471 class Args_08,
472 class Args_09,
473 class Args_10>
474 EmplaceResult emplaceImp(Node *node,
475 const bsl::string_view& remainingKey,
476 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
477 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
478 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
479 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
480 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
481 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06,
482 BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07,
483 BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08,
484 BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) args_09,
485 BSLS_COMPILERFEATURES_FORWARD_REF(Args_10) args_10);
486#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 10
487
488#else
489// The generated code below is a workaround for the absence of perfect
490// forwarding in some compilers.
491 template <class... Args>
492 EmplaceResult emplaceImp(Node *node,
493 const bsl::string_view& remainingKey,
495// }}} END GENERATED CODE
496#endif
497
498 /// Recursively erase all children of the specified `node` (but not the
499 /// node itself). Return the number of entries removed.
500 size_type eraseAllChildren(Node *node);
501
502 /// Recursively erase the entry with the specified `remainingKey` from the
503 /// subtree rooted at the specified `node`. Return `true` if the entry was
504 /// removed, and `false` otherwise. Deleting an entry may not delete the
505 /// node corresponding to `remainingKey` if it has children. However if
506 /// the node is deleted, this method will also recursively delete
507 /// all now-unused (no value) nodes that lead to it. Notice that this
508 /// method erases one entry only, meaning that it does not erase entries
509 /// with keys that have `remainingKey` as a prefix. If a node exists with
510 /// `remainingKey` but has no value (it is not an entry) this method will
511 /// do nothing and return `false`.
512 bool eraseImp(Node *node, const bsl::string_view& remainingKey);
513
514 /// Recursively erase all entries with keys matching the specified
515 /// `remainingPrefix` from the subtree rooted at the specified `node`.
516 /// Return the number of entries removed. While deleting the entries all
517 /// nodes that become unused (no value and no children) are also deleted.
518 size_type erasePrefixImp(Node *node,
519 const bsl::string_view& remainingPrefix);
520
521 /// Clean up a child node after an erase operation. If the child at the
522 /// specified `it` in the specified `node`'s children map (accessed via
523 /// the specified `firstChar`) has no value and no children, remove it.
524 /// If the child has no value but exactly one grandchild, merge the child
525 /// with its grandchild to maintain a compact tree structure.
526 void cleanupChildAfterErase(
527 Node *node,
528 typename Node::Children::iterator it,
529 char firstChar);
530
531 private:
532 // PRIVATE CLASS METHODS
533
534 /// Recursively visit all key-value pairs in the subtree rooted at the
535 /// specified `node` with the specified `keyPrefix`, invoking the specified `functor` for each pair.
536 ///
537 /// \note Note that this variant does not allow
538 /// modifying the value by the functor. Return the number of times the
539 /// functor is called.
540 template <class t_FUNCTOR>
541 static void forEachImp(const Node *node,
542 const bsl::string_view& keyPrefix,
543 const t_FUNCTOR& functor);
544
545 /// Recursively visit all key-value pairs in the subtree rooted at the
546 /// specified `node` with the specified `keyPrefix`, invoking the specified `functor` for each pair.
547 ///
548 /// \note Note that this "manipulator" variant allows
549 /// modifying the value by the functor.
550 template <class t_FUNCTOR>
551 static void forEachImp(Node *node,
552 const bsl::string_view& keyPrefix,
553 const t_FUNCTOR& functor);
554
555 /// Recursively visit all key-value pairs in the subtree rooted at the
556 /// specified 'node' with the specified 'key', invoking the specified
557 /// 'functor' for each pair. This manipulator version allows modifying the
558 /// value by the functor. Return the number of times the functor was
559 /// called.
560 template <class t_FUNCTOR>
561 static size_type forEachPrefixImp(Node *node,
562 const bsl::string_view& key,
563 const t_FUNCTOR& functor);
564
565 /// Recursively visit all key-value pairs in the subtree rooted at the
566 /// specified 'node' with the specified 'key', invoking the specified
567 /// 'functor' for each pair. This accessor version does not allow modifying
568 /// the value by the functor. Return the number of times the functor was
569 /// called.
570 template <class t_FUNCTOR>
571 static size_type forEachPrefixImp(const Node *node,
572 const bsl::string_view& key,
573 const t_FUNCTOR& functor);
574
575 /// Recursively print the subtree rooted at the specified `node` with the
576 /// specified `keyPrefix` to the specified `stream`, using the specified
577 /// `currLevel` for indentation and `spacesPerLevel` for spacing control,
578 /// and when necessary the specified `depth` to indicate the depth on the
579 /// tree (in single line printing). This method is intended for debugging.
580 static void printNodeImp(bsl::ostream& stream,
581 int depth,
582 const Node *node,
583 const bsl::string& keyPrefix,
584 int currLevel,
585 int spacesPerLevel);
586
587 private:
588 // DATA
589 Node d_root; // root node of the tree
590 size_type d_size; // number of entries in the tree
591
592 // FRIENDS
593 template <class t_TYPE>
594 friend bool operator==(const CategoryManager_RadixTree<t_TYPE>&,
595 const CategoryManager_RadixTree<t_TYPE>&);
596
597 template <class t_TYPE>
598 friend void swap(CategoryManager_RadixTree<t_TYPE>& a,
599 CategoryManager_RadixTree<t_TYPE>& b);
600
601 public:
602 // CREATORS
603
604 /// Create an empty `CategoryManager_RadixTree`. Optionally specify
605 /// an `allocator` (e.g., the address of a `bslma::Allocator` object)
606 /// to supply memory; otherwise, the default allocator is used.
608 explicit CategoryManager_RadixTree(const allocator_type& allocator);
609
610 /// Create a `CategoryManager_RadixTree` having the same value as the
611 /// specified `original` object. Optionally specify an `allocator`
612 /// (e.g., the address of a `bslma::Allocator` object) to supply
613 /// memory; otherwise, the default allocator is used.
615 const CategoryManager_RadixTree& original,
616 const allocator_type& allocator = allocator_type());
617
618 /// Create a `CategoryManager_RadixTree` having the same value as the
619 /// specified `original` object by moving (in amortized constant time) the
620 /// contents of `original` to the newly-created object. The allocator
621 /// associated with `original` is propagated for use in the
622 /// newly-created object. `original` is left in a valid but
623 /// unspecified state.
627
628 /// Create a `CategoryManager_RadixTree` having the same value as the
629 /// specified `original` object that uses the specified `allocator` to
630 /// supply memory. The contents of `original` are moved (in amortized
631 /// constant time) to the newly-created object if
632 /// `allocator == original.get_allocator()`, and are move-inserted (in
633 /// linear time) using `allocator` otherwise. `original` is left in a
634 /// valid but unspecified state.
637 const allocator_type& allocator);
638
639 /// Destroy this object.
640 ~CategoryManager_RadixTree() = default;
641
642 // MANIPULATORS
643
644 /// Assign to this object the value of the specified `rhs` object, and
645 /// return a reference providing modifiable access to this object.
647
648 /// Assign to this object the value of the specified `rhs` object, and
649 /// return a reference providing modifiable access to this object. The
650 /// contents of `rhs` are moved (in amortized constant time) to this object
651 /// if `get_allocator() == rhs.get_allocator()`; otherwise, all elements in
652 /// this object are either destroyed or move-assigned to, and each
653 /// additional element in `rhs` is move-inserted into this object. `rhs`
654 /// is left in a valid but unspecified state.
657
658#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
659// {{{ BEGIN GENERATED CODE
660// Command line: sim_cpp11_features.pl ball_categorymanager_radixtree.h
661#ifndef BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT
662#define BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT 10
663#endif
664#ifndef BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B
665#define BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT
666#endif
667#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 0
669#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 0
670
671#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 1
672 template <class Args_01>
674 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01);
675#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 1
676
677#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 2
678 template <class Args_01,
679 class Args_02>
681 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
682 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02);
683#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 2
684
685#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 3
686 template <class Args_01,
687 class Args_02,
688 class Args_03>
690 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
691 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
692 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03);
693#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 3
694
695#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 4
696 template <class Args_01,
697 class Args_02,
698 class Args_03,
699 class Args_04>
701 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
702 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
703 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
704 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04);
705#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 4
706
707#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 5
708 template <class Args_01,
709 class Args_02,
710 class Args_03,
711 class Args_04,
712 class Args_05>
714 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
715 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
716 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
717 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
718 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05);
719#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 5
720
721#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 6
722 template <class Args_01,
723 class Args_02,
724 class Args_03,
725 class Args_04,
726 class Args_05,
727 class Args_06>
729 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
730 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
731 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
732 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
733 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
734 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06);
735#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 6
736
737#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 7
738 template <class Args_01,
739 class Args_02,
740 class Args_03,
741 class Args_04,
742 class Args_05,
743 class Args_06,
744 class Args_07>
746 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
747 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
748 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
749 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
750 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
751 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06,
752 BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07);
753#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 7
754
755#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 8
756 template <class Args_01,
757 class Args_02,
758 class Args_03,
759 class Args_04,
760 class Args_05,
761 class Args_06,
762 class Args_07,
763 class Args_08>
765 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
766 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
767 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
768 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
769 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
770 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06,
771 BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07,
772 BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08);
773#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 8
774
775#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 9
776 template <class Args_01,
777 class Args_02,
778 class Args_03,
779 class Args_04,
780 class Args_05,
781 class Args_06,
782 class Args_07,
783 class Args_08,
784 class Args_09>
786 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
787 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
788 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
789 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
790 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
791 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06,
792 BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07,
793 BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08,
794 BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) args_09);
795#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 9
796
797#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 10
798 template <class Args_01,
799 class Args_02,
800 class Args_03,
801 class Args_04,
802 class Args_05,
803 class Args_06,
804 class Args_07,
805 class Args_08,
806 class Args_09,
807 class Args_10>
809 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
810 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
811 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
812 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
813 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
814 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06,
815 BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07,
816 BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08,
817 BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) args_09,
818 BSLS_COMPILERFEATURES_FORWARD_REF(Args_10) args_10);
819#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 10
820
821#else
822// The generated code below is a workaround for the absence of perfect
823// forwarding in some compilers.
824 template <class... Args>
827// }}} END GENERATED CODE
828#endif
829
830 /// Remove all entries from this tree. After this call `empty()` will
831 /// return `true`. After this call the tree will have 0 nodes.
832 void clear();
833
834 /// Remove from this tree the entry with the specified `key`. Return
835 /// `true` if the entry was removed (key existed), and `false` otherwise.
836 bool erase(const bsl::string_view& key);
837
838 /// Remove all children of the entry matching the specified `prefix`, but
839 /// not the entry with the prefix itself. If unused (no value, no
840 /// children) nodes remain remove those, too. If no entry exists for
841 /// `prefix` remove nothing. Return the number of entries removed.
843
844 /// Remove from this tree all entries with keys that have the specified
845 /// `prefix`, including the entry for the `prefix` itself if it exists. Return the number of entries removed.
846 ///
847 /// \note Note that this method removes
848 /// all nodes whose keys start with `prefix`, not just those that have a
849 /// value.
851
852 /// Return an optional containing a reference to the modifiable value
853 /// associated with the specified `key`, or an empty optional if the key is
854 /// not found. The returned reference remains valid until the tree is
855 /// modified.
857
858 /// Return the longest prefix of the specified `key` that has an associated
859 /// value in this tree, or an empty string view if no such prefix exists.
860 /// If the optionally specified `value` is not null, load into `*value` a
861 /// reference to the value associated with the returned prefix.
862 ///
863 /// \note Note that an empty return value can mean either that no matching prefix exists,
864 /// or that the empty string itself is the longest matching prefix (when
865 /// the tree contains a value for the empty key). Also note that the
866 /// returned reference (if set) remains valid until the tree is modified.
868 const bsl::string_view& key);
869
870 /// Call the specified `functor` for each key-value pair in this tree.
871 /// The `functor` should be a callable object that accepts two parameters:
872 /// `const bsl::string_view&` for the key and `t_VALUE&` for the value.
873 /// The order of visitation is unspecified. Noteice that the functor is
874 /// able to modify the value.
875 template <class t_FUNCTOR>
876 void forEach(const t_FUNCTOR& functor);
877
878 /// Call the specified `functor` for each key-value pair whose key starts
879 /// with the specified `prefix`. The `functor` should be a callable object
880 /// that accepts two parameters: `const bsl::string_view&` for the key and
881 /// `t_VALUE&` for the value. Return the number of times the functor was
882 /// called. The order of visitation is unspecified. Noteice that the
883 /// functor is able to modify the value.
884 template <class t_FUNCTOR>
886 const t_FUNCTOR& functor);
887
888 /// Efficiently exchange the value of this object with the value of the
889 /// specified `other` object. This method provides the no-throw exception-safety guarantee.
890 ///
891 /// \pre The behavior is undefined unless this
892 /// object was created with the same allocator as `other`.
893 void swap(CategoryManager_RadixTree& other);
894
895 // ACCESSORS
896
897 /// Return `true` if this tree contains an entry for the specified `key`,
898 /// and `false` otherwise.
899 bool contains(const bsl::string_view& key) const;
900
901 /// Return the total number of nodes in this tree, including internal nodes without values.
902 ///
903 /// \note Note that this method has O(n) complexity where
904 /// n is the number of nodes, and is intended for use in testing to verify
905 /// tree structure invariants. In user code use `size()` that tells the
906 /// actual number of entries with values.
907 size_type countNodes() const;
908
909 /// Return `true` if this tree contains no entries, and `false` otherwise.
910 bool empty() const;
911
912 /// Return an optional containing a reference to the non-modifiable value
913 /// associated with the specified `key`, or an empty optional if the key is
914 /// not found. The returned reference remains valid until the tree is
915 /// modified.
916 OptValueCRef find(const bsl::string_view& key) const;
917
918 /// Return the longest prefix of the specified `key` that has an associated
919 /// value in this tree, or an empty string view if no such prefix exists.
920 /// If the optionally specified `value` is not null, load into `*value` a
921 /// reference to the value associated with the returned prefix.
922 ///
923 /// \note Note that an empty return value can mean either that no matching prefix exists,
924 /// or that the empty string itself is the longest matching prefix (when
925 /// the tree contains a value for the empty key). Also note that the
926 /// returned reference (if set) remains valid until the tree is modified.
928 OptValueCRef *value,
929 const bsl::string_view& key) const;
930
931 /// Call the specified `functor` for each key-value pair in this tree.
932 /// The `functor` should be a callable object that accepts two parameters:
933 /// `const bsl::string_view&` for the key and `const t_VALUE&` for the
934 /// value. The order of visitation is unspecified. See also the
935 /// manipulator variation that allows the functor to modify the value.
936 template <class t_FUNCTOR>
937 void forEach(const t_FUNCTOR& functor) const;
938
939 /// Call the specified `functor` for each key-value pair whose key starts
940 /// with the specified `prefix`. The `functor` should be a callable object
941 /// that accepts two parameters: `const bsl::string_view&` for the key and
942 /// `const t_VALUE&` for the value. Return the number of times the functor
943 /// was called. The order of visitation is unspecified. See also the
944 /// manipulator variation that allows the functor to modify the value.
945 template <class t_FUNCTOR>
947 const t_FUNCTOR& functor) const;
948
949 /// Write the value of this object to the specified output `stream` in a
950 /// human-readable format, and return a non-`const` reference to
951 /// `stream`. Optionally specify an initial indentation `level`, whose
952 /// absolute value is incremented recursively for nested objects. If
953 /// `level` is specified, optionally specify `spacesPerLevel`, whose
954 /// absolute value indicates the number of spaces per indentation level
955 /// for this and all of its nested objects. If `level` is negative,
956 /// suppress indentation of the first line. If `spacesPerLevel` is
957 /// negative, format the entire output on one line, suppressing all but
958 /// the initial indentation (as governed by `level`). If `stream` is not valid on entry, this operation has no effect.
959 ///
960 /// \note Note that the
961 /// format is not fully specified, and may change without notice.
962 bsl::ostream& printNodes(bsl::ostream& stream,
963 int level = 0,
964 int spacesPerLevel = 4) const;
965
966 /// Return the number of entries in this tree.
967 size_type size() const;
968
969 // Aspects
970
971 /// Return the allocator used by this object to supply memory.
972 ///
973 /// \note Note that if no allocator was supplied at construction the default allocator in
974 /// effect at construction is used.
976};
977
978// FREE OPERATORS
979
980/// Return `true` if the specified `lhs` and `rhs` objects have the same
981/// value, and `false` otherwise. Two `CategoryManager_RadixTree` objects
982/// have the same value if they have the same number of entries and each key
983/// in `lhs` maps to the same value as in `rhs`.
984template <class t_VALUE>
985bool operator==(const CategoryManager_RadixTree<t_VALUE>& lhs,
986 const CategoryManager_RadixTree<t_VALUE>& rhs);
987
988/// Return `true` if the specified `lhs` and `rhs` objects do not have the
989/// same value, and `false` otherwise. Two `CategoryManager_RadixTree`
990/// objects do not have the same value if they differ in their number of
991/// entries or if any key maps to different values in the two objects.
992template <class t_VALUE>
993bool operator!=(const CategoryManager_RadixTree<t_VALUE>& lhs,
994 const CategoryManager_RadixTree<t_VALUE>& rhs);
995
996// FREE FUNCTIONS
997
998/// Exchange the values of the specified `a` and `b` objects. This function
999/// provides the no-throw exception-safety guarantee if the two objects were
1000/// created with the same allocator and the basic guarantee otherwise.
1001template <class t_VALUE>
1002void swap(CategoryManager_RadixTree<t_VALUE>& a,
1003 CategoryManager_RadixTree<t_VALUE>& b);
1004
1005// ============================================================================
1006// INLINE FUNCTION DEFINITIONS
1007// ============================================================================
1008
1009 // ----------------------------------------------
1010 // class CategoryManager_RadixTree_ChildNodeGuard
1011 // ----------------------------------------------
1012
1013// CREATORS
1014template <class t_VALUE>
1015inline
1016CategoryManager_RadixTree_ChildNodeGuard<t_VALUE>::
1017CategoryManager_RadixTree_ChildNodeGuard(Node *parent,
1018 ChildIterator child)
1019: d_parent_p(parent)
1020, d_child(child)
1021, d_released(false)
1022{
1023 BSLS_ASSERT(parent);
1024 BSLS_ASSERT(child != parent->children().end());
1025}
1026
1027template <class t_VALUE>
1028inline
1029CategoryManager_RadixTree_ChildNodeGuard<t_VALUE>::
1030~CategoryManager_RadixTree_ChildNodeGuard()
1031{
1032 if (!d_released) {
1033 d_parent_p->children().erase(d_child);
1034 }
1035}
1036
1037// MANIPULATORS
1038template <class t_VALUE>
1039inline
1040void CategoryManager_RadixTree_ChildNodeGuard<t_VALUE>::release()
1041{
1042 d_released = true;
1043}
1044
1045 // ------------------------------------
1046 // class CategoryManager_RadixTree_Node
1047 // ------------------------------------
1048
1049// CREATORS
1050template <class t_VALUE>
1051inline
1052CategoryManager_RadixTree_Node<t_VALUE>::CategoryManager_RadixTree_Node(
1053 const bsl::string_view& prefix,
1054 const allocator_type& allocator)
1055: d_prefix(prefix, allocator)
1056, d_value(allocator)
1057, d_children(allocator)
1058{
1059}
1060
1061template <class t_VALUE>
1062inline
1063CategoryManager_RadixTree_Node<t_VALUE>::CategoryManager_RadixTree_Node(
1064 const CategoryManager_RadixTree_Node& original)
1065: d_prefix(original.d_prefix)
1066, d_value(original.d_value, allocator_type())
1067, d_children(original.d_children)
1068{
1069}
1070
1071template <class t_VALUE>
1072inline
1073CategoryManager_RadixTree_Node<t_VALUE>::CategoryManager_RadixTree_Node(
1074 const CategoryManager_RadixTree_Node& original,
1075 const allocator_type& allocator)
1076: d_prefix(original.d_prefix, allocator)
1077, d_value(original.d_value, allocator)
1078, d_children(original.d_children, allocator)
1079{
1080}
1081
1082template <class t_VALUE>
1083inline
1084CategoryManager_RadixTree_Node<t_VALUE>::CategoryManager_RadixTree_Node(
1088 bslmf::MovableRefUtil::access(original).d_prefix))
1089, d_value(allocator_type())
1090, d_children(bslmf::MovableRefUtil::move(
1091 bslmf::MovableRefUtil::access(original).d_children))
1092{
1093 d_value.object() =
1095 bslmf::MovableRefUtil::access(original).d_value.object());
1096}
1097
1098template <class t_VALUE>
1099inline
1100CategoryManager_RadixTree_Node<t_VALUE>::CategoryManager_RadixTree_Node(
1102 const allocator_type& allocator)
1103: d_prefix(bslmf::MovableRefUtil::move(
1104 bslmf::MovableRefUtil::access(original).d_prefix),
1105 allocator)
1106, d_value(bslmf::MovableRefUtil::move(
1107 bslmf::MovableRefUtil::access(original).d_value),
1108 allocator)
1109, d_children(bslmf::MovableRefUtil::move(
1110 bslmf::MovableRefUtil::access(original).d_children),
1111 allocator)
1112{
1113}
1114
1115// MANIPULATORS
1116template <class t_VALUE>
1117inline
1118CategoryManager_RadixTree_Node<t_VALUE>&
1119CategoryManager_RadixTree_Node<t_VALUE>::operator=(
1120 const CategoryManager_RadixTree_Node& rhs)
1121{
1122 if (this != &rhs) {
1123 // Copy-and-swap for strong exception safety
1124 CategoryManager_RadixTree_Node temp(rhs, get_allocator());
1125 swap(temp);
1126 }
1127 return *this;
1128}
1129
1130template <class t_VALUE>
1131inline
1132CategoryManager_RadixTree_Node<t_VALUE>&
1133CategoryManager_RadixTree_Node<t_VALUE>::operator=(
1135{
1136 CategoryManager_RadixTree_Node& lvalue = rhs;
1137 if (this != &lvalue) {
1138 if (get_allocator() == lvalue.get_allocator()) {
1139 // Same allocator - can swap efficiently
1140 swap(lvalue);
1141 }
1142 else {
1143 // Different allocators - must deep copy, use copy-and-swap
1144 CategoryManager_RadixTree_Node temp(lvalue, get_allocator());
1145 swap(temp);
1146 }
1147 }
1148 return *this;
1149}
1150
1151template <class t_VALUE>
1152inline
1153typename CategoryManager_RadixTree_Node<t_VALUE>::Children&
1154CategoryManager_RadixTree_Node<t_VALUE>::children()
1155{
1156 return d_children;
1157}
1158
1159template <class t_VALUE>
1160inline
1161bsl::string& CategoryManager_RadixTree_Node<t_VALUE>::prefix()
1162{
1163 return d_prefix;
1164}
1165
1166template <class t_VALUE>
1167void
1168CategoryManager_RadixTree_Node<t_VALUE>::swap(
1169 CategoryManager_RadixTree_Node& other)
1170{
1171 BSLS_ASSERT(get_allocator() == other.get_allocator());
1172
1173 bslalg::SwapUtil::swap(&d_prefix, &other.d_prefix);
1174 bslalg::SwapUtil::swap(&d_value.object(), &other.d_value.object());
1175 bslalg::SwapUtil::swap(&d_children, &other.d_children);
1176}
1177
1178template <class t_VALUE>
1179inline
1180bsl::optional<t_VALUE>& CategoryManager_RadixTree_Node<t_VALUE>::value()
1181{
1182 return d_value.object();
1183}
1184
1185// ACCESSORS
1186template <class t_VALUE>
1187inline
1188const typename CategoryManager_RadixTree_Node<t_VALUE>::Children&
1189CategoryManager_RadixTree_Node<t_VALUE>::children() const
1190{
1191 return d_children;
1192}
1193
1194template <class t_VALUE>
1195inline
1196const bsl::string& CategoryManager_RadixTree_Node<t_VALUE>::prefix() const
1197{
1198 return d_prefix;
1199}
1200
1201template <class t_VALUE>
1202inline
1204CategoryManager_RadixTree_Node<t_VALUE>::value() const
1205{
1206 return d_value.object();
1207}
1208
1209 // Aspects
1210
1211template <class t_VALUE>
1212inline
1213typename CategoryManager_RadixTree_Node<t_VALUE>::allocator_type
1214CategoryManager_RadixTree_Node<t_VALUE>::get_allocator() const
1215{
1216 return d_prefix.get_allocator();
1217}
1218
1219 // -------------------------------
1220 // class CategoryManager_RadixTree
1221 // -------------------------------
1222
1223// PRIVATE MANIPULATORS
1224#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
1225// {{{ BEGIN GENERATED CODE
1226// Command line: sim_cpp11_features.pl ball_categorymanager_radixtree.h
1227#ifndef BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT
1228#define BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT 10
1229#endif
1230#ifndef BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C
1231#define BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT
1232#endif
1233#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 0
1234template <class t_VALUE>
1235typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
1236CategoryManager_RadixTree<t_VALUE>::emplaceImp(
1237 Node *node,
1238 const bsl::string_view& remainingKey)
1239{
1240 BSLS_ASSERT(node);
1241
1242 if (remainingKey.empty()) {
1243 if (node->value().has_value()) {
1244 return EmplaceResult(false, node->value().value());
1245 }
1246 node->value().emplace();
1247 return EmplaceResult(true, node->value().value());
1248 }
1249
1250 const char firstChar = remainingKey[0];
1251 typename Node::Children::iterator it = node->children().find(firstChar);
1252
1253 if (it == node->children().end()) {
1254 typename Node::Children::iterator iter =
1255 node->children().emplace(firstChar, remainingKey).first;
1256 ChildNodeGuard guard(node, iter);
1257 iter->second.value().emplace();
1258 guard.release();
1259 return EmplaceResult(true, iter->second.value().value());
1260 }
1261
1262 Node& child = it->second;
1263 const bsl::string_view childPrefix = child.prefix();
1264
1265 size_type minLen = bsl::min(remainingKey.size(), childPrefix.size());
1266 const bsl::string_view::const_iterator mismatchPos =
1267 bsl::mismatch(remainingKey.begin(),
1268 remainingKey.begin() + minLen,
1269 childPrefix.begin())
1270 .first;
1271 const size_type commonLen = mismatchPos - remainingKey.begin();
1272
1273 if (commonLen == childPrefix.size()) {
1274 return emplaceImp(&child,
1275 remainingKey.substr(commonLen));
1276 }
1277
1278 Node splitNode(childPrefix.substr(0, commonLen), get_allocator());
1279
1280 Node childCopy(child, get_allocator());
1281 childCopy.prefix() = childPrefix.substr(commonLen);
1282
1283 splitNode.children().emplace(childCopy.prefix()[0],
1284 bslmf::MovableRefUtil::move(childCopy));
1285
1286 if (commonLen == remainingKey.size()) {
1287 splitNode.value().emplace();
1288
1289 it->second = bslmf::MovableRefUtil::move(splitNode);
1290 return EmplaceResult(true,
1291 it->second.value().value());
1292 }
1293
1294 const bsl::string_view newKey = remainingKey.substr(commonLen);
1295 const typename Node::Children::iterator newIter =
1296 splitNode.children().emplace(newKey[0], newKey).first;
1297 newIter->second.value().emplace();
1298
1299 it->second = bslmf::MovableRefUtil::move(splitNode);
1300 return EmplaceResult(true, newIter->second.value().value());
1301}
1302#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 0
1303
1304#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 1
1305template <class t_VALUE>
1306template <class Args_01>
1307typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
1308CategoryManager_RadixTree<t_VALUE>::emplaceImp(
1309 Node *node,
1310 const bsl::string_view& remainingKey,
1311 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01)
1312{
1313 BSLS_ASSERT(node);
1314
1315 if (remainingKey.empty()) {
1316 if (node->value().has_value()) {
1317 return EmplaceResult(false, node->value().value());
1318 }
1319 node->value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01));
1320 return EmplaceResult(true, node->value().value());
1321 }
1322
1323 const char firstChar = remainingKey[0];
1324 typename Node::Children::iterator it = node->children().find(firstChar);
1325
1326 if (it == node->children().end()) {
1327 typename Node::Children::iterator iter =
1328 node->children().emplace(firstChar, remainingKey).first;
1329 ChildNodeGuard guard(node, iter);
1330 iter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1331 args_01));
1332 guard.release();
1333 return EmplaceResult(true, iter->second.value().value());
1334 }
1335
1336 Node& child = it->second;
1337 const bsl::string_view childPrefix = child.prefix();
1338
1339 size_type minLen = bsl::min(remainingKey.size(), childPrefix.size());
1340 const bsl::string_view::const_iterator mismatchPos =
1341 bsl::mismatch(remainingKey.begin(),
1342 remainingKey.begin() + minLen,
1343 childPrefix.begin())
1344 .first;
1345 const size_type commonLen = mismatchPos - remainingKey.begin();
1346
1347 if (commonLen == childPrefix.size()) {
1348 return emplaceImp(&child,
1349 remainingKey.substr(commonLen),
1350 BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01));
1351 }
1352
1353 Node splitNode(childPrefix.substr(0, commonLen), get_allocator());
1354
1355 Node childCopy(child, get_allocator());
1356 childCopy.prefix() = childPrefix.substr(commonLen);
1357
1358 splitNode.children().emplace(childCopy.prefix()[0],
1359 bslmf::MovableRefUtil::move(childCopy));
1360
1361 if (commonLen == remainingKey.size()) {
1362 splitNode.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1363 args_01));
1364
1365 it->second = bslmf::MovableRefUtil::move(splitNode);
1366 return EmplaceResult(true,
1367 it->second.value().value());
1368 }
1369
1370 const bsl::string_view newKey = remainingKey.substr(commonLen);
1371 const typename Node::Children::iterator newIter =
1372 splitNode.children().emplace(newKey[0], newKey).first;
1373 newIter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1374 args_01));
1375
1376 it->second = bslmf::MovableRefUtil::move(splitNode);
1377 return EmplaceResult(true, newIter->second.value().value());
1378}
1379#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 1
1380
1381#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 2
1382template <class t_VALUE>
1383template <class Args_01,
1384 class Args_02>
1385typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
1386CategoryManager_RadixTree<t_VALUE>::emplaceImp(
1387 Node *node,
1388 const bsl::string_view& remainingKey,
1389 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
1390 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02)
1391{
1392 BSLS_ASSERT(node);
1393
1394 if (remainingKey.empty()) {
1395 if (node->value().has_value()) {
1396 return EmplaceResult(false, node->value().value());
1397 }
1398 node->value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
1399 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02));
1400 return EmplaceResult(true, node->value().value());
1401 }
1402
1403 const char firstChar = remainingKey[0];
1404 typename Node::Children::iterator it = node->children().find(firstChar);
1405
1406 if (it == node->children().end()) {
1407 typename Node::Children::iterator iter =
1408 node->children().emplace(firstChar, remainingKey).first;
1409 ChildNodeGuard guard(node, iter);
1410 iter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1411 args_01),
1413 args_02));
1414 guard.release();
1415 return EmplaceResult(true, iter->second.value().value());
1416 }
1417
1418 Node& child = it->second;
1419 const bsl::string_view childPrefix = child.prefix();
1420
1421 size_type minLen = bsl::min(remainingKey.size(), childPrefix.size());
1422 const bsl::string_view::const_iterator mismatchPos =
1423 bsl::mismatch(remainingKey.begin(),
1424 remainingKey.begin() + minLen,
1425 childPrefix.begin())
1426 .first;
1427 const size_type commonLen = mismatchPos - remainingKey.begin();
1428
1429 if (commonLen == childPrefix.size()) {
1430 return emplaceImp(&child,
1431 remainingKey.substr(commonLen),
1432 BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
1433 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02));
1434 }
1435
1436 Node splitNode(childPrefix.substr(0, commonLen), get_allocator());
1437
1438 Node childCopy(child, get_allocator());
1439 childCopy.prefix() = childPrefix.substr(commonLen);
1440
1441 splitNode.children().emplace(childCopy.prefix()[0],
1442 bslmf::MovableRefUtil::move(childCopy));
1443
1444 if (commonLen == remainingKey.size()) {
1445 splitNode.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1446 args_01),
1448 args_02));
1449
1450 it->second = bslmf::MovableRefUtil::move(splitNode);
1451 return EmplaceResult(true,
1452 it->second.value().value());
1453 }
1454
1455 const bsl::string_view newKey = remainingKey.substr(commonLen);
1456 const typename Node::Children::iterator newIter =
1457 splitNode.children().emplace(newKey[0], newKey).first;
1458 newIter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1459 args_01),
1461 args_02));
1462
1463 it->second = bslmf::MovableRefUtil::move(splitNode);
1464 return EmplaceResult(true, newIter->second.value().value());
1465}
1466#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 2
1467
1468#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 3
1469template <class t_VALUE>
1470template <class Args_01,
1471 class Args_02,
1472 class Args_03>
1473typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
1474CategoryManager_RadixTree<t_VALUE>::emplaceImp(
1475 Node *node,
1476 const bsl::string_view& remainingKey,
1477 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
1478 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
1479 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03)
1480{
1481 BSLS_ASSERT(node);
1482
1483 if (remainingKey.empty()) {
1484 if (node->value().has_value()) {
1485 return EmplaceResult(false, node->value().value());
1486 }
1487 node->value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
1488 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02),
1489 BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03));
1490 return EmplaceResult(true, node->value().value());
1491 }
1492
1493 const char firstChar = remainingKey[0];
1494 typename Node::Children::iterator it = node->children().find(firstChar);
1495
1496 if (it == node->children().end()) {
1497 typename Node::Children::iterator iter =
1498 node->children().emplace(firstChar, remainingKey).first;
1499 ChildNodeGuard guard(node, iter);
1500 iter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1501 args_01),
1503 args_02),
1505 args_03));
1506 guard.release();
1507 return EmplaceResult(true, iter->second.value().value());
1508 }
1509
1510 Node& child = it->second;
1511 const bsl::string_view childPrefix = child.prefix();
1512
1513 size_type minLen = bsl::min(remainingKey.size(), childPrefix.size());
1514 const bsl::string_view::const_iterator mismatchPos =
1515 bsl::mismatch(remainingKey.begin(),
1516 remainingKey.begin() + minLen,
1517 childPrefix.begin())
1518 .first;
1519 const size_type commonLen = mismatchPos - remainingKey.begin();
1520
1521 if (commonLen == childPrefix.size()) {
1522 return emplaceImp(&child,
1523 remainingKey.substr(commonLen),
1524 BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
1525 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02),
1526 BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03));
1527 }
1528
1529 Node splitNode(childPrefix.substr(0, commonLen), get_allocator());
1530
1531 Node childCopy(child, get_allocator());
1532 childCopy.prefix() = childPrefix.substr(commonLen);
1533
1534 splitNode.children().emplace(childCopy.prefix()[0],
1535 bslmf::MovableRefUtil::move(childCopy));
1536
1537 if (commonLen == remainingKey.size()) {
1538 splitNode.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1539 args_01),
1541 args_02),
1543 args_03));
1544
1545 it->second = bslmf::MovableRefUtil::move(splitNode);
1546 return EmplaceResult(true,
1547 it->second.value().value());
1548 }
1549
1550 const bsl::string_view newKey = remainingKey.substr(commonLen);
1551 const typename Node::Children::iterator newIter =
1552 splitNode.children().emplace(newKey[0], newKey).first;
1553 newIter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1554 args_01),
1556 args_02),
1558 args_03));
1559
1560 it->second = bslmf::MovableRefUtil::move(splitNode);
1561 return EmplaceResult(true, newIter->second.value().value());
1562}
1563#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 3
1564
1565#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 4
1566template <class t_VALUE>
1567template <class Args_01,
1568 class Args_02,
1569 class Args_03,
1570 class Args_04>
1571typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
1572CategoryManager_RadixTree<t_VALUE>::emplaceImp(
1573 Node *node,
1574 const bsl::string_view& remainingKey,
1575 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
1576 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
1577 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
1578 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04)
1579{
1580 BSLS_ASSERT(node);
1581
1582 if (remainingKey.empty()) {
1583 if (node->value().has_value()) {
1584 return EmplaceResult(false, node->value().value());
1585 }
1586 node->value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
1587 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02),
1588 BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03),
1589 BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04));
1590 return EmplaceResult(true, node->value().value());
1591 }
1592
1593 const char firstChar = remainingKey[0];
1594 typename Node::Children::iterator it = node->children().find(firstChar);
1595
1596 if (it == node->children().end()) {
1597 typename Node::Children::iterator iter =
1598 node->children().emplace(firstChar, remainingKey).first;
1599 ChildNodeGuard guard(node, iter);
1600 iter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1601 args_01),
1603 args_02),
1605 args_03),
1607 args_04));
1608 guard.release();
1609 return EmplaceResult(true, iter->second.value().value());
1610 }
1611
1612 Node& child = it->second;
1613 const bsl::string_view childPrefix = child.prefix();
1614
1615 size_type minLen = bsl::min(remainingKey.size(), childPrefix.size());
1616 const bsl::string_view::const_iterator mismatchPos =
1617 bsl::mismatch(remainingKey.begin(),
1618 remainingKey.begin() + minLen,
1619 childPrefix.begin())
1620 .first;
1621 const size_type commonLen = mismatchPos - remainingKey.begin();
1622
1623 if (commonLen == childPrefix.size()) {
1624 return emplaceImp(&child,
1625 remainingKey.substr(commonLen),
1626 BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
1627 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02),
1628 BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03),
1629 BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04));
1630 }
1631
1632 Node splitNode(childPrefix.substr(0, commonLen), get_allocator());
1633
1634 Node childCopy(child, get_allocator());
1635 childCopy.prefix() = childPrefix.substr(commonLen);
1636
1637 splitNode.children().emplace(childCopy.prefix()[0],
1638 bslmf::MovableRefUtil::move(childCopy));
1639
1640 if (commonLen == remainingKey.size()) {
1641 splitNode.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1642 args_01),
1644 args_02),
1646 args_03),
1648 args_04));
1649
1650 it->second = bslmf::MovableRefUtil::move(splitNode);
1651 return EmplaceResult(true,
1652 it->second.value().value());
1653 }
1654
1655 const bsl::string_view newKey = remainingKey.substr(commonLen);
1656 const typename Node::Children::iterator newIter =
1657 splitNode.children().emplace(newKey[0], newKey).first;
1658 newIter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1659 args_01),
1661 args_02),
1663 args_03),
1665 args_04));
1666
1667 it->second = bslmf::MovableRefUtil::move(splitNode);
1668 return EmplaceResult(true, newIter->second.value().value());
1669}
1670#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 4
1671
1672#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 5
1673template <class t_VALUE>
1674template <class Args_01,
1675 class Args_02,
1676 class Args_03,
1677 class Args_04,
1678 class Args_05>
1679typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
1680CategoryManager_RadixTree<t_VALUE>::emplaceImp(
1681 Node *node,
1682 const bsl::string_view& remainingKey,
1683 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
1684 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
1685 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
1686 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
1687 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05)
1688{
1689 BSLS_ASSERT(node);
1690
1691 if (remainingKey.empty()) {
1692 if (node->value().has_value()) {
1693 return EmplaceResult(false, node->value().value());
1694 }
1695 node->value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
1696 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02),
1697 BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03),
1698 BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04),
1699 BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05));
1700 return EmplaceResult(true, node->value().value());
1701 }
1702
1703 const char firstChar = remainingKey[0];
1704 typename Node::Children::iterator it = node->children().find(firstChar);
1705
1706 if (it == node->children().end()) {
1707 typename Node::Children::iterator iter =
1708 node->children().emplace(firstChar, remainingKey).first;
1709 ChildNodeGuard guard(node, iter);
1710 iter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1711 args_01),
1713 args_02),
1715 args_03),
1717 args_04),
1719 args_05));
1720 guard.release();
1721 return EmplaceResult(true, iter->second.value().value());
1722 }
1723
1724 Node& child = it->second;
1725 const bsl::string_view childPrefix = child.prefix();
1726
1727 size_type minLen = bsl::min(remainingKey.size(), childPrefix.size());
1728 const bsl::string_view::const_iterator mismatchPos =
1729 bsl::mismatch(remainingKey.begin(),
1730 remainingKey.begin() + minLen,
1731 childPrefix.begin())
1732 .first;
1733 const size_type commonLen = mismatchPos - remainingKey.begin();
1734
1735 if (commonLen == childPrefix.size()) {
1736 return emplaceImp(&child,
1737 remainingKey.substr(commonLen),
1738 BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
1739 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02),
1740 BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03),
1741 BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04),
1742 BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05));
1743 }
1744
1745 Node splitNode(childPrefix.substr(0, commonLen), get_allocator());
1746
1747 Node childCopy(child, get_allocator());
1748 childCopy.prefix() = childPrefix.substr(commonLen);
1749
1750 splitNode.children().emplace(childCopy.prefix()[0],
1751 bslmf::MovableRefUtil::move(childCopy));
1752
1753 if (commonLen == remainingKey.size()) {
1754 splitNode.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1755 args_01),
1757 args_02),
1759 args_03),
1761 args_04),
1763 args_05));
1764
1765 it->second = bslmf::MovableRefUtil::move(splitNode);
1766 return EmplaceResult(true,
1767 it->second.value().value());
1768 }
1769
1770 const bsl::string_view newKey = remainingKey.substr(commonLen);
1771 const typename Node::Children::iterator newIter =
1772 splitNode.children().emplace(newKey[0], newKey).first;
1773 newIter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1774 args_01),
1776 args_02),
1778 args_03),
1780 args_04),
1782 args_05));
1783
1784 it->second = bslmf::MovableRefUtil::move(splitNode);
1785 return EmplaceResult(true, newIter->second.value().value());
1786}
1787#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 5
1788
1789#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 6
1790template <class t_VALUE>
1791template <class Args_01,
1792 class Args_02,
1793 class Args_03,
1794 class Args_04,
1795 class Args_05,
1796 class Args_06>
1797typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
1798CategoryManager_RadixTree<t_VALUE>::emplaceImp(
1799 Node *node,
1800 const bsl::string_view& remainingKey,
1801 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
1802 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
1803 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
1804 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
1805 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
1806 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06)
1807{
1808 BSLS_ASSERT(node);
1809
1810 if (remainingKey.empty()) {
1811 if (node->value().has_value()) {
1812 return EmplaceResult(false, node->value().value());
1813 }
1814 node->value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
1815 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02),
1816 BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03),
1817 BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04),
1818 BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05),
1819 BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06));
1820 return EmplaceResult(true, node->value().value());
1821 }
1822
1823 const char firstChar = remainingKey[0];
1824 typename Node::Children::iterator it = node->children().find(firstChar);
1825
1826 if (it == node->children().end()) {
1827 typename Node::Children::iterator iter =
1828 node->children().emplace(firstChar, remainingKey).first;
1829 ChildNodeGuard guard(node, iter);
1830 iter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1831 args_01),
1833 args_02),
1835 args_03),
1837 args_04),
1839 args_05),
1841 args_06));
1842 guard.release();
1843 return EmplaceResult(true, iter->second.value().value());
1844 }
1845
1846 Node& child = it->second;
1847 const bsl::string_view childPrefix = child.prefix();
1848
1849 size_type minLen = bsl::min(remainingKey.size(), childPrefix.size());
1850 const bsl::string_view::const_iterator mismatchPos =
1851 bsl::mismatch(remainingKey.begin(),
1852 remainingKey.begin() + minLen,
1853 childPrefix.begin())
1854 .first;
1855 const size_type commonLen = mismatchPos - remainingKey.begin();
1856
1857 if (commonLen == childPrefix.size()) {
1858 return emplaceImp(&child,
1859 remainingKey.substr(commonLen),
1860 BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
1861 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02),
1862 BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03),
1863 BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04),
1864 BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05),
1865 BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06));
1866 }
1867
1868 Node splitNode(childPrefix.substr(0, commonLen), get_allocator());
1869
1870 Node childCopy(child, get_allocator());
1871 childCopy.prefix() = childPrefix.substr(commonLen);
1872
1873 splitNode.children().emplace(childCopy.prefix()[0],
1874 bslmf::MovableRefUtil::move(childCopy));
1875
1876 if (commonLen == remainingKey.size()) {
1877 splitNode.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1878 args_01),
1880 args_02),
1882 args_03),
1884 args_04),
1886 args_05),
1888 args_06));
1889
1890 it->second = bslmf::MovableRefUtil::move(splitNode);
1891 return EmplaceResult(true,
1892 it->second.value().value());
1893 }
1894
1895 const bsl::string_view newKey = remainingKey.substr(commonLen);
1896 const typename Node::Children::iterator newIter =
1897 splitNode.children().emplace(newKey[0], newKey).first;
1898 newIter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1899 args_01),
1901 args_02),
1903 args_03),
1905 args_04),
1907 args_05),
1909 args_06));
1910
1911 it->second = bslmf::MovableRefUtil::move(splitNode);
1912 return EmplaceResult(true, newIter->second.value().value());
1913}
1914#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 6
1915
1916#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 7
1917template <class t_VALUE>
1918template <class Args_01,
1919 class Args_02,
1920 class Args_03,
1921 class Args_04,
1922 class Args_05,
1923 class Args_06,
1924 class Args_07>
1925typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
1926CategoryManager_RadixTree<t_VALUE>::emplaceImp(
1927 Node *node,
1928 const bsl::string_view& remainingKey,
1929 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
1930 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
1931 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
1932 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
1933 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
1934 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06,
1935 BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07)
1936{
1937 BSLS_ASSERT(node);
1938
1939 if (remainingKey.empty()) {
1940 if (node->value().has_value()) {
1941 return EmplaceResult(false, node->value().value());
1942 }
1943 node->value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
1944 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02),
1945 BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03),
1946 BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04),
1947 BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05),
1948 BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06),
1949 BSLS_COMPILERFEATURES_FORWARD(Args_07, args_07));
1950 return EmplaceResult(true, node->value().value());
1951 }
1952
1953 const char firstChar = remainingKey[0];
1954 typename Node::Children::iterator it = node->children().find(firstChar);
1955
1956 if (it == node->children().end()) {
1957 typename Node::Children::iterator iter =
1958 node->children().emplace(firstChar, remainingKey).first;
1959 ChildNodeGuard guard(node, iter);
1960 iter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
1961 args_01),
1963 args_02),
1965 args_03),
1967 args_04),
1969 args_05),
1971 args_06),
1973 args_07));
1974 guard.release();
1975 return EmplaceResult(true, iter->second.value().value());
1976 }
1977
1978 Node& child = it->second;
1979 const bsl::string_view childPrefix = child.prefix();
1980
1981 size_type minLen = bsl::min(remainingKey.size(), childPrefix.size());
1982 const bsl::string_view::const_iterator mismatchPos =
1983 bsl::mismatch(remainingKey.begin(),
1984 remainingKey.begin() + minLen,
1985 childPrefix.begin())
1986 .first;
1987 const size_type commonLen = mismatchPos - remainingKey.begin();
1988
1989 if (commonLen == childPrefix.size()) {
1990 return emplaceImp(&child,
1991 remainingKey.substr(commonLen),
1992 BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
1993 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02),
1994 BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03),
1995 BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04),
1996 BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05),
1997 BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06),
1998 BSLS_COMPILERFEATURES_FORWARD(Args_07, args_07));
1999 }
2000
2001 Node splitNode(childPrefix.substr(0, commonLen), get_allocator());
2002
2003 Node childCopy(child, get_allocator());
2004 childCopy.prefix() = childPrefix.substr(commonLen);
2005
2006 splitNode.children().emplace(childCopy.prefix()[0],
2007 bslmf::MovableRefUtil::move(childCopy));
2008
2009 if (commonLen == remainingKey.size()) {
2010 splitNode.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
2011 args_01),
2013 args_02),
2015 args_03),
2017 args_04),
2019 args_05),
2021 args_06),
2023 args_07));
2024
2025 it->second = bslmf::MovableRefUtil::move(splitNode);
2026 return EmplaceResult(true,
2027 it->second.value().value());
2028 }
2029
2030 const bsl::string_view newKey = remainingKey.substr(commonLen);
2031 const typename Node::Children::iterator newIter =
2032 splitNode.children().emplace(newKey[0], newKey).first;
2033 newIter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
2034 args_01),
2036 args_02),
2038 args_03),
2040 args_04),
2042 args_05),
2044 args_06),
2046 args_07));
2047
2048 it->second = bslmf::MovableRefUtil::move(splitNode);
2049 return EmplaceResult(true, newIter->second.value().value());
2050}
2051#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 7
2052
2053#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 8
2054template <class t_VALUE>
2055template <class Args_01,
2056 class Args_02,
2057 class Args_03,
2058 class Args_04,
2059 class Args_05,
2060 class Args_06,
2061 class Args_07,
2062 class Args_08>
2063typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
2064CategoryManager_RadixTree<t_VALUE>::emplaceImp(
2065 Node *node,
2066 const bsl::string_view& remainingKey,
2067 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
2068 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
2069 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
2070 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
2071 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
2072 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06,
2073 BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07,
2074 BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08)
2075{
2076 BSLS_ASSERT(node);
2077
2078 if (remainingKey.empty()) {
2079 if (node->value().has_value()) {
2080 return EmplaceResult(false, node->value().value());
2081 }
2082 node->value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
2083 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02),
2084 BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03),
2085 BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04),
2086 BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05),
2087 BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06),
2088 BSLS_COMPILERFEATURES_FORWARD(Args_07, args_07),
2089 BSLS_COMPILERFEATURES_FORWARD(Args_08, args_08));
2090 return EmplaceResult(true, node->value().value());
2091 }
2092
2093 const char firstChar = remainingKey[0];
2094 typename Node::Children::iterator it = node->children().find(firstChar);
2095
2096 if (it == node->children().end()) {
2097 typename Node::Children::iterator iter =
2098 node->children().emplace(firstChar, remainingKey).first;
2099 ChildNodeGuard guard(node, iter);
2100 iter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
2101 args_01),
2103 args_02),
2105 args_03),
2107 args_04),
2109 args_05),
2111 args_06),
2113 args_07),
2115 args_08));
2116 guard.release();
2117 return EmplaceResult(true, iter->second.value().value());
2118 }
2119
2120 Node& child = it->second;
2121 const bsl::string_view childPrefix = child.prefix();
2122
2123 size_type minLen = bsl::min(remainingKey.size(), childPrefix.size());
2124 const bsl::string_view::const_iterator mismatchPos =
2125 bsl::mismatch(remainingKey.begin(),
2126 remainingKey.begin() + minLen,
2127 childPrefix.begin())
2128 .first;
2129 const size_type commonLen = mismatchPos - remainingKey.begin();
2130
2131 if (commonLen == childPrefix.size()) {
2132 return emplaceImp(&child,
2133 remainingKey.substr(commonLen),
2134 BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
2135 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02),
2136 BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03),
2137 BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04),
2138 BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05),
2139 BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06),
2140 BSLS_COMPILERFEATURES_FORWARD(Args_07, args_07),
2141 BSLS_COMPILERFEATURES_FORWARD(Args_08, args_08));
2142 }
2143
2144 Node splitNode(childPrefix.substr(0, commonLen), get_allocator());
2145
2146 Node childCopy(child, get_allocator());
2147 childCopy.prefix() = childPrefix.substr(commonLen);
2148
2149 splitNode.children().emplace(childCopy.prefix()[0],
2150 bslmf::MovableRefUtil::move(childCopy));
2151
2152 if (commonLen == remainingKey.size()) {
2153 splitNode.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
2154 args_01),
2156 args_02),
2158 args_03),
2160 args_04),
2162 args_05),
2164 args_06),
2166 args_07),
2168 args_08));
2169
2170 it->second = bslmf::MovableRefUtil::move(splitNode);
2171 return EmplaceResult(true,
2172 it->second.value().value());
2173 }
2174
2175 const bsl::string_view newKey = remainingKey.substr(commonLen);
2176 const typename Node::Children::iterator newIter =
2177 splitNode.children().emplace(newKey[0], newKey).first;
2178 newIter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
2179 args_01),
2181 args_02),
2183 args_03),
2185 args_04),
2187 args_05),
2189 args_06),
2191 args_07),
2193 args_08));
2194
2195 it->second = bslmf::MovableRefUtil::move(splitNode);
2196 return EmplaceResult(true, newIter->second.value().value());
2197}
2198#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 8
2199
2200#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 9
2201template <class t_VALUE>
2202template <class Args_01,
2203 class Args_02,
2204 class Args_03,
2205 class Args_04,
2206 class Args_05,
2207 class Args_06,
2208 class Args_07,
2209 class Args_08,
2210 class Args_09>
2211typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
2212CategoryManager_RadixTree<t_VALUE>::emplaceImp(
2213 Node *node,
2214 const bsl::string_view& remainingKey,
2215 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
2216 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
2217 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
2218 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
2219 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
2220 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06,
2221 BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07,
2222 BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08,
2223 BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) args_09)
2224{
2225 BSLS_ASSERT(node);
2226
2227 if (remainingKey.empty()) {
2228 if (node->value().has_value()) {
2229 return EmplaceResult(false, node->value().value());
2230 }
2231 node->value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
2232 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02),
2233 BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03),
2234 BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04),
2235 BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05),
2236 BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06),
2237 BSLS_COMPILERFEATURES_FORWARD(Args_07, args_07),
2238 BSLS_COMPILERFEATURES_FORWARD(Args_08, args_08),
2239 BSLS_COMPILERFEATURES_FORWARD(Args_09, args_09));
2240 return EmplaceResult(true, node->value().value());
2241 }
2242
2243 const char firstChar = remainingKey[0];
2244 typename Node::Children::iterator it = node->children().find(firstChar);
2245
2246 if (it == node->children().end()) {
2247 typename Node::Children::iterator iter =
2248 node->children().emplace(firstChar, remainingKey).first;
2249 ChildNodeGuard guard(node, iter);
2250 iter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
2251 args_01),
2253 args_02),
2255 args_03),
2257 args_04),
2259 args_05),
2261 args_06),
2263 args_07),
2265 args_08),
2267 args_09));
2268 guard.release();
2269 return EmplaceResult(true, iter->second.value().value());
2270 }
2271
2272 Node& child = it->second;
2273 const bsl::string_view childPrefix = child.prefix();
2274
2275 size_type minLen = bsl::min(remainingKey.size(), childPrefix.size());
2276 const bsl::string_view::const_iterator mismatchPos =
2277 bsl::mismatch(remainingKey.begin(),
2278 remainingKey.begin() + minLen,
2279 childPrefix.begin())
2280 .first;
2281 const size_type commonLen = mismatchPos - remainingKey.begin();
2282
2283 if (commonLen == childPrefix.size()) {
2284 return emplaceImp(&child,
2285 remainingKey.substr(commonLen),
2286 BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
2287 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02),
2288 BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03),
2289 BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04),
2290 BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05),
2291 BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06),
2292 BSLS_COMPILERFEATURES_FORWARD(Args_07, args_07),
2293 BSLS_COMPILERFEATURES_FORWARD(Args_08, args_08),
2294 BSLS_COMPILERFEATURES_FORWARD(Args_09, args_09));
2295 }
2296
2297 Node splitNode(childPrefix.substr(0, commonLen), get_allocator());
2298
2299 Node childCopy(child, get_allocator());
2300 childCopy.prefix() = childPrefix.substr(commonLen);
2301
2302 splitNode.children().emplace(childCopy.prefix()[0],
2303 bslmf::MovableRefUtil::move(childCopy));
2304
2305 if (commonLen == remainingKey.size()) {
2306 splitNode.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
2307 args_01),
2309 args_02),
2311 args_03),
2313 args_04),
2315 args_05),
2317 args_06),
2319 args_07),
2321 args_08),
2323 args_09));
2324
2325 it->second = bslmf::MovableRefUtil::move(splitNode);
2326 return EmplaceResult(true,
2327 it->second.value().value());
2328 }
2329
2330 const bsl::string_view newKey = remainingKey.substr(commonLen);
2331 const typename Node::Children::iterator newIter =
2332 splitNode.children().emplace(newKey[0], newKey).first;
2333 newIter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
2334 args_01),
2336 args_02),
2338 args_03),
2340 args_04),
2342 args_05),
2344 args_06),
2346 args_07),
2348 args_08),
2350 args_09));
2351
2352 it->second = bslmf::MovableRefUtil::move(splitNode);
2353 return EmplaceResult(true, newIter->second.value().value());
2354}
2355#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 9
2356
2357#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 10
2358template <class t_VALUE>
2359template <class Args_01,
2360 class Args_02,
2361 class Args_03,
2362 class Args_04,
2363 class Args_05,
2364 class Args_06,
2365 class Args_07,
2366 class Args_08,
2367 class Args_09,
2368 class Args_10>
2369typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
2370CategoryManager_RadixTree<t_VALUE>::emplaceImp(
2371 Node *node,
2372 const bsl::string_view& remainingKey,
2373 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
2374 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
2375 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
2376 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
2377 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
2378 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06,
2379 BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07,
2380 BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08,
2381 BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) args_09,
2382 BSLS_COMPILERFEATURES_FORWARD_REF(Args_10) args_10)
2383{
2384 BSLS_ASSERT(node);
2385
2386 if (remainingKey.empty()) {
2387 if (node->value().has_value()) {
2388 return EmplaceResult(false, node->value().value());
2389 }
2390 node->value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
2391 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02),
2392 BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03),
2393 BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04),
2394 BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05),
2395 BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06),
2396 BSLS_COMPILERFEATURES_FORWARD(Args_07, args_07),
2397 BSLS_COMPILERFEATURES_FORWARD(Args_08, args_08),
2398 BSLS_COMPILERFEATURES_FORWARD(Args_09, args_09),
2399 BSLS_COMPILERFEATURES_FORWARD(Args_10, args_10));
2400 return EmplaceResult(true, node->value().value());
2401 }
2402
2403 const char firstChar = remainingKey[0];
2404 typename Node::Children::iterator it = node->children().find(firstChar);
2405
2406 if (it == node->children().end()) {
2407 typename Node::Children::iterator iter =
2408 node->children().emplace(firstChar, remainingKey).first;
2409 ChildNodeGuard guard(node, iter);
2410 iter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
2411 args_01),
2413 args_02),
2415 args_03),
2417 args_04),
2419 args_05),
2421 args_06),
2423 args_07),
2425 args_08),
2427 args_09),
2429 args_10));
2430 guard.release();
2431 return EmplaceResult(true, iter->second.value().value());
2432 }
2433
2434 Node& child = it->second;
2435 const bsl::string_view childPrefix = child.prefix();
2436
2437 size_type minLen = bsl::min(remainingKey.size(), childPrefix.size());
2438 const bsl::string_view::const_iterator mismatchPos =
2439 bsl::mismatch(remainingKey.begin(),
2440 remainingKey.begin() + minLen,
2441 childPrefix.begin())
2442 .first;
2443 const size_type commonLen = mismatchPos - remainingKey.begin();
2444
2445 if (commonLen == childPrefix.size()) {
2446 return emplaceImp(&child,
2447 remainingKey.substr(commonLen),
2448 BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01),
2449 BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02),
2450 BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03),
2451 BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04),
2452 BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05),
2453 BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06),
2454 BSLS_COMPILERFEATURES_FORWARD(Args_07, args_07),
2455 BSLS_COMPILERFEATURES_FORWARD(Args_08, args_08),
2456 BSLS_COMPILERFEATURES_FORWARD(Args_09, args_09),
2457 BSLS_COMPILERFEATURES_FORWARD(Args_10, args_10));
2458 }
2459
2460 Node splitNode(childPrefix.substr(0, commonLen), get_allocator());
2461
2462 Node childCopy(child, get_allocator());
2463 childCopy.prefix() = childPrefix.substr(commonLen);
2464
2465 splitNode.children().emplace(childCopy.prefix()[0],
2466 bslmf::MovableRefUtil::move(childCopy));
2467
2468 if (commonLen == remainingKey.size()) {
2469 splitNode.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
2470 args_01),
2472 args_02),
2474 args_03),
2476 args_04),
2478 args_05),
2480 args_06),
2482 args_07),
2484 args_08),
2486 args_09),
2488 args_10));
2489
2490 it->second = bslmf::MovableRefUtil::move(splitNode);
2491 return EmplaceResult(true,
2492 it->second.value().value());
2493 }
2494
2495 const bsl::string_view newKey = remainingKey.substr(commonLen);
2496 const typename Node::Children::iterator newIter =
2497 splitNode.children().emplace(newKey[0], newKey).first;
2498 newIter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01,
2499 args_01),
2501 args_02),
2503 args_03),
2505 args_04),
2507 args_05),
2509 args_06),
2511 args_07),
2513 args_08),
2515 args_09),
2517 args_10));
2518
2519 it->second = bslmf::MovableRefUtil::move(splitNode);
2520 return EmplaceResult(true, newIter->second.value().value());
2521}
2522#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 10
2523
2524#else
2525// The generated code below is a workaround for the absence of perfect
2526// forwarding in some compilers.
2527template <class t_VALUE>
2528template <class... Args>
2529typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
2530CategoryManager_RadixTree<t_VALUE>::emplaceImp(
2531 Node *node,
2532 const bsl::string_view& remainingKey,
2534{
2535 BSLS_ASSERT(node);
2536
2537 if (remainingKey.empty()) {
2538 if (node->value().has_value()) {
2539 return EmplaceResult(false, node->value().value());
2540 }
2541 node->value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args, args)...);
2542 return EmplaceResult(true, node->value().value());
2543 }
2544
2545 const char firstChar = remainingKey[0];
2546 typename Node::Children::iterator it = node->children().find(firstChar);
2547
2548 if (it == node->children().end()) {
2549 typename Node::Children::iterator iter =
2550 node->children().emplace(firstChar, remainingKey).first;
2551 ChildNodeGuard guard(node, iter);
2552 iter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args,
2553 args)...);
2554 guard.release();
2555 return EmplaceResult(true, iter->second.value().value());
2556 }
2557
2558 Node& child = it->second;
2559 const bsl::string_view childPrefix = child.prefix();
2560
2561 size_type minLen = bsl::min(remainingKey.size(), childPrefix.size());
2562 const bsl::string_view::const_iterator mismatchPos =
2563 bsl::mismatch(remainingKey.begin(),
2564 remainingKey.begin() + minLen,
2565 childPrefix.begin())
2566 .first;
2567 const size_type commonLen = mismatchPos - remainingKey.begin();
2568
2569 if (commonLen == childPrefix.size()) {
2570 return emplaceImp(&child,
2571 remainingKey.substr(commonLen),
2572 BSLS_COMPILERFEATURES_FORWARD(Args, args)...);
2573 }
2574
2575 Node splitNode(childPrefix.substr(0, commonLen), get_allocator());
2576
2577 Node childCopy(child, get_allocator());
2578 childCopy.prefix() = childPrefix.substr(commonLen);
2579
2580 splitNode.children().emplace(childCopy.prefix()[0],
2581 bslmf::MovableRefUtil::move(childCopy));
2582
2583 if (commonLen == remainingKey.size()) {
2584 splitNode.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args,
2585 args)...);
2586
2587 it->second = bslmf::MovableRefUtil::move(splitNode);
2588 return EmplaceResult(true,
2589 it->second.value().value());
2590 }
2591
2592 const bsl::string_view newKey = remainingKey.substr(commonLen);
2593 const typename Node::Children::iterator newIter =
2594 splitNode.children().emplace(newKey[0], newKey).first;
2595 newIter->second.value().emplace(BSLS_COMPILERFEATURES_FORWARD(Args,
2596 args)...);
2597
2598 it->second = bslmf::MovableRefUtil::move(splitNode);
2599 return EmplaceResult(true, newIter->second.value().value());
2600}
2601// }}} END GENERATED CODE
2602#endif
2603
2604template <class t_VALUE>
2605typename CategoryManager_RadixTree<t_VALUE>::size_type
2606CategoryManager_RadixTree<t_VALUE>::eraseAllChildren(
2607 typename CategoryManager_RadixTree<t_VALUE>::Node *node)
2608{
2609 BSLS_ASSERT(node);
2610
2611 size_type count = 0;
2612
2613 typedef typename Node::Children::iterator Iter;
2614 for (Iter it = node->children().begin();
2615 it != node->children().end(); ) {
2616 count += eraseAllChildren(&it->second);
2617 if (it->second.value().has_value()) {
2618 it->second.value().reset();
2619 --d_size;
2620 ++count;
2621 }
2622 it = node->children().erase(it);
2623 }
2624
2625 return count;
2626}
2627
2628template <class t_VALUE>
2629void CategoryManager_RadixTree<t_VALUE>::cleanupChildAfterErase(
2630 Node *node,
2631 typename Node::Children::iterator it,
2632 char firstChar)
2633{
2634 BSLS_ASSERT(node);
2635
2636 Node& child = it->second;
2637
2638 if (!child.value().has_value() && child.children().empty()) {
2639 // Remove child completely
2640 node->children().erase(it);
2641 }
2642 else if (!child.value().has_value() && child.children().size() == 1) {
2643 // Merge child with its single grandchild
2644 // Build merged node without modifying original, then commit atomically
2645 const typename Node::Children::iterator grandIt =
2646 child.children().begin();
2647 Node& grandchild = grandIt->second;
2648
2649 // Build new prefix (may throw - but original tree unchanged)
2650 bsl::string mergedPrefix(child.prefix() + grandchild.prefix(),
2651 get_allocator());
2652
2653 // Create merged node (may throw - but original tree unchanged)
2654 Node mergedNode(mergedPrefix, get_allocator());
2655 mergedNode.value() = bslmf::MovableRefUtil::move(grandchild.value());
2656 mergedNode.children() =
2657 bslmf::MovableRefUtil::move(grandchild.children());
2658
2659 // All operations succeeded - commit by replacing child in tree
2660 node->children().erase(it);
2661 node->children().emplace(firstChar,
2662 bslmf::MovableRefUtil::move(mergedNode));
2663 }
2664}
2665
2666template <class t_VALUE>
2667bool CategoryManager_RadixTree<t_VALUE>::eraseImp(
2668 Node *node,
2669 const bsl::string_view& remainingKey)
2670{
2671 BSLS_ASSERT(node);
2672
2673 if (remainingKey.empty()) {
2674 if (!node->value().has_value()) {
2675 return false; // RETURN
2676 }
2677 node->value().reset();
2678 return true; // RETURN
2679 }
2680
2681 const char firstChar = remainingKey[0];
2682 typename Node::Children::iterator it = node->children().find(firstChar);
2683
2684 if (it == node->children().end()) {
2685 return false; // RETURN
2686 }
2687
2688 Node& child = it->second;
2689 bsl::string_view childPrefix = child.prefix();
2690
2691 if (!remainingKey.starts_with(childPrefix)) {
2692 return false; // RETURN
2693 }
2694
2695 // Recurse into child
2696 const bool erased = eraseImp(&child,
2697 remainingKey.substr(childPrefix.size()));
2698
2699 if (!erased) {
2700 return false; // RETURN
2701 }
2702
2703 // Post-order cleanup: merge or remove child if needed
2704 cleanupChildAfterErase(node, it, firstChar);
2705
2706 return true;
2707}
2708
2709template <class t_VALUE>
2710typename CategoryManager_RadixTree<t_VALUE>::size_type
2711CategoryManager_RadixTree<t_VALUE>::erasePrefixImp(
2712 Node *node,
2713 const bsl::string_view& remainingPrefix)
2714{
2715 BSLS_ASSERT(node);
2716
2717 if (remainingPrefix.empty()) {
2718 // Found the prefix node - recursively count and remove this subtree
2719 size_type count = 0;
2720
2721 // Count and remove value at this node
2722 if (node->value().has_value()) {
2723 node->value().reset();
2724 --d_size;
2725 ++count;
2726 }
2727
2728 // Recursively count and remove all children
2729 typedef typename Node::Children::iterator Iter;
2730 for (Iter it = node->children().begin();
2731 it != node->children().end();
2732 ++it) {
2733 count += erasePrefixImp(&it->second, "");
2734 }
2735
2736 node->children().clear();
2737
2738 return count; // RETURN
2739 }
2740
2741 const char firstChar = remainingPrefix[0];
2742 const typename Node::Children::iterator it =
2743 node->children().find(firstChar);
2744
2745 if (it == node->children().end()) {
2746 return 0; // RETURN
2747 }
2748
2749 Node& child = it->second;
2750 const bsl::string_view childPrefix = child.prefix();
2751
2752 if (remainingPrefix.starts_with(childPrefix)) {
2753 // Prefix matches this child's prefix completely, recurse
2754 const size_type count =
2755 erasePrefixImp(&child,
2756 remainingPrefix.substr(childPrefix.size()));
2757
2758 // After recursion, clean up child if needed
2759 cleanupChildAfterErase(node, it, firstChar);
2760
2761 return count; // RETURN
2762 }
2763 else if (childPrefix.starts_with(remainingPrefix)) {
2764 // Child prefix starts with remaining prefix - remove entire child
2765 const size_type count = erasePrefixImp(&child, "");
2766 node->children().erase(it);
2767 return count; // RETURN
2768 }
2769
2770 return 0;
2771}
2772
2773// PRIVATE CLASS METHODS
2774template <class t_VALUE>
2775template <class t_FUNCTOR>
2776void
2777CategoryManager_RadixTree<t_VALUE>::forEachImp(
2778 const Node *node,
2779 const bsl::string_view& keyPrefix,
2780 const t_FUNCTOR& functor)
2781{
2782 // Design Note: No return value with a count because it would always be
2783 // `size()` as we always run on all nodes with values.
2784
2785 BSLS_ASSERT(node);
2786
2787 const bsl::string fullKey = keyPrefix + node->prefix();
2788
2789 // Call on `node` itself
2790 if (node->value().has_value()) {
2791 functor(fullKey, node->value().value());
2792 }
2793
2794 // Recursively handle the children
2795 typedef typename Node::Children::const_iterator ConstIter;
2796 for (ConstIter it = node->children().begin();
2797 it != node->children().end();
2798 ++it) {
2799 forEachImp(&it->second, fullKey, functor);
2800 }
2801}
2802
2803template <class t_VALUE>
2804template <class t_FUNCTOR>
2805void
2806CategoryManager_RadixTree<t_VALUE>::forEachImp(
2807 Node *node,
2808 const bsl::string_view& keyPrefix,
2809 const t_FUNCTOR& functor)
2810{
2811 // Design Note: No return value with a count because it would always be
2812 // `size()` as we always run on all nodes with values.
2813
2814 BSLS_ASSERT(node);
2815
2816 const bsl::string fullKey = keyPrefix + node->prefix();
2817
2818 // Call on `node` itself
2819 if (node->value().has_value()) {
2820 functor(fullKey, node->value().value());
2821 }
2822
2823 // Recursively handle the children
2824 typedef typename Node::Children::iterator Iter;
2825 for (Iter it = node->children().begin();
2826 it != node->children().end();
2827 ++it) {
2828 forEachImp(&it->second, fullKey, functor);
2829 }
2830}
2831
2832template <class t_VALUE>
2833template <class t_FUNCTOR>
2834typename CategoryManager_RadixTree<t_VALUE>::size_type
2835CategoryManager_RadixTree<t_VALUE>::forEachPrefixImp(
2836 Node *node,
2837 const bsl::string_view& key,
2838 const t_FUNCTOR& functor)
2839{
2840 BSLS_ASSERT(node);
2841
2842 size_type count = 0;
2843
2844 // Call on `node` itself
2845 if (node->value()) {
2846 functor(key, *node->value());
2847 ++count;
2848 }
2849
2850 // Recursively handle the children
2851 typedef typename Node::Children::iterator Iter;
2852 for (Iter it = node->children().begin();
2853 it != node->children().end();
2854 ++it) {
2855 const bsl::string nextKey = key + it->second.prefix();
2856 count += forEachPrefixImp(&it->second, nextKey, functor);
2857 }
2858
2859 return count;
2860}
2861
2862template <class t_VALUE>
2863template <class t_FUNCTOR>
2864typename CategoryManager_RadixTree<t_VALUE>::size_type
2865CategoryManager_RadixTree<t_VALUE>::forEachPrefixImp(
2866 const Node *node,
2867 const bsl::string_view& key,
2868 const t_FUNCTOR& functor)
2869{
2870 BSLS_ASSERT(node);
2871
2872 size_type count = 0;
2873
2874 // Call on `node` itself
2875 if (node->value()) {
2876 functor(key, *node->value());
2877 ++count;
2878 }
2879
2880 // Recursively handle the children
2881 typedef typename Node::Children::const_iterator Iter;
2882 for (Iter it = node->children().begin();
2883 it != node->children().end();
2884 ++it) {
2885 const bsl::string nextKey = key + it->second.prefix();
2886 count += forEachPrefixImp(&it->second, nextKey, functor);
2887 }
2888
2889 return count;
2890}
2891
2892template <class t_VALUE>
2893void
2894CategoryManager_RadixTree<t_VALUE>::printNodeImp(
2895 bsl::ostream& stream,
2896 int depth,
2897 const Node *node,
2898 const bsl::string& keyPrefix,
2899 int currLevel,
2900 int spacesPerLevel)
2901{
2902 BSLS_ASSERT(node);
2903
2904 const bool noFirstLineIndent = (currLevel < 0);
2905 const bool singleLineMode = (spacesPerLevel < 0);
2906
2907 const int absLevel = noFirstLineIndent ? -currLevel : currLevel;
2908 const int absSpacesPerLevel = singleLineMode
2909 ? -spacesPerLevel
2910 : spacesPerLevel;
2911
2912 if (!noFirstLineIndent) {
2913 stream << bsl::string(absLevel * absSpacesPerLevel, ' ');
2914 }
2915
2916 if (singleLineMode) {
2917 stream << '{' << depth << "} ";
2918 }
2919
2920 stream << '"' << keyPrefix << '"';
2921 if (node->value().has_value()) {
2922 stream << ": ";
2923 stream << node->value().value();
2924 }
2925 else {
2926 stream << ": **NO-VALUE**";
2927 }
2928
2929 stream << (singleLineMode ? ' ' : '\n');
2930
2931 const int nextLevel = absLevel + 1;
2932
2933 typedef typename Node::Children::const_iterator Iter;
2934 for (Iter it = node->children().begin();
2935 it != node->children().end();
2936 ++it) {
2937 printNodeImp(stream,
2938 depth + 1,
2939 &it->second,
2940 keyPrefix + it->second.prefix(),
2941 singleLineMode ? -nextLevel : nextLevel,
2942 spacesPerLevel);
2943 }
2944}
2945
2946// CREATORS
2947template <class t_VALUE>
2948inline
2949CategoryManager_RadixTree<t_VALUE>::CategoryManager_RadixTree()
2950: d_root("")
2951, d_size(0)
2952{
2953 // Notice that the root has the empty key, so if we add a value with an
2954 // empty key it will not make a child node, it'll be added to `d_root`.
2955}
2956
2957template <class t_VALUE>
2958inline
2959CategoryManager_RadixTree<t_VALUE>::CategoryManager_RadixTree(
2960 const allocator_type& allocator)
2961: d_root("", allocator)
2962, d_size(0)
2963{
2964 // Notice that the root has the empty key, so if we add a value with an
2965 // empty key it will not make a child node, it'll be added to `d_root`.
2966}
2967
2968template <class t_VALUE>
2969inline
2970CategoryManager_RadixTree<t_VALUE>::CategoryManager_RadixTree(
2971 const CategoryManager_RadixTree& original,
2972 const allocator_type& allocator)
2973: d_root(original.d_root, allocator)
2974, d_size(original.d_size)
2975{
2976}
2977
2978template <class t_VALUE>
2979inline
2980CategoryManager_RadixTree<t_VALUE>::CategoryManager_RadixTree(
2984 bslmf::MovableRefUtil::access(original).d_root)),
2986 bslmf::MovableRefUtil::access(original).d_size))
2987{
2988 bslmf::MovableRefUtil::access(original).d_size = 0;
2989}
2990
2991template <class t_VALUE>
2992inline
2993CategoryManager_RadixTree<t_VALUE>::CategoryManager_RadixTree(
2995 const allocator_type& allocator)
2996: d_root(bslmf::MovableRefUtil::move(
2997 bslmf::MovableRefUtil::access(original).d_root),
2998 allocator)
2999, d_size(bslmf::MovableRefUtil::move(
3000 bslmf::MovableRefUtil::access(original).d_size))
3001{
3002 if (bslmf::MovableRefUtil::access(original).get_allocator() == allocator) {
3003 bslmf::MovableRefUtil::access(original).d_size = 0;
3004 }
3005}
3006
3007// MANIPULATORS
3008template <class t_VALUE>
3009inline
3010CategoryManager_RadixTree<t_VALUE>&
3011CategoryManager_RadixTree<t_VALUE>::operator=(
3012 const CategoryManager_RadixTree& rhs)
3013{
3014 if (this != &rhs) {
3015 CategoryManager_RadixTree temp(rhs, get_allocator());
3016 swap(temp);
3017 }
3018 return *this;
3019}
3020
3021template <class t_VALUE>
3022inline
3023CategoryManager_RadixTree<t_VALUE>&
3024CategoryManager_RadixTree<t_VALUE>::operator=(
3026{
3027 CategoryManager_RadixTree& lvalue = rhs;
3028 if (this != &lvalue) {
3029 if (get_allocator() == lvalue.get_allocator()) {
3030 CategoryManager_RadixTree temp(bslmf::MovableRefUtil::move(rhs));
3031 swap(temp);
3032 }
3033 else {
3034 CategoryManager_RadixTree temp(bslmf::MovableRefUtil::move(rhs),
3035 get_allocator());
3036 swap(temp);
3037 }
3038 }
3039 return *this;
3040}
3041
3042#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
3043// {{{ BEGIN GENERATED CODE
3044// Command line: sim_cpp11_features.pl ball_categorymanager_radixtree.h
3045#ifndef BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT
3046#define BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT 10
3047#endif
3048#ifndef BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D
3049#define BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT
3050#endif
3051#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 0
3052template <class t_VALUE>
3053typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3054CategoryManager_RadixTree<t_VALUE>::emplace(const bsl::string_view& key)
3055{
3056 const EmplaceResult result = emplaceImp(&d_root,
3057 key);
3058 if (result.first) {
3059 ++d_size;
3060 }
3061 return result;
3062}
3063#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 0
3064
3065#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 1
3066template <class t_VALUE>
3067template <class Args_01>
3068typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3069CategoryManager_RadixTree<t_VALUE>::emplace(const bsl::string_view& key,
3070 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01)
3071{
3072 const EmplaceResult result = emplaceImp(&d_root,
3073 key,
3075 args_01));
3076 if (result.first) {
3077 ++d_size;
3078 }
3079 return result;
3080}
3081#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 1
3082
3083#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 2
3084template <class t_VALUE>
3085template <class Args_01,
3086 class Args_02>
3087typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3088CategoryManager_RadixTree<t_VALUE>::emplace(const bsl::string_view& key,
3089 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
3090 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02)
3091{
3092 const EmplaceResult result = emplaceImp(&d_root,
3093 key,
3095 args_01),
3097 args_02));
3098 if (result.first) {
3099 ++d_size;
3100 }
3101 return result;
3102}
3103#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 2
3104
3105#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 3
3106template <class t_VALUE>
3107template <class Args_01,
3108 class Args_02,
3109 class Args_03>
3110typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3111CategoryManager_RadixTree<t_VALUE>::emplace(const bsl::string_view& key,
3112 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
3113 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
3114 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03)
3115{
3116 const EmplaceResult result = emplaceImp(&d_root,
3117 key,
3119 args_01),
3121 args_02),
3123 args_03));
3124 if (result.first) {
3125 ++d_size;
3126 }
3127 return result;
3128}
3129#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 3
3130
3131#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 4
3132template <class t_VALUE>
3133template <class Args_01,
3134 class Args_02,
3135 class Args_03,
3136 class Args_04>
3137typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3138CategoryManager_RadixTree<t_VALUE>::emplace(const bsl::string_view& key,
3139 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
3140 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
3141 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
3142 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04)
3143{
3144 const EmplaceResult result = emplaceImp(&d_root,
3145 key,
3147 args_01),
3149 args_02),
3151 args_03),
3153 args_04));
3154 if (result.first) {
3155 ++d_size;
3156 }
3157 return result;
3158}
3159#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 4
3160
3161#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 5
3162template <class t_VALUE>
3163template <class Args_01,
3164 class Args_02,
3165 class Args_03,
3166 class Args_04,
3167 class Args_05>
3168typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3169CategoryManager_RadixTree<t_VALUE>::emplace(const bsl::string_view& key,
3170 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
3171 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
3172 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
3173 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
3174 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05)
3175{
3176 const EmplaceResult result = emplaceImp(&d_root,
3177 key,
3179 args_01),
3181 args_02),
3183 args_03),
3185 args_04),
3187 args_05));
3188 if (result.first) {
3189 ++d_size;
3190 }
3191 return result;
3192}
3193#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 5
3194
3195#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 6
3196template <class t_VALUE>
3197template <class Args_01,
3198 class Args_02,
3199 class Args_03,
3200 class Args_04,
3201 class Args_05,
3202 class Args_06>
3203typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3204CategoryManager_RadixTree<t_VALUE>::emplace(const bsl::string_view& key,
3205 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
3206 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
3207 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
3208 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
3209 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
3210 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06)
3211{
3212 const EmplaceResult result = emplaceImp(&d_root,
3213 key,
3215 args_01),
3217 args_02),
3219 args_03),
3221 args_04),
3223 args_05),
3225 args_06));
3226 if (result.first) {
3227 ++d_size;
3228 }
3229 return result;
3230}
3231#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 6
3232
3233#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 7
3234template <class t_VALUE>
3235template <class Args_01,
3236 class Args_02,
3237 class Args_03,
3238 class Args_04,
3239 class Args_05,
3240 class Args_06,
3241 class Args_07>
3242typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3243CategoryManager_RadixTree<t_VALUE>::emplace(const bsl::string_view& key,
3244 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
3245 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
3246 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
3247 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
3248 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
3249 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06,
3250 BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07)
3251{
3252 const EmplaceResult result = emplaceImp(&d_root,
3253 key,
3255 args_01),
3257 args_02),
3259 args_03),
3261 args_04),
3263 args_05),
3265 args_06),
3267 args_07));
3268 if (result.first) {
3269 ++d_size;
3270 }
3271 return result;
3272}
3273#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 7
3274
3275#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 8
3276template <class t_VALUE>
3277template <class Args_01,
3278 class Args_02,
3279 class Args_03,
3280 class Args_04,
3281 class Args_05,
3282 class Args_06,
3283 class Args_07,
3284 class Args_08>
3285typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3286CategoryManager_RadixTree<t_VALUE>::emplace(const bsl::string_view& key,
3287 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
3288 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
3289 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
3290 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
3291 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
3292 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06,
3293 BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07,
3294 BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08)
3295{
3296 const EmplaceResult result = emplaceImp(&d_root,
3297 key,
3299 args_01),
3301 args_02),
3303 args_03),
3305 args_04),
3307 args_05),
3309 args_06),
3311 args_07),
3313 args_08));
3314 if (result.first) {
3315 ++d_size;
3316 }
3317 return result;
3318}
3319#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 8
3320
3321#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 9
3322template <class t_VALUE>
3323template <class Args_01,
3324 class Args_02,
3325 class Args_03,
3326 class Args_04,
3327 class Args_05,
3328 class Args_06,
3329 class Args_07,
3330 class Args_08,
3331 class Args_09>
3332typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3333CategoryManager_RadixTree<t_VALUE>::emplace(const bsl::string_view& key,
3334 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
3335 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
3336 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
3337 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
3338 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
3339 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06,
3340 BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07,
3341 BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08,
3342 BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) args_09)
3343{
3344 const EmplaceResult result = emplaceImp(&d_root,
3345 key,
3347 args_01),
3349 args_02),
3351 args_03),
3353 args_04),
3355 args_05),
3357 args_06),
3359 args_07),
3361 args_08),
3363 args_09));
3364 if (result.first) {
3365 ++d_size;
3366 }
3367 return result;
3368}
3369#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 9
3370
3371#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 10
3372template <class t_VALUE>
3373template <class Args_01,
3374 class Args_02,
3375 class Args_03,
3376 class Args_04,
3377 class Args_05,
3378 class Args_06,
3379 class Args_07,
3380 class Args_08,
3381 class Args_09,
3382 class Args_10>
3383typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3384CategoryManager_RadixTree<t_VALUE>::emplace(const bsl::string_view& key,
3385 BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01,
3386 BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02,
3387 BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03,
3388 BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04,
3389 BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05,
3390 BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06,
3391 BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07,
3392 BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08,
3393 BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) args_09,
3394 BSLS_COMPILERFEATURES_FORWARD_REF(Args_10) args_10)
3395{
3396 const EmplaceResult result = emplaceImp(&d_root,
3397 key,
3399 args_01),
3401 args_02),
3403 args_03),
3405 args_04),
3407 args_05),
3409 args_06),
3411 args_07),
3413 args_08),
3415 args_09),
3417 args_10));
3418 if (result.first) {
3419 ++d_size;
3420 }
3421 return result;
3422}
3423#endif // BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 10
3424
3425#else
3426// The generated code below is a workaround for the absence of perfect
3427// forwarding in some compilers.
3428template <class t_VALUE>
3429template <class... Args>
3430typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3431CategoryManager_RadixTree<t_VALUE>::emplace(const bsl::string_view& key,
3433{
3434 const EmplaceResult result = emplaceImp(&d_root,
3435 key,
3437 args)...);
3438 if (result.first) {
3439 ++d_size;
3440 }
3441 return result;
3442}
3443// }}} END GENERATED CODE
3444#endif
3445
3446template <class t_VALUE>
3447inline
3448void CategoryManager_RadixTree<t_VALUE>::clear()
3449{
3450 d_root.children().clear();
3451 d_root.value().reset();
3452 d_size = 0;
3453}
3454
3455template <class t_VALUE>
3456bool CategoryManager_RadixTree<t_VALUE>::erase(const bsl::string_view& key)
3457{
3458 const bool erased = eraseImp(&d_root, key);
3459 if (erased) {
3460 --d_size;
3461 }
3462 return erased;
3463}
3464
3465template <class t_VALUE>
3466typename CategoryManager_RadixTree<t_VALUE>::size_type
3467CategoryManager_RadixTree<t_VALUE>::eraseChildrenOfPrefix(
3468 const bsl::string_view& prefix)
3469{
3470 Node *node = &d_root;
3471 size_type pos = 0;
3472
3473 while (pos < prefix.size()) {
3474 typedef typename Node::Children::iterator Iter;
3475
3476 Iter it = node->children().find(prefix[pos]);
3477 if (it == node->children().end()) {
3478 return 0; // RETURN
3479 }
3480
3481 Node &child = it->second;
3482 const bsl::string_view childPrefix = child.prefix();
3483 if (prefix.substr(pos, childPrefix.size()) == childPrefix) {
3484 node = &child;
3485 pos += childPrefix.size();
3486 } else {
3487 return 0; // RETURN
3488 }
3489 }
3490 // Now 'node' is the prefix node. Erase all its children, but not itself.
3491 return eraseAllChildren(node);
3492}
3493
3494template <class t_VALUE>
3495typename CategoryManager_RadixTree<t_VALUE>::size_type
3496CategoryManager_RadixTree<t_VALUE>::erasePrefix(const bsl::string_view& prefix)
3497{
3498 // Empty prefix is a prefix of all nodes, so we just quickly clear it out
3499 if (prefix.empty()) {
3500 const size_type oldSize = d_size;
3501 clear();
3502 return oldSize; // RETURN
3503 }
3504
3505 return erasePrefixImp(&d_root, prefix);
3506}
3507
3508template <class t_VALUE>
3509typename CategoryManager_RadixTree<t_VALUE>::OptValueRef
3510CategoryManager_RadixTree<t_VALUE>::find(const bsl::string_view& key)
3511{
3512 // Iterative implementation to avoid stack overflow
3513 Node *currentNode = &d_root;
3514 bsl::string_view remainingKey = key;
3515
3516 while (true) {
3517 if (remainingKey.empty()) {
3518 return currentNode->value().has_value()
3519 ? typename CategoryManager_RadixTree::OptValueRef(
3520 bsl::ref(currentNode->value().value()))
3521 : bsl::nullopt; // RETURN
3522 }
3523
3524 const typename Node::Children::iterator it =
3525 currentNode->children().find(remainingKey[0]);
3526
3527 if (it == currentNode->children().end()) {
3528 return bsl::nullopt; // RETURN
3529 }
3530
3531 Node& child = it->second;
3532 const bsl::string_view childPrefix = child.prefix();
3533
3534 // Check if key matches child prefix
3535 if (!remainingKey.starts_with(childPrefix)) {
3536 return bsl::nullopt; // RETURN
3537 }
3538
3539 remainingKey.remove_prefix(childPrefix.size());
3540 currentNode = &child;
3541 }
3542}
3543
3544template <class t_VALUE>
3545inline
3547CategoryManager_RadixTree<t_VALUE>::findLongestCommonPrefix(
3548 OptValueRef *value,
3549 const bsl::string_view& key)
3550{
3551 OptValueCRef constValue;
3552 const CategoryManager_RadixTree<t_VALUE>* constThis =
3553 const_cast<const CategoryManager_RadixTree*>(this);
3554 const bsl::string_view result =
3555 constThis->findLongestCommonPrefix(&constValue, key);
3556
3557 if (value) {
3558 if (constValue.has_value()) {
3559 *value = bsl::ref(const_cast<t_VALUE&>(constValue.value().get()));
3560 } else {
3561 *value = bsl::nullopt;
3562 }
3563 }
3564 return result;
3565}
3566
3567template <class t_VALUE>
3568template <class t_FUNCTOR>
3569void CategoryManager_RadixTree<t_VALUE>::forEach(const t_FUNCTOR& functor)
3570{
3571 if (d_size == 0) {
3572 return; // RETURN
3573 }
3574
3575 forEachImp(&d_root, "", functor);
3576}
3577
3578template <class t_VALUE>
3579template <class t_FUNCTOR>
3580typename CategoryManager_RadixTree<t_VALUE>::size_type
3581CategoryManager_RadixTree<t_VALUE>::forEachPrefix(
3582 const bsl::string_view& prefix,
3583 const t_FUNCTOR& functor)
3584{
3585 Node *node = &d_root;
3586 bsl::string keySoFar;
3587 size_type pos = 0;
3588 while (pos < prefix.size()) {
3589 bool found = false;
3590 typedef typename Node::Children::iterator Iter;
3591 for (Iter it = node->children().begin();
3592 it != node->children().end();
3593 ++it) {
3594 const Node& child = it->second;
3595 const bsl::string& childPrefix = child.prefix();
3596 size_type i = 0;
3597 while (i < childPrefix.size()
3598 && pos + i < prefix.size()
3599 && prefix[pos + i] == childPrefix[i]) {
3600 ++i;
3601 }
3602 if (i == childPrefix.size()) {
3603 // Full child prefix match, keep descending
3604 node = &it->second;
3605 keySoFar.append(childPrefix);
3606 pos += i;
3607 found = true;
3608 break; // BREAK
3609 } else if (i == prefix.size() - pos) {
3610 // Prefix matches the start of childPrefix, descend into child
3611 node = &it->second;
3612 keySoFar.append(childPrefix.substr(0, i));
3613 pos += i;
3614 found = true;
3615 // Now, apply functor to all descendants of this child
3616 return forEachPrefixImp(node, prefix, functor);
3617 }
3618 }
3619 if (!found) {
3620 node = 0;
3621 break; // BREAK
3622 }
3623 }
3624 if (!node) {
3625 return 0; // RETURN
3626 }
3627 return forEachPrefixImp(node, prefix.substr(0, keySoFar.size()), functor);
3628}
3629
3630template <class t_VALUE>
3631inline
3632void CategoryManager_RadixTree<t_VALUE>::swap(CategoryManager_RadixTree& other)
3633{
3634 BSLS_ASSERT(get_allocator() == other.get_allocator());
3635
3636 bslalg::SwapUtil::swap(&d_root, &other.d_root);
3637 bslalg::SwapUtil::swap(&d_size, &other.d_size);
3638}
3639
3640// ACCESSORS
3641template <class t_VALUE>
3642inline
3643bool CategoryManager_RadixTree<t_VALUE>::contains(
3644 const bsl::string_view& key) const
3645{
3646 // Iterative implementation to avoid stack overflow
3647 const Node *currentNode = &d_root;
3648 bsl::string_view remainingKey = key;
3649
3650 while (true) {
3651 if (remainingKey.empty()) {
3652 return currentNode->value().has_value(); // RETURN
3653 }
3654
3655 const typename Node::Children::const_iterator it =
3656 currentNode->children().find(remainingKey[0]);
3657
3658 if (it == currentNode->children().end()) {
3659 return false; // RETURN
3660 }
3661
3662 const Node& child = it->second;
3663 const bsl::string_view childPrefix = child.prefix();
3664
3665 // Check if key matches child prefix
3666 if (!remainingKey.starts_with(childPrefix)) {
3667 return false; // RETURN
3668 }
3669
3670 remainingKey.remove_prefix(childPrefix.size());
3671 currentNode = &child;
3672 }
3673}
3674
3675template <class t_VALUE>
3676typename CategoryManager_RadixTree<t_VALUE>::size_type
3677CategoryManager_RadixTree<t_VALUE>::countNodes() const
3678{
3679 size_type count = 1; // count root node
3680
3681 // Recursively count all child nodes
3682 typedef typename Node::Children::const_iterator Iter;
3683 for (Iter it = d_root.children().begin();
3684 it != d_root.children().end();
3685 ++it) {
3686 // Count this child node
3687 ++count;
3688
3689 // Recursively count all descendants of this child
3691 stack.push_back(&it->second);
3692
3693 while (!stack.empty()) {
3694 const Node* node = stack.back();
3695 stack.pop_back();
3696
3697 for (Iter childIt = node->children().begin();
3698 childIt != node->children().end();
3699 ++childIt) {
3700 ++count;
3701 stack.push_back(&childIt->second);
3702 }
3703 }
3704 }
3705
3706 return count;
3707}
3708
3709template <class t_VALUE>
3710inline
3711bool CategoryManager_RadixTree<t_VALUE>::empty() const
3712{
3713 return 0 == d_size;
3714}
3715
3716template <class t_VALUE>
3717typename CategoryManager_RadixTree<t_VALUE>::OptValueCRef
3718CategoryManager_RadixTree<t_VALUE>::find(const bsl::string_view& key) const
3719{
3720 // Iterative implementation to avoid stack overflow
3721 const Node *currentNode = &d_root;
3722 bsl::string_view remainingKey = key;
3723
3724 while (true) {
3725 if (remainingKey.empty()) {
3726 return currentNode->value().has_value()
3727 ? typename CategoryManager_RadixTree::OptValueCRef(
3728 bsl::cref(currentNode->value().value()))
3729 : bsl::nullopt; // RETURN
3730 }
3731
3732 const typename Node::Children::const_iterator it =
3733 currentNode->children().find(remainingKey[0]);
3734
3735 if (it == currentNode->children().end()) {
3736 return bsl::nullopt; // RETURN
3737 }
3738
3739 const Node& child = it->second;
3740 const bsl::string_view childPrefix = child.prefix();
3741
3742 // Check if key matches child prefix
3743 if (!remainingKey.starts_with(childPrefix)) {
3744 return bsl::nullopt; // RETURN
3745 }
3746
3747 remainingKey.remove_prefix(childPrefix.size());
3748 currentNode = &child;
3749 }
3750}
3751
3752template <class t_VALUE>
3753inline
3754bsl::string_view CategoryManager_RadixTree<t_VALUE>::findLongestCommonPrefix(
3755 OptValueCRef *value,
3756 const bsl::string_view& key) const
3757
3758{
3759 const Node *node = &d_root;
3760 size_type matched = 0;
3761 size_type pos = 0;
3762 size_type lastMatchedLength = 0;
3763 OptValueCRef lastValueRef = bsl::nullopt;
3764
3765 // Handle the case where the root node has a value (empty-string key)
3766 if (node->value().has_value()) {
3767 lastMatchedLength = 0;
3768 lastValueRef = bsl::cref(node->value().value());
3769 }
3770
3771 while (pos < key.size()) {
3772 typedef typename Node::Children::const_iterator Iter;
3773 const Iter it = node->children().find(key[pos]);
3774 if (it == node->children().end()) {
3775 break; // BREAK
3776 }
3777 const Node& child = it->second;
3778 const bsl::string& childPrefix = child.prefix();
3779 size_type i = 0;
3780 while (i < childPrefix.size()
3781 && pos + i < key.size()
3782 && key[pos + i] == childPrefix[i]) {
3783 ++i;
3784 }
3785 // Defensive: if no progress is made, break to avoid infinite loop
3786 if (i == 0) {
3787 // No characters matched in prefix, cannot advance
3788 break; // BREAK
3789 }
3790 if (i < childPrefix.size()) {
3791 // Partial match, stop here
3792 break; // BREAK
3793 }
3794 // Full prefix match
3795 matched += i;
3796 pos += i;
3797 node = &child;
3798 if (node->value().has_value()) {
3799 lastMatchedLength = matched;
3800 lastValueRef = bsl::cref(node->value().value());
3801 }
3802 }
3803 if (value) {
3804 *value = lastValueRef;
3805 }
3806 return key.substr(0, lastMatchedLength);
3807}
3808
3809template <class t_VALUE>
3810template <class t_FUNCTOR>
3811void
3812CategoryManager_RadixTree<t_VALUE>::forEach(const t_FUNCTOR& functor) const
3813{
3814 if (d_size == 0) {
3815 return; // RETURN
3816 }
3817
3818 forEachImp(&d_root, "", functor);
3819}
3820
3821template <class t_VALUE>
3822template <class t_FUNCTOR>
3823typename CategoryManager_RadixTree<t_VALUE>::size_type
3824CategoryManager_RadixTree<t_VALUE>::forEachPrefix(
3825 const bsl::string_view& prefix,
3826 const t_FUNCTOR& functor) const
3827{
3828 const Node *node = &d_root;
3829 bsl::string keySoFar;
3830 size_type pos = 0;
3831
3832 while (pos < prefix.size()) {
3833 bool found = false;
3834 typedef typename Node::Children::const_iterator Iter;
3835 for (Iter it = node->children().begin();
3836 it != node->children().end();
3837 ++it) {
3838 const Node& child = it->second;
3839 const bsl::string& childPrefix = child.prefix();
3840 size_type i = 0;
3841 while (i < childPrefix.size()
3842 && pos + i < prefix.size()
3843 && prefix[pos + i] == childPrefix[i]) {
3844 ++i;
3845 }
3846 if (i == childPrefix.size()) {
3847 // Full child prefix match, keep descending
3848 node = &it->second;
3849 keySoFar.append(childPrefix);
3850 pos += i;
3851 found = true;
3852 break; // BREAK
3853 } else if (i == prefix.size() - pos) {
3854 // Prefix matches the start of childPrefix, descend into child
3855 node = &it->second;
3856 keySoFar.append(childPrefix.substr(0, i));
3857 pos += i;
3858 found = true;
3859 // Now, apply functor to all descendants of this child
3860 return forEachPrefixImp(node, prefix, functor);
3861 }
3862 }
3863 if (!found) {
3864 node = 0;
3865 break; // BREAK
3866 }
3867 }
3868 if (!node) {
3869 return 0; // RETURN
3870 }
3871 return forEachPrefixImp(node, prefix.substr(0, keySoFar.size()), functor);
3872}
3873
3874template <class t_VALUE>
3875bsl::ostream& CategoryManager_RadixTree<t_VALUE>::printNodes(
3876 bsl::ostream& stream,
3877 int level,
3878 int spacesPerLevel) const
3879{
3880 printNodeImp(stream, 0, &d_root, "", level, spacesPerLevel);
3881 return stream;
3882}
3883
3884template <class t_VALUE>
3885inline
3886typename CategoryManager_RadixTree<t_VALUE>::size_type
3887CategoryManager_RadixTree<t_VALUE>::size() const
3888{
3889 return d_size;
3890}
3891
3892 // Aspects
3893
3894template <class t_VALUE>
3895inline
3896typename CategoryManager_RadixTree<t_VALUE>::allocator_type
3897CategoryManager_RadixTree<t_VALUE>::get_allocator() const
3898{
3899 return d_root.children().get_allocator();
3900}
3901
3902} // close package namespace
3903
3904 // ------------------------------------
3905 // class CategoryManager_RadixTree_Node
3906 // ------------------------------------
3907
3908// FREE OPERATORS
3909template <class t_VALUE>
3910bool ball::operator==(const CategoryManager_RadixTree_Node<t_VALUE>& lhs,
3911 const CategoryManager_RadixTree_Node<t_VALUE>& rhs)
3912{
3913 return lhs.prefix() == rhs.prefix()
3914 && lhs.value() == rhs.value()
3915 && lhs.children() == rhs.children();
3916}
3917
3918template <class t_VALUE>
3919inline
3920bool ball::operator!=(const CategoryManager_RadixTree_Node<t_VALUE>& lhs,
3921 const CategoryManager_RadixTree_Node<t_VALUE>& rhs)
3922{
3923 return !(lhs == rhs);
3924}
3925
3926 // -------------------------------
3927 // class CategoryManager_RadixTree
3928 // -------------------------------
3929
3930// FREE OPERATORS
3931
3932template <class t_VALUE>
3933bool ball::operator==(const CategoryManager_RadixTree<t_VALUE>& lhs,
3934 const CategoryManager_RadixTree<t_VALUE>& rhs)
3935{
3936 if (lhs.d_size != rhs.d_size) {
3937 return false; // RETURN
3938 }
3939
3940 // Since the radix tree is always in its most compact form, two equal
3941 // trees will have identical structure. Use direct node comparison.
3942 return lhs.d_root == rhs.d_root;
3943}
3944
3945template <class t_VALUE>
3946inline
3947bool ball::operator!=(const CategoryManager_RadixTree<t_VALUE>& lhs,
3948 const CategoryManager_RadixTree<t_VALUE>& rhs)
3949{
3950 return !(lhs == rhs);
3951}
3952
3953// FREE FUNCTIONS
3954template <class t_VALUE>
3955inline
3956void ball::swap(CategoryManager_RadixTree<t_VALUE>& a,
3957 CategoryManager_RadixTree<t_VALUE>& b)
3958{
3959 bslalg::SwapUtil::swap(&a.d_root, &b.d_root);
3960 bslalg::SwapUtil::swap(&a.d_size, &b.d_size);
3961}
3962
3963
3964#else // if ! defined(DEFINED_BALL_CATEGORYMANAGER_RADIXTREE_H)
3965# error Not valid except when included from ball_categorymanager_radixtree.h
3966#endif // ! defined(COMPILING_BALL_CATEGORYMANAGER_RADIXTREE_H)
3967
3968#endif // ! defined(INCLUDED_BALL_CATEGORYMANAGER_RADIXTREE_CPP03)
3969
3970// ----------------------------------------------------------------------------
3971// Copyright 2025 Bloomberg Finance L.P.
3972//
3973// Licensed under the Apache License, Version 2.0 (the "License");
3974// you may not use this file except in compliance with the License.
3975// You may obtain a copy of the License at
3976//
3977// http://www.apache.org/licenses/LICENSE-2.0
3978//
3979// Unless required by applicable law or agreed to in writing, software
3980// distributed under the License is distributed on an "AS IS" BASIS,
3981// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3982// See the License for the specific language governing permissions and
3983// limitations under the License.
3984// ----------------------------- END-OF-FILE ----------------------------------
3985
3986/** @} */
3987/** @} */
3988/** @} */
void release()
Definition ball_categorymanager_radixtree.h:862
~CategoryManager_RadixTree_ChildNodeGuard()
Definition ball_categorymanager_radixtree.h:852
Node::Children::iterator ChildIterator
Definition ball_categorymanager_radixtree.h:384
CategoryManager_RadixTree_Node< t_VALUE > Node
Definition ball_categorymanager_radixtree.h:383
void swap(CategoryManager_RadixTree_Node &other)
Definition ball_categorymanager_radixtree.h:990
bsl::allocator allocator_type
Definition ball_categorymanager_radixtree.h:251
Children & children()
Definition ball_categorymanager_radixtree.h:976
bsl::optional< t_VALUE > & value()
Definition ball_categorymanager_radixtree.h:1002
bsl::map< char, CategoryManager_RadixTree_Node > Children
Definition ball_categorymanager_radixtree.h:237
allocator_type get_allocator() const
Return the allocator used by this object to supply memory.
Definition ball_categorymanager_radixtree.h:1036
CategoryManager_RadixTree_Node(const bsl::string_view &prefix, const allocator_type &allocator=allocator_type())
Definition ball_categorymanager_radixtree.h:874
bsl::string & prefix()
Definition ball_categorymanager_radixtree.h:983
CategoryManager_RadixTree_Node & operator=(const CategoryManager_RadixTree_Node &rhs)
Definition ball_categorymanager_radixtree.h:941
size_type eraseChildrenOfPrefix(const bsl::string_view &prefix)
Definition ball_categorymanager_radixtree.h:1611
~CategoryManager_RadixTree()=default
Destroy this object.
OptValueRef find(const bsl::string_view &key)
Definition ball_categorymanager_radixtree.h:1654
bsl::optional< bsl::reference_wrapper< t_VALUE > > OptValueRef
Definition ball_categorymanager_radixtree.h:443
bsl::ostream & printNodes(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
Definition ball_categorymanager_radixtree.h:2019
bool empty() const
Return true if this tree contains no entries, and false otherwise.
Definition ball_categorymanager_radixtree.h:1855
bsl::size_t size_type
Definition ball_categorymanager_radixtree.h:439
bsl::optional< bsl::reference_wrapper< const t_VALUE > > OptValueCRef
Definition ball_categorymanager_radixtree.h:447
bsl::pair< bool, bsl::reference_wrapper< t_VALUE > > EmplaceResult
Definition ball_categorymanager_radixtree.h:457
t_VALUE value_type
Definition ball_categorymanager_radixtree.h:438
friend void swap(CategoryManager_RadixTree< t_TYPE > &a, CategoryManager_RadixTree< t_TYPE > &b)
allocator_type get_allocator() const
Definition ball_categorymanager_radixtree.h:2041
void forEach(const t_FUNCTOR &functor)
Definition ball_categorymanager_radixtree.h:1713
void clear()
Definition ball_categorymanager_radixtree.h:1592
friend bool operator==(const CategoryManager_RadixTree< t_TYPE > &, const CategoryManager_RadixTree< t_TYPE > &)
CategoryManager_RadixTree & operator=(const CategoryManager_RadixTree &rhs)
Definition ball_categorymanager_radixtree.h:1542
size_type forEachPrefix(const bsl::string_view &prefix, const t_FUNCTOR &functor)
Definition ball_categorymanager_radixtree.h:1725
EmplaceResult emplace(const bsl::string_view &key, Args &&... args)
Definition ball_categorymanager_radixtree.h:1577
bsl::allocator allocator_type
Definition ball_categorymanager_radixtree.h:437
size_type erasePrefix(const bsl::string_view &prefix)
Definition ball_categorymanager_radixtree.h:1640
size_type countNodes() const
Definition ball_categorymanager_radixtree.h:1821
bsl::string_view findLongestCommonPrefix(OptValueRef *value, const bsl::string_view &key)
Definition ball_categorymanager_radixtree.h:1691
CategoryManager_RadixTree()
Definition ball_categorymanager_radixtree.h:1480
bool erase(const bsl::string_view &key)
Definition ball_categorymanager_radixtree.h:1600
bool contains(const bsl::string_view &key) const
Definition ball_categorymanager_radixtree.h:1787
size_type size() const
Return the number of entries in this tree.
Definition ball_categorymanager_radixtree.h:2031
Definition bslma_bslallocator.h:588
Definition bslstl_stringview.h:471
BSLS_KEYWORD_CONSTEXPR_CPP14 size_type find(basic_string_view subview, size_type position=0) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stringview.h:2284
BSLS_KEYWORD_CONSTEXPR_CPP17 bool starts_with(basic_string_view subview) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stringview.h:2215
BSLS_KEYWORD_CONSTEXPR_CPP14 basic_string_view substr(size_type position=0, size_type numChars=npos) const
Definition bslstl_stringview.h:2027
BSLS_KEYWORD_CONSTEXPR size_type size() const BSLS_KEYWORD_NOEXCEPT
Return the length of this view.
Definition bslstl_stringview.h:1904
const value_type * const_iterator
Definition bslstl_stringview.h:481
BSLS_KEYWORD_CONSTEXPR const_iterator begin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stringview.h:1830
BSLS_KEYWORD_CONSTEXPR_CPP14 void remove_prefix(size_type numChars)
Definition bslstl_stringview.h:1800
BSLS_KEYWORD_CONSTEXPR bool empty() const BSLS_KEYWORD_NOEXCEPT
Return true if this view has length 0, and false otherwise.
Definition bslstl_stringview.h:1931
Definition bslstl_string.h:1252
basic_string substr(size_type position=0, size_type numChars=npos) const
Definition bslstl_string.h:8013
size_type size() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7292
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Return the allocator used by this string to supply memory.
Definition bslstl_string.h:7423
basic_string & append(const basic_string &suffix)
Definition bslstl_string.h:6188
Definition bslstl_map.h:653
Definition bslstl_optional.h:2043
Definition bslstl_pair.h:1280
reference back()
Definition bslstl_vector.h:2932
bool empty() const BSLS_KEYWORD_NOEXCEPT
Return true if this vector has size 0, and false otherwise.
Definition bslstl_vector.h:3034
Definition bslstl_vector.h:1120
void push_back(const VALUE_TYPE &value)
Definition bslstl_vector.h:4343
void pop_back()
Definition bslstl_vector.h:4375
Definition bslalg_constructorproxy.h:376
static void swap(T *a, T *b)
Definition bslalg_swaputil.h:182
Definition bslmf_movableref.h:752
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2343
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2349
#define BSLS_KEYWORD_DELETED
Definition bsls_keyword.h:651
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:674
bool operator!=(const FileCleanerConfiguration &lhs, const FileCleanerConfiguration &rhs)
bool operator==(const FileCleanerConfiguration &lhs, const FileCleanerConfiguration &rhs)
void swap(OptionValue &a, OptionValue &b)
Definition ball_administration.h:214
void swap(CategoryManager_RadixTree< t_VALUE > &a, CategoryManager_RadixTree< t_VALUE > &b)
bool operator!=(const Attribute &lhs, const Attribute &rhs)
bool operator==(const Attribute &lhs, const Attribute &rhs)
Definition bdlat_valuetypefunctions.h:939
const nullopt_t nullopt
reference_wrapper< const T > cref(const T &object)
reference_wrapper< T > ref(T &object)
Return a reference wrapper that represents the specified object.
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
ALLOCATOR & lhs
Definition bslstl_string.h:3917
basic_string< char > string
Definition bslstl_string.h:844
Definition bdlbb_blob.h:579
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1067
static t_TYPE & access(t_TYPE &ref) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1039