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