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