98template<
typename TChar=
character,
integer TLocalCapacity= 32>
107 strings::TString <TChar> >;
123 template<
typename TTree>
130 if constexpr (TLocalCapacity <= 0)
133 node.name.key.CopyTo( buffer );
141 node.name.storage.DbgDisableBufferReplacementWarning();
142 ALIB_DBG(
const TChar* internalBuffer= node.name.storage.Buffer(); )
143 node.name.storage.Append(key);
145 if( internalBuffer != node.name.storage.Buffer() )
163 template<
typename TTree>
165 void FreeNode( TTree& tree,
typename TTree::Node& node )
168 if constexpr (TLocalCapacity <= 0)
169 delete[] node.name.key.Buffer();
171 node.name.storage.~TLocalString();
201template<
typename TChar=
character>
226 template<
typename TTree>
250 template<
typename TTree>
252 void FreeNode( TTree& tree,
typename TTree::Node& node )
253 { (void) tree; (void) node; }
284template<
typename TChar=
character>
311 template<
typename TTree>
315 node.name.storage.Allocate( tree.nodeTable.GetAllocator(), node.name.key );
334 template<
typename TTree>
336 void FreeNode( TTree& tree,
typename TTree::baseNode& node ) { (void) tree; (void) node; }
581template<
typename TAllocator,
584 Recycling TRecycling = Recycling::Private>
596 using baseNodeKey =
typename basetree::NodeKey;
597 using baseNodeBase =
typename basetree::NodeBase;
598 using baseNode =
typename basetree::Node;
599 using baseCursor =
typename basetree::CursorBase;
600 using baseConstCursor =
typename basetree::ConstCursorBase;
660 {
return value==other.value; }
667 {
return value==other.value; }
698 template<
bool TConst>
706 #if ALIB_DEBUG_CRITICAL_SECTIONS
707 #define DCS ALIB_DCS_WITH(cmCursor::tree->nodeTable.dcs)
708 #define DCSSHRD ALIB_DCS_SHARED_WITH(cmCursor::tree->nodeTable.dcs)
718 using cmTree = std::conditional_t<!TConst, basetree, const basetree>;
722 using cmNode = std::conditional_t<!TConst, baseNode, const baseNode>;
726 using cmCursor = std::conditional_t<!TConst, baseCursor, baseConstCursor>;
741 "Invalid StringTree::Cursor: No binding with a StringTree. "
742 "(Probably default-constructed.)")
751 "Invalid StringTree::Cursor not representing a node of the assigned tree." )
758 using TStringTree = std::conditional_t<!TConst, StringTree, const StringTree>;
769 :
TCursor{ src.tree, src.node }
775 :
TCursor{ src.tree, src.node }
801 return cmCursor::node == other.node
802 && cmCursor::tree == other.tree;
811 return !((*this) == other);
847 return cmCursor::node !=
nullptr;
866 return TCursor(cmCursor::tree, &cmCursor::tree->
root.root);
874 cmCursor::node = &cmCursor::tree->root.root;
889 return TCursor(cmCursor::tree,
static_cast<cmNode*
>(cmCursor::node->parent));
899 cmCursor::node =
static_cast<cmNode*
>(cmCursor::node->parent);
926 cmCursor::node =
static_cast<cmNode*
>(cmCursor::node->next());
929 cmCursor::node =
nullptr;
955 cmCursor::node=
static_cast<cmNode*
>(cmCursor::node->prev());
958 cmCursor::node=
nullptr;
982 cmCursor::node=
static_cast<cmNode*
>(cmCursor::node->children.first());
985 cmCursor::node=
nullptr;
1010 cmCursor::node=
static_cast<cmNode*
>(cmCursor::node->children.last());
1013 cmCursor::node=
nullptr;
1032 return TCursor( cmCursor::tree,
1033 static_cast<cmNode*
>(cmCursor::node->findChild(cmCursor::tree, name)));
1053 cmNode* child=
static_cast<cmNode*
>(cmCursor::node->findChild( cmCursor::tree, name ));
1056 cmCursor::node= child;
1078 template<
typename... TArgs>
1084 return std::make_pair(
TCursor(cmCursor::tree,
nullptr),
true );
1086 auto result= cmCursor::node->findOrCreateChild( cmCursor::tree, name,
1087 std::forward<TArgs>(args)... );
1089 return std::make_pair(
TCursor( cmCursor::tree, result.first ), result.second );
1106 template<
typename... TArgs>
1112 cmCursor::node=
nullptr;
1116 auto result= cmCursor::node->findOrCreateChild( cmCursor::tree, name,
1117 std::forward<TArgs>(args)... );
1119 cmCursor::node=
static_cast<cmNode*
>(result.first);
1120 return result.second;
1164 cmNode* grandChild= cmCursor::followPath( remainingPath );
1165 return std::make_pair(
TCursor(cmCursor::tree, grandChild), remainingPath );
1179 cmCursor::node= cmCursor::followPath( remainingPath );
1180 return remainingPath;
1197 template<
typename... TArgs>
1203 "STRINGTREE",
"Invalid StringTree::Cursor given with relative path addressing." )
1205 auto result= cmCursor::followPathCreate( path, std::forward<TArgs>(args)... );
1207 return std::make_pair(
TCursor(cmCursor::tree,
static_cast<cmNode*
>(result.first)),
1224 template<
typename... TArgs>
1230 "STRINGTREE",
"Invalid StringTree::Cursor given with relative path addressing." )
1232 auto result= cmCursor::followPathCreate( path, std::forward<TArgs>(args)... );
1233 cmCursor::node=
static_cast<cmNode*
>(result.first);
1234 return result.second;
1246 return cmCursor::node->name.key;
1254 template<
typename TParent= StringTree>
1255 requires std::derived_from<TParent, StringTree>
1257 {
dbgCheckTree();
return *
static_cast<TParent*
>(cmCursor::tree); }
1266 template<
bool TRequires= !TConst>
1272 "Root node has no value. Either this operation is unwanted or root node's value\n"
1273 "has to be explicitly set using SetRootNode(...)" )
1274 return static_cast<baseNode*
>(cmCursor::node)->data;
1285 "Root node has no value. Either this operation is unwanted or root node's value\n"
1286 "has to be explicitly set using SetRootNode(...)" )
1287 return static_cast<const baseNode*
>(cmCursor::node)->data;
1296 template<
bool TRequires= !TConst>
1302 "Root node has no value. Either this operation is unwanted or root node's value\n"
1303 "has to be explicitly set using SetRootNode(...)" )
1304 return &
static_cast<baseNode*
>(cmCursor::node)->data;
1314 "Root node has no value. Either this operation is unwanted or root node's value\n"
1315 "has to be explicitly set using SetRootNode(...)" )
1316 return &
static_cast<const baseNode*
>(cmCursor::node)->data;
1325 template<
bool TRequires= !TConst>
1331 "Root node has no value. Either this operation is unwanted or root node's value\n"
1332 "has to be explicitly set using SetRootNode(...)" )
1333 return static_cast<baseNode*
>(cmCursor::node)->data;
1344 "Root node has no value. Either this operation is unwanted or root node's value\n"
1345 "has to be explicitly set using SetRootNode(...)" )
1346 return static_cast<const baseNode*
>(cmCursor::node)->data;
1355 return cmCursor::node->isRoot();
1364 return cmCursor::node->depth();
1384 "Given node belongs to a different StringTree." )
1385 return cmCursor::node->distance( other.node );
1393 return cmCursor::node->qtyChildren != 0;
1402 return cmCursor::node->qtyChildren;
1413 && !cmCursor::node->parent->children.isLast( cmCursor::node );
1424 && !cmCursor::node->parent->children.isFirst( cmCursor::node );
1455 targetString.Reset();
1457 return cmCursor::node->assemblePath( targetString, cmCursor::node,
nullptr,
1486 targetString.Reset();
1487 return cmCursor::node->assemblePath( targetString, cmCursor::node, parent.node,
1488 cmCursor::tree->separator );
1518 template<
typename TCheck =
CHK,
typename... TArgs>
1522 if constexpr ( TCheck::value )
1527 ALIB_WARNING(
"STRINGTREE",
"Illegal child name \"{}\"", childName )
1528 return Cursor( baseCursor::tree,
nullptr );
1532 if( baseCursor::node->qtyChildren > 0
1533 && baseCursor::tree->
nodeTable.Contains( baseNodeKey( baseCursor::node, childName) ))
1534 return Cursor( baseCursor::tree,
nullptr );
1537 baseNode* child= &baseCursor::tree->nodeTable.EmplaceUnique( baseCursor::node, childName,
1538 std::forward<TArgs>(args)... )
1540 TNodeHandler::InitializeNode( *baseCursor::tree, *child );
1542 baseCursor::node->children.pushEnd( child );
1543 ++baseCursor::node->qtyChildren;
1544 return TCursor( baseCursor::tree, child );
1561 if( baseCursor::node->qtyChildren == 0 )
1564 auto handle= baseCursor::tree->nodeTable.Extract( baseNodeKey( baseCursor::node, childName) );
1565 if( handle.IsEmpty() )
1567 handle.Value().deleteChildren( baseCursor::tree );
1568 TNodeHandler::FreeNode( *baseCursor::tree, handle.Value() );
1569 handle.Value().remove();
1571 --baseCursor::node->qtyChildren;
1592 cmNode* nodeToDelete= child.node;
1594 baseCursor::node->deleteChild( baseCursor::tree, nodeToDelete );
1604 return baseCursor::node->deleteChildren( baseCursor::tree );
1626 if( baseCursor::node->isRoot() )
1627 return baseCursor::node->deleteChildren( baseCursor::tree );
1629 cmNode * child= baseCursor::node;
1630 baseCursor::node=
static_cast<cmNode*
>(baseCursor::node->parent);
1631 return baseCursor::node->deleteChild( baseCursor::tree, child );
1701 template<
bool TConst>
1705 #if ALIB_DEBUG_CRITICAL_SECTIONS
1708 #define DCS ALIB_DCS_WITH(tree->nodeTable.dcs)
1709 #define DCSSHRD ALIB_DCS_SHARED_WITH(tree->nodeTable.dcs)
1715 using cmTree = std::conditional_t<!TConst, StringTree , const StringTree>;
1719 using cmNodeBase= std::conditional_t<!TConst, baseNodeBase, const baseNodeBase>;
1723 using cmNode = std::conditional_t<!TConst, baseNode , const baseNode>;
1727 using cmCursor = std::conditional_t<!TConst, Cursor , ConstCursor>;
1757 std::conditional_t<!TConst,
1892 unsigned int depth= (std::numeric_limits<unsigned int>::max)() )
1894 initialize( &pTree, &pTree.root.root, depth );
1913 unsigned int depth= (std::numeric_limits<unsigned int>::max)() )
1916 cursor.IsValid() ? cursor.node : &cursor.tree->root.root,
1932 unsigned int depth= (std::numeric_limits<unsigned int>::max)() )
2085 return target <<
node->name.key;
2108 "RecursiveIterator not initialized or exceeded (invalid)." )
2126 "RecursiveIterator not initialized or exceeded (invalid)." )
2150 "RecursiveIterator not initialized or exceeded (invalid)." )
2151 auto& nodeToDelete= *
node;
2153 return nodeToDelete.parent->deleteChild(
tree, &nodeToDelete );
2170 if( newnode->isRoot() )
2175 if( newnode->qtyChildren )
2192 stack.emplace_back();
2203 rd.childrenUnsorted= &
node->children;
2204 node=
static_cast<cmNode*
>(rd.actChild.unsorted= rd.childrenUnsorted->first());
2209 rd.childrenSorted.clear();
2210 rd.childrenSorted.reserve(
size_t(
node->qtyChildren ) );
2211 auto* copyIt=
node->children.first();
2212 while( copyIt != &
node->children.hook )
2214 rd.childrenSorted.emplace_back(
static_cast<cmNode*
>(copyIt) );
2215 copyIt= copyIt->next();
2219 if( rd.customSorter )
2221 std::sort( rd.childrenSorted.begin(), rd.childrenSorted.end(),
2225 return rd.customSorter( cmCursor(tree, lhs),
2226 cmCursor(tree, rhs) );
2232 std::sort( rd.childrenSorted.begin(), rd.childrenSorted.end(),
2235 int compResult= rd.sortingIsCaseSensitive
2236 ? lhs->name.key. template CompareTo<CHK, lang::Case::Sensitive>(rhs->name.key)
2237 : lhs->name.key. template CompareTo<CHK, lang::Case::Ignore >(rhs->name.key);
2238 return rd.sortingIsDescending ? compResult > 0
2245 rd.actChild.sorted= 0;
2246 node= rd.childrenSorted[0];
2267 &&
node->qtyChildren )
2280 stack.emplace_back();
2292 bool foundNextChild;
2299 if( (foundNextChild= rd.actChild.
sorted < rd.childrenSorted.size())
2306 foundNextChild= (
node != &rd.childrenUnsorted->
hook);
2310 if( foundNextChild )
2329 while( lastChar !=
tree->separator &&
actPath.IsNotEmpty() );
2357 #if ALIB_DEBUG_CRITICAL_SECTIONS
2360 #define DCS ALIB_DCS_WITH(basetree::nodeTable.dcs)
2361 #define DCSSHRD ALIB_DCS_SHARED_WITH(basetree::nodeTable.dcs)
2371 : basetree( allocator, pathSeparator )
2373 #if ALIB_DEBUG_CRITICAL_SECTIONS
2374 basetree::nodeTable.dcs.DCSName=
"StringTree";
2383 template<
typename TSharedRecycler= SharedRecyclerType>
2384 requires(!std::same_as<TSharedRecycler, void>)
2386 : basetree( pRecycler, pathSeparator )
2388 #if ALIB_DEBUG_CRITICAL_SECTIONS
2389 basetree::nodeTable.dcs.DCSName=
"StringTree";
2400 for(
auto& node : basetree::nodeTable )
2401 TNodeHandler::FreeNode( *
this, *
static_cast<baseNode*
>(&node) );
2404 "Possible memory leak! The root node's value object was set but not deleted before\n"
2405 "destruction of this StringTree. To suppress this warning call DestructRootValue()\n"
2406 "before destruction. In case this is not necessary (because the stored type does not\n"
2407 "leak if not destructed), emplace it in macro ALIB_DBG() to remove the call in\n"
2425 {
return basetree::separator; }
2427 #if ALIB_DEBUG_CRITICAL_SECTIONS
2431 void DbgSetDCSName(
const char* name)
const { basetree::nodeTable.dcs.DCSName= name; }
2449 template<
typename... TArgs>
2454 "Root node value is set without prior deletion. Possible memory leak (depending on\n "
2455 "allocation of template type T). This warning is only printed on the first overwrite.")
2456 ++basetree::dbgRootDataSet;
2459 new (&basetree::root.root.data) T( std::forward<TArgs>(args)... );
2472 "Deletion of root node data without prior setting (or double deletion)." )
2473 --basetree::dbgRootDataSet;
2475 basetree::root.root.data.~T();
2491 for(
auto& node : basetree::nodeTable )
2492 TNodeHandler::FreeNode( *
this, *
static_cast<baseNode*
>(&node) );
2493 basetree::nodeTable.Clear();
2496 basetree::root.root.children.reset();
2497 basetree::root.root.qtyChildren= 0;
2517 for(
auto& node : basetree::nodeTable )
2518 TNodeHandler::FreeNode( *
this, *
static_cast<baseNode*
>(&node) );
2521 basetree::nodeTable.Reset();
2522 basetree::root.root.children.reset();
2523 basetree::root.root.qtyChildren= 0;
2540 {
return basetree::nodeTable.RecyclablesCount(); }
2551 {
return basetree::nodeTable.Size(); }
2559 {
return basetree::nodeTable.Size() == 0; }
2573 { basetree::nodeTable.ReserveRecyclables( qty, reference ); }
2583 {
return basetree::nodeTable; }
2593 {
return basetree::nodeTable; }
2600 {
return Cursor(
this, &(basetree::root.
root) ); }
2613 {
return Cursor(
this,
reinterpret_cast<typename basetree::Node*
>(handle.value) ); }
2619 {
return Cursor(
this,
reinterpret_cast<typename basetree::Node*
>(handle.value) ); }
2622 #if ALIB_DEBUG_CRITICAL_SECTIONS
2635template<
typename TChar,
integer TLocalCapacity= 32>
2639template<
typename TChar>
2643template<
typename TChar>
2647template<
typename TAllocator,
2650 Recycling TRecycling = Recycling::Private >
TCursor() noexcept=default
SubstringType GoTo(const NameType &path)
int Distance(const TCursor< true > &other) const
TCursor NextSibling() const
bool operator!=(const TCursor &other) const
integer GoToCreatedPathIfNotExistent(const NameType &path, TArgs &&... args)
std::pair< TCursor, SubstringType > operator()(const NameType &path) const
TCursor & operator=(const TCursor &) noexcept=default
const T * operator->() const
void dbgCheckTree() const
TCursor CreateChild(const NameType &childName, TArgs &&... args) const
std::conditional_t<!TConst, StringTree, const StringTree > TStringTree
const T & operator*() const
TCursor FirstChild() const
std::conditional_t<!TConst, basetree, const basetree > cmTree
TCursor PreviousSibling() const
bool HasNextSibling() const
TCursor(TCursor &&src) noexcept
bool GoToPreviousSibling()
ConstCursorHandle Export() const
std::conditional_t<!TConst, baseNode, const baseNode > cmNode
const NameType & Name() const
strings::TAString< typename cmTree::CharacterType, lang::HeapAllocator > & AssemblePath(strings::TAString< typename cmTree::CharacterType, lang::HeapAllocator > &targetString, const TCursor< true > &parent, lang::CurrentData targetData=lang::CurrentData::Clear) const
TCursor LastChild() const
TCursor Child(const NameType &name) const
bool GoToCreateChildIfNotExistent(const NameType &name, TArgs &&... args)
bool HasPreviousSibling() const
bool GoToChild(const NameType &name)
std::pair< TCursor, integer > CreatePathIfNotExistent(const NameType &path, TArgs &&... args)
uinteger CountChildren() const
TCursor(cmTree *pTree, cmNode *pNode) noexcept
void DeleteChild(TCursor &child) const
std::conditional_t<!TConst, baseCursor, baseConstCursor > cmCursor
void dbgCheckTreeAndNode() const
strings::TAString< typename cmTree::CharacterType, lang::HeapAllocator > & AssemblePath(strings::TAString< typename cmTree::CharacterType, lang::HeapAllocator > &targetString, lang::CurrentData targetData=lang::CurrentData::Clear) const
bool operator==(const TCursor &other) const
std::pair< TCursor, bool > CreateChildIfNotExistent(const NameType &name, TArgs &&... args)
TCursor & operator=(TCursor &&) noexcept=default
bool DeleteChild(const NameType &childName) const
uinteger DeleteChildren() const
int RequestedDepth() const
void Initialize(const TRecursiveIterator &other, unsigned int depth=(std::numeric_limits< unsigned int >::max)())
bool nextSortingIsCaseSensitive
void initialize(cmTree *pTree, cmNode *newnode, unsigned int depth)
std::conditional_t<!TConst, baseNode, const baseNode > cmNode
std::conditional_t<!TConst, baseNodeBase, const baseNodeBase > cmNodeBase
AString & FullPath(AString &target, lang::CurrentData targetData=lang::CurrentData::Clear) const
bool nextSortingIsDescending
void SetSorting(lang::Switch sorting)
std::conditional_t<!TConst, StringTree, const StringTree > cmTree
void SetSorting(bool(*customSorterFunction)(const Cursor &, const Cursor &))
bool(* nextCustomSorter)(const cmCursor &, const cmCursor &)
void Initialize(cmCursor cursor, unsigned int depth=(std::numeric_limits< unsigned int >::max)())
const NameType & CurrentPath() const
std::vector< RecursionData > stack
TRecursiveIterator()=default
Default constructor.
std::conditional_t<!TConst, Cursor, ConstCursor > cmCursor
void Initialize(cmTree &pTree, unsigned int depth=(std::numeric_limits< unsigned int >::max)())
void SetPathGeneration(lang::Switch pathGeneration)
unsigned int recursionDepth
void SetSorting(lang::SortOrder order=lang::SortOrder::Ascending, lang::Case sensitivity=lang::Case::Ignore)
void ReserveRecyclables(integer qty, lang::ValueReference reference)
integer RecyclablesCount() const
constexpr CharacterType Separator() const noexcept
const auto & NodeTable() const
TRecursiveIterator< true > ConstRecursiveIterator
TCursor< true > ConstCursor
The constant version of type TCursor<TConst>.
typename StringTreeNamesAlloc< character >::CharacterType CharacterType
Cursor ImportCursor(CursorHandle handle)
const ConstCursor Root() const
Cursor createCursor(baseNode &node)
StringTree(CharacterType pathSeparator, TSharedRecycler &pRecycler)
ConstCursor ImportCursor(ConstCursorHandle handle)
typename strings::TSubstring< CharacterType > SubstringType
strings::TString< CharacterType > NameType
void DbgSetDCSName(const char *name) const
AllocatorType & GetAllocator() noexcept
TRecursiveIterator< false > RecursiveIterator
TCursor< false > Cursor
The mutable version of type TCursor<TConst>.
StringTree(AllocatorType &allocator, CharacterType pathSeparator)
StringTreeNamesAlloc< character > HandlerType
typename basetree::SharedRecyclerType SharedRecyclerType
MonoAllocator AllocatorType
void ConstructRootValue(TArgs &&... args)
TChar CharAtStart() const
#define ALIB_ASSERT(cond, domain)
#define ALIB_WARNING(domain,...)
#define ALIB_ASSERT_WARNING(cond, domain,...)
#define ALIB_ASSERT_ERROR(cond, domain,...)
uinteger DBG_STATS_STRINGTREE_NAMES
uinteger DBG_STATS_STRINGTREE_NAME_OVERFLOWS
SortOrder
Denotes sort order.
@ Ascending
Chooses ascending sort oder.
@ Descending
Chooses descending sort oder.
Switch
Denotes if sth. is switched on or off.
@ On
Switch it on, switched on, etc.
@ Off
Switch it off, switched off, etc.
Case
Denotes upper and lower case character treatment.
@ Clear
Chooses to clear existing data.
ValueReference
Denotes if a value is interpreted as an absolute or relative number.
constexpr String NULL_STRING
A nulled string of the default character type.
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace alib.
constexpr const String EMPTY_STRING
An empty string of the default character type.
lang::integer integer
Type alias in namespace alib.
containers::StringTreeNamesStatic< TChar > StringTreeNamesStatic
Type alias in namespace alib.
containers::Recycling Recycling
Type alias in namespace alib.
containers::StringTree< TAllocator, T, TNodeHandler, TRecycling > StringTree
Type alias in namespace alib.
containers::StringTreeNamesAlloc< TChar > StringTreeNamesAlloc
Type alias in namespace alib.
characters::character character
Type alias in namespace alib.
lang::uinteger uinteger
Type alias in namespace alib.
containers::StringTreeNamesDynamic< TChar, TLocalCapacity > StringTreeNamesDynamic
Type alias in namespace alib.
strings::TString< TChar > NameStringType
The string-type of a node's name.
static void InitializeNode(TTree &tree, typename TTree::Node &node)
static void FreeNode(TTree &tree, typename TTree::baseNode &node)
TChar CharacterType
The character type that the StringTree uses for child name and path strings.
TChar CharacterType
The character type that the StringTree uses for child name and path strings.
static void InitializeNode(TTree &tree, typename TTree::Node &node)
std::conditional_t<(TLocalCapacity > 0), strings::TLocalString< TChar, TLocalCapacity >, strings::TString< TChar > > NameStringType
The string-type of a node's name.
static void FreeNode(TTree &tree, typename TTree::Node &node)
static void FreeNode(TTree &tree, typename TTree::Node &node)
static void InitializeNode(TTree &tree, typename TTree::Node &node)
TChar CharacterType
The character type that the StringTree uses for child name and path strings.
strings::TString< TChar > NameStringType
The string-type of a node's name.
A handle type used with methods TCursor::Export and ImportCursor.
bool operator==(const CursorHandle &other) const noexcept
bool IsValid() const noexcept
uinteger value
The encapsulated value.
bool operator==(const ConstCursorHandle &other) const noexcept
A handle type used with methods TCursor::Export and ImportCursor.
uinteger value
The encapsulated value.
bool IsValid() const noexcept
bool operator==(const CursorHandle &other) const noexcept
bool(* customSorter)(const cmCursor &, const cmCursor &)
RecursionData() noexcept=default
Trivial default constructor.
lang::BidiListHook< baseNodeBase > * childrenUnsorted
bool sortingIsCaseSensitive
std::vector< cmNode * > childrenSorted
A pointer to a dynamically allocated vector of children used with sorting.
RootNodeSpacer root
The root node.
HashTable< TAllocator, typename NodeKey::ValueDescriptor, typename NodeKey::Hash, typename NodeKey::EqualTo, lang::Caching::Enabled, TRecycling > nodeTable
bool checkChildName(const NameType &name) const
TAllocator & GetAllocator() const noexcept
TNode hook
The root node. Points twice to itself when the list is empty.