ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
stringtreebase.inl
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_containers of the \aliblong.
4///
5/// \emoji :copyright: 2013-2025 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
9
10/// Base struct of \alib{containers;StringTree} providing internals.
11/// \note
12/// The separation of the internals of class \b StringTree to this type in namespace \b detail
13/// has no benefit on compilation speed or other positive "technical" effect, nor is it a matter
14/// of software design.<br>
15/// A user of derived class \alib{containers;HashTable} finds all interface methods and types
16/// in one place, which is not cluttered by the documentation of the internals found here.
17/// Otherwise, the separation is exclusively supporting source code organization.
18///
19/// @see For a description of the template parameters and a general introduction to the topic,
20/// se the reference documentation of the derived main class
21/// \alib{containers;StringTree}.
22template<typename TAllocator, typename T, typename TNodeHandler, Recycling TRecycling>
24{
25 //################################################################################################
26 // Inner types
27 //################################################################################################
28 struct NodeBase; // forward declaration
29 struct Node; // forward declaration
30
31 /// Alias shortcut for a bidirectional list of \b Node elements.
33
34 /// The character type of node names and paths strings. This is defined using character type
35 /// definition \alib{containers::StringTreeNamesDynamic;CharacterType} of template type
36 /// \p{TNodeHandler}.
37 using CharacterType = typename TNodeHandler::CharacterType;
38
39 /// The string-type of node names and paths if provided externally for comparison.
41
42 /// The string-type of node names and paths. This is defined by
43 /// \alib{containers::StringTreeNamesDynamic;NameStringType} of template type \p{TNodeHandler}.
44 using NameStorageType = typename TNodeHandler::NameStringType;
45
46 /// The substring-type of paths. This is defined using character type definition
47 /// \alib{containers::StringTreeNamesDynamic;CharacterType} of template type \p{TNodeHandler}.
49
50 /// The unique key to any element stored in this container.
51 /// By being a (second) base type for of type \alib{containers::detail::StringTreeBase;Node}, any
52 /// node includes this key.
53 struct NodeKey
54 {
55 /// The parent node. A value of \c nullptr indicates that this is the root node of
56 /// the tree, which is always existing.
58
59 /// A union of base string and the derived (or same) final storage type. Only the node
60 /// handler will finalize the name into the second field.
62 {
63 /// Constructor taking a key string. @param n The name of the node.
64 explicit NodeNameUnion(const NameType& n) : key(n) {}
65
66 /// Copy constructor. @param n The union to copy.
67 explicit NodeNameUnion(const NodeNameUnion& n) : key(n.key) {}
68
69 /// Destructor.
71
72 NameType key; ///< The name to compare when just keys are used.
73 NameStorageType storage; ///< The name when stored in the hashtable
74 };
75
76 /// A string object containing the pointer to this node's name.
77 /// Node names constitute path strings and, together with the pointer to their parent, form
78 /// the key of the hash set found with field \alib{containers::detail::StringTreeBase;nodeTable}.
79 /// <br>
80 /// Node names must not contain the separator character and must not equal to <c>"."</c> or
81 /// <c>".."</c>.
82 ///
83 /// The name of the root node is nulled.
85
86 /// Constructor
87 /// @param pParent Parent node to search a child for.
88 /// @param pName Child name to search
89 NodeKey( NodeBase* pParent, const NameType& pName )
90 : parent(pParent)
91 , name( pName ) {}
92
93 /// Hash functor for nodes hashed in field #nodeTable.
94 struct Hash
95 {
96 /// Calculates a hash code for \b NodeKey objects.
97 /// @param key The key to hash.
98 /// @return The hash code.
99 std::size_t operator()(const NodeKey& key) const {
100 return key.name.key.Hashcode()
101 + reinterpret_cast<std::size_t>(key.parent) * 29;
102 }
103 };
104
105 /// Equality functor for nodes in field #nodeTable.
106 struct EqualTo
107 {
108 /// Invokes \alib{strings;TString::Equals;String::Equals} on \p{lhs}, passing \p{rhs}
109 /// and returns the result.
110 /// @param lhs The first string object.
111 /// @param rhs The second string object.
112 /// @return The result of the string comparison.
113 bool operator()(const NodeKey& lhs,
114 const NodeKey& rhs ) const
115 {
116 return lhs.parent == rhs.parent
117 && lhs.name.key. template Equals<NC>( rhs.name.key );
118 }
119 };
120
121 /// ValueDescriptor for hash table #nodeTable.
123 {
124 /// Casts given \p{src} down to its base class
125 /// \alib{containers::detail::StringTreeBase;NodeKey}.
126 /// @param src The node to receive the key-portion for.
127 /// @return The key-portion of the node.
128 NodeKey& Key( NodeBase& src ) const { return static_cast<NodeKey&>( src ); }
129 };
130 };
131
132 /// This is the base class of the internal node type \alib{containers::detail::StringTreeBase;Node}.
133 /// This type implements functionality needed. Derived type \b Node then only adds the custom
134 /// value \p{T}.
135 ///
136 /// Objects of this type cannot be received directly and all interface is available
137 /// via public type \alib{containers;StringTree::Cursor} only, which holds a pointer to
138 /// an object of this class.
140 public NodeKey
141 {
142 /// The number of children currently stored in this node.
144
145 /// The hook to the doubly linked list of children.
147
148 /// Constructor.
149 /// @param pKey The key portion of the node.
150 NodeBase(const NodeKey& pKey)
151 : NodeKey ( pKey )
152 , qtyChildren(0) {}
153
154 /// Constructor. Custom data is default-initialized.
155 /// @param pParent Parent node to search a child for.
156 /// @param pName Child name to search
157 NodeBase( NodeBase* pParent, const NameType& pName)
158 : NodeKey ( pParent, pName )
159 , qtyChildren(0) {}
160
161 /// Returns \c true if this is the root node, \c false otherwise.
162 /// @return \c true if this is the root node, \c false otherwise.
163 bool isRoot() const { return NodeKey::parent == nullptr; }
164
165 /// Searches a child with a given name.
166 /// The name is not checked for <c>.</c>, <c>..</c> or if separation characters.
167 ///
168 /// @param tree The tree this node belongs to.
169 /// @param childName The name of the child to search.
170 /// @return The child or \c nullptr if not found.
171 NodeBase* findChild( StringTreeBase* tree, const NameType& childName ) {
172 if( qtyChildren == 0 )
173 return nullptr;
174
175 // With a small number of children, the search is faster if we iterate, because
176 // a) no hash value has to be calculated and
177 // b) the string compare is fast, at least if string have different length or are
178 // different at the beginning.
179 // A good value is probably five children. With bigger numbers, it soon becomes better
180 // to calculate the hash value. While in the bucket also children of other nodes
181 // are found, each entry of the hashtable is first compared against the full hash code.
182 if( qtyChildren <= 5 ) {
183 NodeBase* childIt= children.first();
184 while( childIt != &children.hook ) {
185 if( childIt->name.key. template Equals<NC>( childName ) )
186 return childIt;
187 childIt= childIt->next();
188 }
189
190 return nullptr;
191 }
192
193 // search in hash table
194 auto childIt= tree->nodeTable.Find( NodeKey( this, childName ) );
195 return childIt != tree->nodeTable.end() ? &childIt.Value()
196 : nullptr;
197 }
198
199 /// Iterates over the parent nodes to the root node and returns this node's depth.
200 /// @return The depth of this node.
201 int depth() const {
202 int result= -1;
203 const NodeBase* p= this;
204 while( p != nullptr ) {
205 ++result;
206 p= p->parent;
207 }
208 return result;
209 }
210
211 /// Iterates over the parent nodes and searches given \p{other} in the path.
212 /// @param other The node to calculate the distance to.
213 /// @return The distance of \p{other} to this node.
214 /// \c 0 if the nodes are the same.
215 /// \c -1 if \p{other} was not found.
216 int distance( const NodeBase* other ) const {
217 int result= 0;
218 const NodeBase* p= this;
219 while( p != nullptr ) {
220 if( p == other )
221 return result;
222 ++result;
223 p= p->parent;
224 }
225 return -1;
226 }
227
228 /// Searches a child with a given name, if not found, one is created.
229 /// The name is not checked for <c>.</c>, <c>..</c> or if separation characters.
230 ///
231 /// @tparam TArgs Types of variadic parameters given with parameter \p{args}.
232 /// @param tree The tree this node belongs to.
233 /// @param childName The name of the child to search.
234 /// @param args Variadic parameters to be forwarded to the constructor of custom type
235 /// \p{T} in the case a child is created.
236 /// @return A pair containing an iterator referencing either the element found or the new
237 /// element added.
238 /// The bool component is \c true if the insertion took place and \c false nothing
239 /// was changed.
240 template<typename... TArgs>
241 std::pair<NodeBase*,bool> findOrCreateChild( StringTreeBase* tree,
242 const NameType& childName,
243 TArgs&&... args ) {
244 auto childCreation= tree->nodeTable.EmplaceIfNotExistent( NodeKey(this, childName),
245 std::forward<TArgs>(args)...);
246 NodeBase* child= &childCreation.first.Value();
247
248 if( childCreation.second ) {
249 TNodeHandler::InitializeNode( *static_cast<Node*>(child), *tree );
250 children.pushEnd( child );
251 ++qtyChildren;
252 }
253
254 return std::make_pair( child, childCreation.second );
255 }
256
257 /// Deletes a given child node.
258 /// \note
259 /// If the given node is not a child of this node, the behavior is undefined.
260 /// With debug-builds, in this case an \alib_assertion is raised.
261 ///
262 /// @param tree The tree this node belongs to.
263 /// @param child A pointer to a child of this node that is to be deleted.
264 /// @return The total number of nodes deleted.
267 "STRINGTREE", "This node has no children to remove")
268 ALIB_ASSERT_ERROR( child->parent == this,
269 "STRINGTREE", "The given node is not a child of this node.")
270
271 --qtyChildren;
272 child->remove(); // remove from linked list
273 auto count= child->deleteChildren( tree );
274 auto handle= tree->nodeTable.Extract( *child );
275 ALIB_ASSERT( !handle.IsEmpty(), "STRINGTREE" )
276 TNodeHandler::FreeNode( handle.Value(), *tree );
277
278 return count + 1;
279 }
280
281 /// Deletes all child nodes.
282 /// @param tree The tree this node belongs to.
283 /// @return The number of children that were deleted.
285 if( children.isEmpty() )
286 return 0;
287
289
290 auto* child= children.first();
291 while( child != &children.hook ) {
292 count+= child->deleteChildren( tree ); // recursion
293 auto handle= tree->nodeTable.Extract( *child ); ALIB_ASSERT( !handle.IsEmpty(), "STRINGTREE")
294 TNodeHandler::FreeNode( handle.Value(), *tree );
295 child= child->next();
296 --qtyChildren;
297 }
298
299 ALIB_ASSERT(qtyChildren == 0, "STRINGTREE")
300 children.reset();
301 return count;
302 }
303
304 /// Implementation of
305 /// \alib{containers;StringTree<T,TNodeHandler,TRecycling>;TCursor::AssemblePath}.
306 ///
307 /// @param target The target to append the path to.
308 /// @param childNode The (current) child node.
309 /// @param maxParent The last parent node to travel up to. The root node is designated
310 /// by \c nullptr.
311 /// @param separatorChar The separator character as defined with the template parameter of
312 /// class \alib{containers;StringTree}.
313 /// @return The given \b AString to allow concatenated operations on it.
316 lang::HeapAllocator>& target,
317 const NodeBase* childNode,
318 const NodeBase* maxParent,
319 CharacterType separatorChar ) const {
320 static constexpr int STACK_SIZE= 32;
321 const NodeBase* nStack[STACK_SIZE];
322
323 // build stack
324 int sp =1;
325 nStack[0] = childNode;
326 while( childNode->parent != maxParent ) {
327 childNode= childNode->parent;
328 if( childNode == nullptr)
329 break;
330
331 // local stack full? -> let a recursive call do the rest
332 if(sp == STACK_SIZE) {
333 assemblePath( target, childNode, maxParent, separatorChar );
334 break;
335 }
336 nStack[sp++]= childNode;
337 }
338
339 // unroll stack now from top to bottom
340 while( --sp >= 0) {
341 if( nStack[sp]->parent != nullptr ) {
342 if( target.CharAtEnd() != separatorChar
343 && nStack[sp]->parent != maxParent )
344 target << separatorChar;
345
346 target << nStack[sp]->name.key;
347 }
348 else
349 target << separatorChar;
350 }
351
352 return target;
353 }
354 }; // inner class NodeBase
355
356 /// This is the "final" internal node type, just adds a field of template type \p{T}
357 /// to its base class.
358 ///
359 /// Objects of this type cannot be received directly, and all interfaces are available
360 /// via public type \alib{containers;StringTree::Cursor} only, which holds a pointer to
361 /// an object of this class.
362 struct Node : public NodeBase
363 {
364 /// The templated custom data object stored with each node.
366
367 /// Deleted copy constructor.
368 Node( const Node& ) =delete;
369
370 /// Deleted move constructor.
371 Node( Node&& ) =delete;
372
373 /// Constructor. Custom data is default-initialized.
374 /// @tparam TArgs Types of variadic parameters given with parameter \p{args}.
375 /// @param pKey The key portion of the node.
376 /// @param args Variadic parameters. Forwarded to the constructor of custom type \p{T}.
377 template<typename... TArgs>
378 Node( const NodeKey& pKey, TArgs&&... args )
379 : NodeBase( pKey )
380 , data ( std::forward<TArgs>(args)... ) {}
381
382 /// Constructor. Custom data is default-initialized.
383 /// @tparam TArgs Types of variadic parameters given with parameter \p{args}.
384 /// @param pParent Parent node to search a child for.
385 /// @param pName Child name to search
386 /// @param args Variadic parameters. Forwarded to the constructor of custom type \p{T}.
387 template<typename... TArgs>
388 Node( NodeBase* pParent, const NameType& pName, TArgs&&... args )
389 : NodeBase( pParent, pName )
390 , data ( std::forward<TArgs>(args)... ) {}
391
392 }; // inner class Node
393
394 //################################################################################################
395 // StringTreeBase: members
396 //################################################################################################
397 /// This is a union of either a node with a custom object or without. This tricks us into the
398 /// position to embed the memory for a custom type which may optionally be assigned to the root
399 /// node, without constructing it.
400 /// Construction will only be done with explicit use of method
401 /// \alib{containers;StringTree::ConstructRootValue}.
403 {
404 NodeBase rootBase; ///< Base version of the root node, which becomes initialized.
405 Node root; ///< Full version of the root node, without initialization of member T.
406
407 /// Explicitly implement otherwise implicitly deleted constructor
408 RootNodeSpacer() : rootBase( nullptr, nullptr) {}
409
410 /// Destructor
412 };
413
414 /// The root node.
415 RootNodeSpacer root;
416
417 #if ALIB_DEBUG
418 /// Flag available only in debug-compilations to detect access to root node's value
419 /// without prior use of method \alib{containers::StringTree;ConstructRootValue}. Also, the
420 /// destructor issues a warning, in case the root node's value was not deleted with
421 /// \alib{containers::StringTree;DestructRootValue}.
423 #endif
424
425
426 /// The separator character to use with path strings.
427 /// This is set once with construction.
429
430 /// Hash set which contains all children of all nodes.
431 /// This is used to find children of nodes by their parent/name combination.
432 HashTable< TAllocator,
433 typename NodeKey::ValueDescriptor,
434 typename NodeKey::Hash,
435 typename NodeKey::EqualTo,
437 TRecycling > nodeTable;
438
439 /// This type definition may be used to define an externally managed shared recycler,
440 /// which can be passed to the alternative constructor of this class when template
441 /// parameter \p{TRecycling} equals \alib{containers;Recycling;Shared}.
442 /// \see
443 /// Chapter \ref alib_contmono_containers_recycling_shared of the Programmer's Manual
444 /// for this \alibmod.
446
447
448 //################################################################################################
449 // class TCursorBase
450 //################################################################################################
451 /// Base class for \alib{containers;StringTree::Cursor}
452 /// @tparam TConst If true, internal fields representing the StringTree and the current Node
453 /// become \c const and the method #followPathCreate becomes unavailable.
454 template<bool TConst>
456 {
457 /// Constant or mutable version of the base tree type, depending on template parameter
458 /// \p{TConst}
459 using cmTree = std::conditional_t<!TConst, StringTreeBase, const StringTreeBase>;
460
461 /// Constant or mutable version of type \b NodeBase, depending on template parameter
462 /// \p{TConst}
463 using cmNodeBase = std::conditional_t<!TConst, NodeBase, const NodeBase>;
464
465 /// Constant or mutable version of type \b Node, depending on template parameter \p{TConst}
466 using cmNode = std::conditional_t<!TConst, Node, const Node>;
467
468 /// The currently represented node of the #tree.
470
471 /// The \b %StringTree this object refers to.
473
474 /// Constructor initializing both fields #tree and #node.
475 /// @param pNode The node to refer to.
476 /// @param pTree The \b %StringTree we work on.
477 TCursorBase( cmNode* pNode, cmTree* pTree) noexcept
478 : node( pNode )
479 , tree( pTree ) {}
480
481 /// Default constructor. Creates an invalid (uninitialized) object.
482 TCursorBase() noexcept
483 : node( nullptr )
484 , tree( nullptr ) {}
485
486 /// Trivial default copy constructor.
487 TCursorBase( const TCursorBase& ) noexcept =default;
488
489 /// Trivial default move constructor.
490 TCursorBase( TCursorBase&& ) noexcept =default;
491
492 /// Trivial default copy assign operator.
493 /// @return A reference to \c this.
494 TCursorBase& operator=( const TCursorBase& ) noexcept =default;
495
496 /// Trivial default move assign operator.
497 /// @return A reference to \c this.
498 TCursorBase& operator=( TCursorBase&& ) noexcept =default;
499
500 /// Trivial default destructor.
501 ~TCursorBase() noexcept =default;
502
503
504 /// Finds a child node along the \p{path} given, but does not create new nodes.
505 /// Incomplete results may occur if a child along the path was not found.
506 /// In this case, parameter \p{path} contains the remaining path, excluding a leading
507 /// separator.
508 ///
509 /// A leading slash (aka \p{TSeparator}) allows absolute path addressing, which means
510 /// the root of \p{node} is searched if a leading separator is found.
511 ///
512 /// Besides normal child names, this method accepts
513 /// - multiple separator characters (ignored)
514 /// - child name "." (ignored)
515 /// - child name ".." for parent node
516 ///
517 /// @param[in,out] path Creation path. Provided as reference and consumed as far
518 /// as the path exits.
519 /// @return The node found
521 cmNodeBase* actNode= node;
522
523 // check for "root addressing"
524 if( path.CharAtStart() == tree->separator ) {
525 path.ConsumeChars( 1 );
526 while( actNode->parent != nullptr )
527 actNode= actNode->parent;
528 }
529
530 // loop over node names in path
531 for(;;) {
532 // multiple separators are ignored
533 while(path.ConsumeChar( tree->separator ) )
534 ;
535
536 if( path.IsEmpty() )
537 return static_cast<cmNode*>(actNode);
538
539
540 NameType name=path.template Substring<NC>(0, path.IndexOfOrLength(tree->separator));
541
542
543 if( name.Length() == 2 && name[0] == '.' && name[1] == '.' ) {
544 // we move up only if possible. If not, the ".." is just ignored (consumed)
545 // (This behavior was just more helpful in the use cases so far)
546 if( actNode->parent != nullptr )
547 actNode= actNode->parent;
548 }
549
550 else if( name.Length() != 1 || name[0] != '.' ) {
551 cmNodeBase* child= actNode->findChild( tree, name );
552 if( child == nullptr )
553 return static_cast<cmNode*>(actNode);
554
555 actNode= child;
556 }
557
558 path.ConsumeChars( name.Length() );
559 } }
560
561 /// Follows the given path and creates non-existing children along the way.
562 ///
563 /// Child names <c>"."</c> and <c>".."</c> are allowed and respected same
564 /// as in #followPath.
565 ///
566 /// New child nodes are constructed by forwarding the given \p{args}. Existing children
567 /// remain untouched.
568 ///
569 /// \note This method is only available if the template parameter \p{TConst} of this
570 /// type is \c false.
571 /// @tparam TRequires Defaulted template parameter. Must not be specified.
572 /// @tparam TArgs Types of variadic parameters given with parameter \p{args}.
573 /// @param path The path to move along.
574 /// @param args Variadic parameters to be forwarded to the constructor of each node
575 /// that is created.
576 /// @return A <c>std::pair</c> containing a resulting \b Node* and the number of nodes
577 /// created.
578 template<typename... TArgs, bool TRequires= !TConst >
579 requires TRequires
580 std::pair<cmNodeBase*, integer>
581 followPathCreate( const NameType& path, TArgs&&... args ) {
582 std::pair<cmNodeBase*, integer> result= std::make_pair( node, 0 );
583 cmNodeBase*& actNode= result.first; // a local alias name, let the compiler decide
584
585 SubstringType rest= path;
586
587 // check for "root addressing"
588 if( rest.CharAtStart() == tree->separator ) {
589 rest.ConsumeChars( 1 );
590 while( actNode->parent != nullptr )
591 actNode= actNode->parent;
592 }
593
594 // loop over path string
595 for(;;) {
596 // consume '/' and check for emptiness
597 while(rest.ConsumeChar( tree->separator ) )
598 ;
599 if( rest.IsEmpty() )
600 return result;
601
602 NameType childName= rest.template Substring<NC>( 0,
603 rest.IndexOfOrLength( tree->separator ) );
604
605 // "." or ".."?
607 if( childName[0] == '.' )
609 {
610 if( childName.Length() == 1 )
611 continue;
612 if( childName.Length() == 2 && childName[1] != '.' ) {
613 if ( !actNode->isRoot() )
614 actNode= actNode->parent;
615 continue;
616 } }
617
618 auto childCreation= actNode->findOrCreateChild( tree, childName,
619 std::forward<TArgs>(args)... );
620
621 if( childCreation.second )
622 ++result.second;
623
624 actNode= childCreation.first;
625 rest.ConsumeChars( childName.Length() + 1);
626 } }
627 }; // inner class TCursorBase
628
629 /// The mutable version of type \alib{containers::detail;StringTreeBase::TCursorBase<TConst>}.
631
632 /// The constant version of type \alib{containers::detail;StringTreeBase::TCursorBase<TConst>}.
634
635 //################################################################################################
636 // StringTreeBase interface
637 //################################################################################################
638 /// Constructor.
639 /// @param allocator The monotonic allocator to use.
640 /// @param pathSeparator The separation character used with path strings.
641 StringTreeBase( TAllocator& allocator, CharacterType pathSeparator )
642 : separator( pathSeparator )
643 , nodeTable( allocator ) {}
644
645 /// Constructor taking a shared recycler.
646 /// @param allocator The monotonic allocator to use.
647 /// @param pRecycler The shared recycler.
648 /// @param pathSeparator The separation character used with path strings.
649 template<typename TSharedRecycler= SharedRecyclerType>
650 requires ( !std::same_as<TSharedRecycler , void> )
651 StringTreeBase( TAllocator& allocator, TSharedRecycler& pRecycler, CharacterType pathSeparator )
652 : separator( pathSeparator )
653 , nodeTable( allocator, pRecycler ) {}
654
655 /// Constructor taking a shared recycler.
656 /// @param pRecycler The shared recycler.
657 /// @param pathSeparator The separation character used with path strings.
658 /// @tparam TSharedRecycler Used to select this constructor. Deduced by the compiler.
659 template<typename TSharedRecycler= SharedRecyclerType>
660 requires (!std::same_as<TSharedRecycler, void>)
661 StringTreeBase( TSharedRecycler& pRecycler, CharacterType pathSeparator )
662 : separator( pathSeparator )
663 , nodeTable( pRecycler ) {}
664
665 /// @return Returns the allocator received with construction.
666 TAllocator& GetAllocator() noexcept { return nodeTable.GetAllocator(); }
667
668 /// Simple helper method which checks a node name for not being <c>"."</c> or <c>".."</c>
669 /// and for not containing a separator character.
670 /// In debug-compilations, if it does, a \ref alib_mod_assert "warning is raised".
671 ///
672 /// @param name The child name to check.
673 /// @return \c true if the name is legal, false otherwise.
674 bool checkChildName( const NameType& name ) const {
675 if( name.IsEmpty()
676 || ( name[0] == '.'
677 && ( name.Length() == 1 || ( name[1] == '.'
678 && name.Length() == 2 ) ) )
679 || name.IndexOf( separator) >=0 )
680 {
681 ALIB_WARNING( "STRINGTREE", "Illegal child name \"{}\".", name )
682 return false;
683 }
684 return true;
685 }
686
687}; // StringTreeBase
688
689
690} // namespace [alib::containers::detail]
constexpr integer Length() const
Definition string.inl:316
constexpr bool IsEmpty() const
Definition string.inl:365
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.inl:815
std::size_t Hashcode() const
#define ALIB_WARNINGS_UNINITIALIZED_OFF
Definition alib.inl:614
#define ALIB_ASSERT(cond, domain)
Definition alib.inl:1065
#define ALIB_WARNINGS_RESTORE
Definition alib.inl:719
#define ALIB_WARNING(domain,...)
Definition alib.inl:1063
#define ALIB_EXPORT
Definition alib.inl:497
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1066
Detail namespace of module ALib Containers.
@ Enabled
Caching is enabled.
lang::uinteger uinteger
Type alias in namespace alib.
Definition integers.inl:152
strings::TSubstring< character > Substring
Type alias in namespace alib.
NodeList children
The hook to the doubly linked list of children.
strings::TAString< CharacterType, lang::HeapAllocator > & assemblePath(strings::TAString< CharacterType, lang::HeapAllocator > &target, const NodeBase *childNode, const NodeBase *maxParent, CharacterType separatorChar) const
NodeBase(NodeBase *pParent, const NameType &pName)
uinteger qtyChildren
The number of children currently stored in this node.
uinteger deleteChild(StringTreeBase *tree, NodeBase *child)
NodeBase * findChild(StringTreeBase *tree, const NameType &childName)
std::pair< NodeBase *, bool > findOrCreateChild(StringTreeBase *tree, const NameType &childName, TArgs &&... args)
Equality functor for nodes in field nodeTable.
bool operator()(const NodeKey &lhs, const NodeKey &rhs) const
Hash functor for nodes hashed in field nodeTable.
std::size_t operator()(const NodeKey &key) const
NodeKey(NodeBase *pParent, const NameType &pName)
Node(const Node &)=delete
Deleted copy constructor.
T data
The templated custom data object stored with each node.
Node(const NodeKey &pKey, TArgs &&... args)
Node(Node &&)=delete
Deleted move constructor.
Node(NodeBase *pParent, const NameType &pName, TArgs &&... args)
TCursorBase() noexcept
Default constructor. Creates an invalid (uninitialized) object.
std::conditional_t<!TConst, NodeBase, const NodeBase > cmNodeBase
std::pair< cmNodeBase *, integer > followPathCreate(const NameType &path, TArgs &&... args)
TCursorBase(const TCursorBase &) noexcept=default
Trivial default copy constructor.
std::conditional_t<!TConst, Node, const Node > cmNode
Constant or mutable version of type Node, depending on template parameter TConst
TCursorBase(cmNode *pNode, cmTree *pTree) noexcept
std::conditional_t<!TConst, StringTreeBase, const StringTreeBase > cmTree
TCursorBase(TCursorBase &&) noexcept=default
Trivial default move constructor.
typename strings::TSubstring< CharacterType > SubstringType
lang::BidiListHook< NodeBase > NodeList
Alias shortcut for a bidirectional list of Node elements.
StringTreeBase(TAllocator &allocator, TSharedRecycler &pRecycler, CharacterType pathSeparator)
typename decltype(nodeTable)::SharedRecyclerType SharedRecyclerType
typename TNodeHandler::CharacterType CharacterType
StringTreeBase(TSharedRecycler &pRecycler, CharacterType pathSeparator)
typename TNodeHandler::NameStringType NameStorageType
StringTreeBase(TAllocator &allocator, CharacterType pathSeparator)
const strings::TString< CharacterType > NameType
The string-type of node names and paths if provided externally for comparison.
HashTable< TAllocator, typename NodeKey::ValueDescriptor, typename NodeKey::Hash, typename NodeKey::EqualTo, lang::Caching::Enabled, TRecycling > nodeTable
bool checkChildName(const NameType &name) const
TCursorBase< false > CursorBase
The mutable version of type StringTreeBase::TCursorBase<TConst>.
TCursorBase< true > ConstCursorBase
The constant version of type StringTreeBase::TCursorBase<TConst>.
void remove() noexcept
Unhooks this node from a list.
Definition bidilist.inl:97
void next(SidiNodeBase *p)
Definition sidilist.inl:95
integer count(SidiNodeBase *end=nullptr) const noexcept
Definition sidilist.inl:156
NameType key
The name to compare when just keys are used.
NameStorageType storage
The name when stored in the hashtable.
NodeNameUnion(const NameType &n)
Constructor taking a key string.
Node root
Full version of the root node, without initialization of member T.
RootNodeSpacer()
Explicitly implement otherwise implicitly deleted constructor.
NodeBase rootBase
Base version of the root node, which becomes initialized.