8#ifndef HPP_ALIB_MONOMEM_CONTAINERS_STRINGTREE
9#define HPP_ALIB_MONOMEM_CONTAINERS_STRINGTREE 1
16#include "alib/containers/detail/stringtreebase.inl"
19namespace alib {
namespace containers {
109template<
typename TChar=
character,
integer TLocalCapacity= 32>
120 strings::TString <TChar> );
136 template<
typename TTree>
143 if constexpr (TLocalCapacity <= 0)
146 node.name.key.CopyTo( buffer );
154 node.name.storage.DbgDisableBufferReplacementWarning();
155 ALIB_DBG(
const TChar* internalBuffer= node.name.storage.Buffer(); )
156 node.name.storage.Append(key);
158 if( internalBuffer != node.name.storage.Buffer() )
176 template<
typename TTree>
178 void FreeNode( TTree& tree,
typename TTree::Node& node )
181 if constexpr (TLocalCapacity <= 0)
182 delete[] node.name.key.Buffer();
184 node.name.storage.~TLocalString();
214template<
typename TChar=
character>
239 template<
typename TTree>
263 template<
typename TTree>
265 void FreeNode( TTree& tree,
typename TTree::Node& node )
266 { (void) tree; (void) node; }
297template<
typename TChar=
character>
324 template<
typename TTree>
328 node.name.storage.Allocate( tree.nodeTable.GetAllocator(), node.name.key );
347 template<
typename TTree>
349 void FreeNode( TTree& tree,
typename TTree::baseNode& node ) { (void) tree; (void) node; }
594template<
typename TAllocator,
597 Recycling TRecycling = Recycling::Private>
609 using baseNodeKey =
typename basetree::NodeKey;
610 using baseNodeBase =
typename basetree::NodeBase;
611 using baseNode =
typename basetree::Node;
612 using baseCursor =
typename basetree::CursorBase;
613 using baseConstCursor =
typename basetree::ConstCursorBase;
673 {
return value==other.value; }
680 {
return value==other.value; }
711 template<
bool TConst>
719 #if ALIB_DEBUG_CRITICAL_SECTIONS
720 #define DCS ALIB_DCS_WITH(cmCursor::tree->nodeTable.dcs)
721 #define DCSSHRD ALIB_DCS_SHARED_WITH(cmCursor::tree->nodeTable.dcs)
754 "Invalid StringTree::Cursor: No binding with a StringTree. "
755 "(Probably default-constructed.)")
764 "Invalid StringTree::Cursor not representing a node of the assigned tree." )
782 :
TCursor{ src.tree, src.node }
788 :
TCursor{ src.tree, src.node }
814 return cmCursor::node == other.node
815 && cmCursor::tree == other.tree;
824 return !((*this) == other);
860 return cmCursor::node !=
nullptr;
887 cmCursor::node = &cmCursor::tree->root.root;
902 return TCursor(cmCursor::tree,
static_cast<cmNode*
>(cmCursor::node->parent));
912 cmCursor::node =
static_cast<cmNode*
>(cmCursor::node->parent);
939 cmCursor::node =
static_cast<cmNode*
>(cmCursor::node->next());
942 cmCursor::node =
nullptr;
968 cmCursor::node=
static_cast<cmNode*
>(cmCursor::node->prev());
971 cmCursor::node=
nullptr;
995 cmCursor::node=
static_cast<cmNode*
>(cmCursor::node->children.first());
998 cmCursor::node=
nullptr;
1023 cmCursor::node=
static_cast<cmNode*
>(cmCursor::node->children.last());
1026 cmCursor::node=
nullptr;
1045 return TCursor( cmCursor::tree,
1046 static_cast<cmNode*
>(cmCursor::node->findChild(cmCursor::tree, name)));
1066 cmNode* child=
static_cast<cmNode*
>(cmCursor::node->findChild( cmCursor::tree, name ));
1069 cmCursor::node= child;
1091 template<
typename... TArgs>
1097 return std::make_pair(
TCursor(cmCursor::tree,
nullptr),
true );
1099 auto result= cmCursor::node->findOrCreateChild( cmCursor::tree, name,
1100 std::forward<TArgs>(args)... );
1102 return std::make_pair(
TCursor( cmCursor::tree, result.first ), result.second );
1119 template<
typename... TArgs>
1125 cmCursor::node=
nullptr;
1129 auto result= cmCursor::node->findOrCreateChild( cmCursor::tree, name,
1130 std::forward<TArgs>(args)... );
1132 cmCursor::node=
static_cast<cmNode*
>(result.first);
1133 return result.second;
1176 cmNode* grandChild= cmCursor::followPath( remainingPath );
1177 return std::make_pair(
TCursor(cmCursor::tree, grandChild), remainingPath );
1191 cmCursor::node= cmCursor::followPath( remainingPath );
1192 return remainingPath;
1209 template<
typename... TArgs>
1215 "MONOMEM/STRINGTREE",
1216 "Invalid StringTree::Cursor given with relative path addressing." )
1218 auto result= cmCursor::followPathCreate( path, std::forward<TArgs>(args)... );
1220 return std::make_pair(
TCursor(cmCursor::tree,
static_cast<cmNode*
>(result.first)),
1237 template<
typename... TArgs>
1243 "MONOMEM/STRINGTREE",
1244 "Invalid StringTree::Cursor given with relative path addressing." )
1246 auto result= cmCursor::followPathCreate( path, std::forward<TArgs>(args)... );
1247 cmCursor::node=
static_cast<cmNode*
>(result.first);
1248 return result.second;
1260 return cmCursor::node->name.key;
1269 template<
typename TParent= StringTree>
const
1275 template<
typename TParent= StringTree>
1281 return *
static_cast<TParent*
>(cmCursor::tree);
1293 template<
bool TEnableIf= !TConst>
1299 "Root node has no value. Either this operation is unwanted or root node's value\n"
1300 "has to be explicitly set using SetRootNode(...)" )
1301 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;
1326 template<
bool TEnableIf= !TConst>
1332 "Root node has no value. Either this operation is unwanted or root node's value\n"
1333 "has to be explicitly set using SetRootNode(...)" )
1334 return &static_cast<baseNode*>(
cmCursor::node)->data;
1345 "Root node has no value. Either this operation is unwanted or root node's value\n"
1346 "has to be explicitly set using SetRootNode(...)" )
1347 return &
static_cast<const baseNode*
>(cmCursor::node)->data;
1357 template<
bool TEnableIf= !TConst>
1363 "Root node has no value. Either this operation is unwanted or root node's value\n"
1364 "has to be explicitly set using SetRootNode(...)" )
1365 return static_cast<baseNode*>(
cmCursor::node)->data;
1377 "Root node has no value. Either this operation is unwanted or root node's value\n"
1378 "has to be explicitly set using SetRootNode(...)" )
1379 return static_cast<const baseNode*
>(cmCursor::node)->data;
1388 return cmCursor::node->isRoot();
1397 return cmCursor::node->depth();
1417 "Given node belongs to a different StringTree." )
1418 return cmCursor::node->distance( other.node );
1426 return cmCursor::node->qtyChildren != 0;
1435 return cmCursor::node->qtyChildren;
1446 && !cmCursor::node->parent->children.isLast( cmCursor::node );
1457 && !cmCursor::node->parent->children.isFirst( cmCursor::node );
1488 targetString.Reset();
1490 return cmCursor::node->assemblePath( targetString, cmCursor::node,
nullptr,
1519 targetString.Reset();
1520 return cmCursor::node->assemblePath( targetString, cmCursor::node, parent.node,
1521 cmCursor::tree->separator );
1551 template<
typename TCheck =
CHK,
typename... TArgs>
1555 if constexpr ( TCheck::value )
1560 ALIB_WARNING(
"STRINGTREE",
"Illegal child name {!Q}", childName )
1561 return Cursor( baseCursor::tree,
nullptr );
1565 if( baseCursor::node->qtyChildren > 0
1566 && baseCursor::tree->
nodeTable.Contains( baseNodeKey( baseCursor::node, childName) ))
1567 return Cursor( baseCursor::tree,
nullptr );
1570 baseNode* child= &baseCursor::tree->nodeTable.EmplaceUnique( baseCursor::node, childName,
1571 std::forward<TArgs>(args)... )
1573 TNodeHandler::InitializeNode( *baseCursor::tree, *child );
1575 baseCursor::node->children.pushEnd( child );
1576 ++baseCursor::node->qtyChildren;
1577 return TCursor( baseCursor::tree, child );
1594 if( baseCursor::node->qtyChildren == 0 )
1597 auto handle= baseCursor::tree->nodeTable.Extract( baseNodeKey( baseCursor::node, childName) );
1598 if( handle.IsEmpty() )
1600 handle.Value().deleteChildren( baseCursor::tree );
1601 TNodeHandler::FreeNode( *baseCursor::tree, handle.Value() );
1602 handle.Value().remove();
1604 --baseCursor::node->qtyChildren;
1625 cmNode* nodeToDelete= child.node;
1627 baseCursor::node->deleteChild( baseCursor::tree, nodeToDelete );
1637 return baseCursor::node->deleteChildren( baseCursor::tree );
1659 if( baseCursor::node->isRoot() )
1660 return baseCursor::node->deleteChildren( baseCursor::tree );
1662 cmNode * child= baseCursor::node;
1663 baseCursor::node=
static_cast<cmNode*
>(baseCursor::node->parent);
1664 return baseCursor::node->deleteChild( baseCursor::tree, child );
1734 template<
bool TConst>
1738 #if ALIB_DEBUG_CRITICAL_SECTIONS
1741 #define DCS ALIB_DCS_WITH(tree->nodeTable.dcs)
1742 #define DCSSHRD ALIB_DCS_SHARED_WITH(tree->nodeTable.dcs)
1854 size_t actDepth =
size_t(-1);
1861 unsigned int recursionDepth =(std::numeric_limits<
unsigned int>::max)();
1867 bool nextIsSorting = false;
1870 bool nextSortingIsDescending = false;
1873 bool nextSortingIsCaseSensitive = false;
1910 void SetPathGeneration( lang::Switch pathGeneration )
1927 unsigned int depth= (std::numeric_limits<unsigned int>::max)() )
1929 initialize( &pTree, &pTree.root.root, depth );
1948 unsigned int depth= (std::numeric_limits<unsigned int>::max)() )
1950 initialize(
static_cast<cmTree*
>( cursor.tree ),
1951 cursor.IsValid() ? cursor.node : &cursor.tree->root.root,
1967 unsigned int depth= (std::numeric_limits<unsigned int>::max)() )
1969 initialize( other.
tree, other.
node, depth );
1977 actDepth= size_t(-1);
1989 return actDepth != size_t(-1);
2015 if( sorting == lang::Switch::Off )
2016 nextIsSorting=
false;
2018 SetSorting(lang::SortOrder::Ascending, lang::Case::Ignore );
2033 lang::Case sensitivity = lang::Case::Ignore )
2035 nextIsSorting =
true;
2036 nextCustomSorter =
nullptr;
2037 nextSortingIsDescending = ( order == lang::SortOrder::Descending );
2038 nextSortingIsCaseSensitive= ( sensitivity == lang:: Case::Sensitive );
2051 nextIsSorting =
true;
2052 nextCustomSorter = customSorterFunction;
2061 bool Next() {DCSSHRD
return next(0); }
2095 "Path generation not activated" )
2114 "Path generation not activated" )
2116 if( targetData == lang::CurrentData::Clear )
2119 if( actPath.IsNotEmpty() )
2120 target << actPath << tree->separator;
2122 return target << node->name.key;
2145 "RecursiveIterator not initialized or exceeded (invalid)." )
2146 return int(actDepth);
2163 "RecursiveIterator not initialized or exceeded (invalid)." )
2187 "RecursiveIterator not initialized or exceeded (invalid)." )
2188 auto& nodeToDelete= *node;
2190 return nodeToDelete.parent->deleteChild( tree, &nodeToDelete );
2204 if( actPath.IsNotNull() )
2207 if( newnode->isRoot() )
2208 actPath << tree->separator;
2212 if( newnode->qtyChildren )
2214 recursionDepth= depth;
2215 actDepth= size_t(-1);
2219 actDepth= size_t( -1 );
2228 if( stack.size() == actDepth )
2229 stack.emplace_back();
2231 auto& rd= stack[actDepth];
2232 rd.customSorter = nextCustomSorter;
2233 rd.isSorting = nextIsSorting;
2234 rd.sortingIsDescending = nextSortingIsDescending;
2235 rd.sortingIsCaseSensitive= nextSortingIsCaseSensitive;
2240 rd.childrenUnsorted= &node->children;
2241 node=
static_cast<cmNode*
>(rd.actChild.unsorted= rd.childrenUnsorted->first());
2246 rd.childrenSorted.clear();
2247 rd.childrenSorted.reserve(
size_t( node->qtyChildren ) );
2248 auto* copyIt= node->children.first();
2249 while( copyIt != &node->children.hook )
2251 rd.childrenSorted.emplace_back(
static_cast<cmNode*
>(copyIt) );
2252 copyIt= copyIt->next();
2256 if( rd.customSorter )
2258 std::sort( rd.childrenSorted.begin(), rd.childrenSorted.end(),
2262 return rd.customSorter( cmCursor(tree, lhs),
2263 cmCursor(tree, rhs) );
2269 std::sort( rd.childrenSorted.begin(), rd.childrenSorted.end(),
2272 int compResult= rd.sortingIsCaseSensitive
2273 ? lhs->name.key. template CompareTo<CHK, lang::Case::Sensitive>(rhs->name.key)
2274 : lhs->name.key. template CompareTo<CHK, lang::Case::Ignore >(rhs->name.key);
2275 return rd.sortingIsDescending ? compResult > 0
2282 rd.actChild.sorted= 0;
2283 node= rd.childrenSorted[0];
2300 "Invalid iterator" )
2304 &&
static_cast<unsigned int>( actDepth ) < recursionDepth
2305 && node->qtyChildren )
2307 if( actPath.IsNotNull() )
2309 if( actPath.IsNotEmpty()
2310 && (actPath.Length() != 1 || actPath.CharAtStart() != tree->separator ) )
2311 actPath << tree->separator;
2313 actPath << node->name.key;
2317 if( stack.size() == actDepth + 1 )
2318 stack.emplace_back();
2330 bool foundNextChild;
2348 if( foundNextChild )
2359 if( actPath.IsNotEmpty() )
2364 lastChar= actPath.CharAtEnd<
NC>();
2365 actPath.DeleteEnd<
NC>( 1 );
2367 while( lastChar != tree->separator && actPath.IsNotEmpty() );
2372 actDepth= size_t(-1);
2374 || (actPath.Length() == 1 && actPath.CharAtStart() == tree->separator) )
2379 return actDepth != size_t(-1);
2395 #if ALIB_DEBUG_CRITICAL_SECTIONS
2398 #define DCS ALIB_DCS_WITH(basetree::nodeTable.dcs)
2399 #define DCSSHRD ALIB_DCS_SHARED_WITH(basetree::nodeTable.dcs)
2409 : basetree( allocator, pathSeparator )
2411 #if ALIB_DEBUG_CRITICAL_SECTIONS
2412 basetree::nodeTable.dcs.DCSName=
"StringTree";
2424 : basetree( pRecycler, pathSeparator )
2426 #if ALIB_DEBUG_CRITICAL_SECTIONS
2427 basetree::nodeTable.dcs.DCSName=
"StringTree";
2438 for(
auto&
node : basetree::nodeTable )
2439 TNodeHandler::FreeNode( *
this, *
static_cast<baseNode*
>(&
node) );
2442 "The root node's value object was set but not deleted before destruction of this StringTree.\n"
2443 "Possible memory leak! To suppress this warning call DestructRootValue() before destruction.\n"
2444 "In case this is not necessary (because the stored type does not leak if not destructed),\n"
2445 "emplace it in macro ALIB_DBG() to remove the call in release compilations." )
2455 {
return basetree::nodeTable.GetAllocator(); }
2462 {
return basetree::separator; }
2464 #if ALIB_DEBUG_CRITICAL_SECTIONS
2468 void DbgSetDCSName(
const char* name)
const { basetree::nodeTable.dcs.DCSName= name; }
2486 template<
typename... TArgs>
2491 "Root node value is set without prior deletion. Possible memory leak (depending on\n "
2492 "allocation of template type T). This warning is only printed on the first overwrite.")
2493 ++basetree::dbgRootDataSet;
2496 new (&basetree::root.root.data) T( std::forward<TArgs>(args)... );
2509 "Deletion of root node data without prior setting (or double deletion)." )
2510 --basetree::dbgRootDataSet;
2512 basetree::root.root.data.~T();
2528 for(
auto&
node : basetree::nodeTable )
2529 TNodeHandler::FreeNode( *
this, *
static_cast<baseNode*
>(&
node) );
2530 basetree::nodeTable.Clear();
2533 basetree::root.root.children.reset();
2534 basetree::root.root.qtyChildren= 0;
2554 for(
auto&
node : basetree::nodeTable )
2555 TNodeHandler::FreeNode( *
this, *
static_cast<baseNode*
>(&
node) );
2558 basetree::nodeTable.Reset();
2559 basetree::root.root.children.reset();
2560 basetree::root.root.qtyChildren= 0;
2577 {
return basetree::nodeTable.RecyclablesCount(); }
2588 {
return basetree::nodeTable.Size(); }
2596 {
return basetree::nodeTable.Size() == 0; }
2610 { basetree::nodeTable.ReserveRecyclables( qty, reference ); }
2620 {
return basetree::nodeTable; }
2630 {
return basetree::nodeTable; }
2637 {
return Cursor(
this, &(basetree::root.
root) ); }
2650 {
return Cursor(
this,
reinterpret_cast<typename basetree::Node*
>(handle.
value) ); }
2656 {
return Cursor(
this,
reinterpret_cast<typename basetree::Node*
>(handle.
value) ); }
2659 #if ALIB_DEBUG_CRITICAL_SECTIONS
2672template<
typename TChar,
integer TLocalCapacity= 32>
2676template<
typename TChar>
2680template<
typename TChar>
2684template<
typename TAllocator,
2687 Recycling TRecycling = Recycling::Private >
strings::TAString< typename cmTree::CharacterType, lang::HeapAllocator > & AssemblePath(strings::TAString< typename cmTree::CharacterType, lang::HeapAllocator > &targetString, lang::CurrentData targetData=lang::CurrentData::Clear) const
TCursor CreateChild(const NameType &childName, TArgs &&... args) const
TCursor() noexcept=default
void dbgCheckTree() const
const T & operator*() const
TCursor & operator=(TCursor &&) noexcept=default
bool DeleteChild(const NameType &childName) const
std::pair< TCursor, SubstringType > operator()(const NameType &path) const
std::pair< TCursor, bool > CreateChildIfNotExistent(const NameType &name, TArgs &&... args)
const NameType & Name() const
ATMP_IF_T_F(!TConst, StringTree, const StringTree) TStringTree
bool operator!=(const TCursor &other) const
bool GoToCreateChildIfNotExistent(const NameType &name, TArgs &&... args)
uinteger DeleteChildren() const
bool HasNextSibling() const
SubstringType GoTo(const NameType &path)
ATMP_IF_T_F(!TConst, basetree, const basetree) cmTree
TCursor LastChild() const
uinteger CountChildren() const
TCursor NextSibling() const
TCursor FirstChild() const
ConstCursorHandle Export() const
int Distance(const TCursor< true > &other) const
TCursor & operator=(const TCursor &) noexcept=default
TCursor(cmTree *pTree, cmNode *pNode) noexcept
TCursor Child(const NameType &name) const
bool HasPreviousSibling() const
std::pair< TCursor, integer > CreatePathIfNotExistent(const NameType &path, TArgs &&... args)
bool operator==(const TCursor &other) const
const T * operator->() const
integer GoToCreatedPathIfNotExistent(const NameType &path, TArgs &&... args)
TCursor PreviousSibling() const
ATMP_IF_T_F(!TConst, baseNode, const baseNode) cmNode
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
bool GoToChild(const NameType &name)
TCursor(TCursor &&src) noexcept
void DeleteChild(TCursor &child) const
void dbgCheckTreeAndNode() const
ATMP_IF_T_F(!TConst, baseCursor, baseConstCursor) cmCursor
bool GoToPreviousSibling()
cmTree * tree
The StringTree this iterator belongs to.
ATMP_IF_T_F(!TConst, baseNodeBase, const baseNodeBase) cmNodeBase
const NameType & CurrentPath() const
void Initialize(cmCursor cursor, unsigned int depth=(std::numeric_limits< unsigned int >::max)())
ATMP_IF_T_F(!TConst, Cursor, ConstCursor) cmCursor
void SetSorting(lang::SortOrder order=lang::SortOrder::Ascending, lang::Case sensitivity=lang::Case::Ignore)
AString & FullPath(AString &target, lang::CurrentData targetData=lang::CurrentData::Clear) const
void initialize(cmTree *pTree, cmNode *newnode, unsigned int depth)
void SetSorting(lang::Switch sorting)
void Initialize(cmTree &pTree, unsigned int depth=(std::numeric_limits< unsigned int >::max)())
ATMP_IF_T_F(!TConst, StringTree, const StringTree) cmTree
ATMP_IF_T_F(!TConst, baseNode, const baseNode) cmNode
void Initialize(const TRecursiveIterator &other, unsigned int depth=(std::numeric_limits< unsigned int >::max)())
cmNode * node
The pointer to the actual node.
int RequestedDepth() const
void SetSorting(bool(*customSorterFunction)(const Cursor &, const Cursor &))
TNodeHandler HandlerType
Type definition publishing template parameter TNodeHandler.
typename TNodeHandler::CharacterType CharacterType
const auto & NodeTable() const
AllocatorType & GetAllocator() noexcept
TAllocator AllocatorType
Type definition publishing template parameter TAllocator.
integer RecyclablesCount() const
void ConstructRootValue(TArgs &&... args)
const ConstCursor Root() const
TCursor< false > Cursor
The mutable version of type StringTree::TCursor<TConst>.
StringTree(AllocatorType &allocator, CharacterType pathSeparator)
StringTree(CharacterType pathSeparator, TSharedRecycler &pRecycler)
Cursor createCursor(baseNode &node)
ConstCursor ImportCursor(ConstCursorHandle handle)
void DbgSetDCSName(const char *name) const
TCursor< true > ConstCursor
The constant version of type StringTree::TCursor<TConst>.
typename strings::TSubstring< CharacterType > SubstringType
constexpr CharacterType Separator() const noexcept
void ReserveRecyclables(integer qty, lang::ValueReference reference)
Cursor ImportCursor(CursorHandle handle)
typename basetree::SharedRecyclerType SharedRecyclerType
TChar CharAtStart() const
#define ATMP_IF_T_F( Cond, T, F)
#define ALIB_WARNING(...)
#define ALIB_ASSERT_MODULE(modulename)
#define ATMP_ISOF( T, TBase)
#define ATMP_EQ( T, TEqual)
#define ALIB_ASSERT_ERROR(cond,...)
#define ALIB_ASSERT_WARNING(cond,...)
#define ALIB_ASSERT(cond)
#define ATMP_T_IF(T, Cond)
ALIB_API uinteger DBG_STATS_STRINGTREE_NAMES
ALIB_API uinteger DBG_STATS_STRINGTREE_NAME_OVERFLOWS
ValueReference
Denotes if a value is interpreted as an absolute or relative number.
Switch
Denotes if sth. is switched on or off.
SortOrder
Denotes sort order.
@ Clear
Chooses to clear existing data.
Case
Denotes upper and lower case character treatment.
lang::uinteger uinteger
Type alias in namespace alib.
constexpr const String EMPTY_STRING
An empty string of the default character type.
characters::character character
Type alias in namespace alib.
constexpr String NULL_STRING
A nulled string of the default character type.
lang::integer integer
Type alias in namespace alib.
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.
ATMP_IF_T_F((TLocalCapacity > 0), strings::TLocalString< TChar ALIB_COMMA TLocalCapacity ALIB_COMMA lang::HeapAllocator >, strings::TString< TChar >) NameStringType
The string-type of a node's name.
static void InitializeNode(TTree &tree, typename TTree::Node &node)
TChar CharacterType
The character type that the StringTree uses for child name and path strings.
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.
static void FreeNode(TTree &tree, typename TTree::Node &node)
A handle type used with methods TCursor::Export and ImportCursor.
bool IsValid() const noexcept
bool operator==(const ConstCursorHandle &other) const noexcept
uinteger value
The encapsulated value.
bool operator==(const CursorHandle &other) const noexcept
A handle type used with methods TCursor::Export and ImportCursor.
bool IsValid() const noexcept
uinteger value
The encapsulated value.
bool operator==(const CursorHandle &other) const noexcept
Protected, internal struct used to store the data of recursive iterations.
union alib::containers::StringTree::TRecursiveIterator::RecursionData::@1 actChild
lang::BidiListHook< baseNodeBase > * childrenUnsorted
std::vector< cmNode * > childrenSorted
A pointer to a dynamically allocated vector of children used with sorting.
RecursionData() noexcept=default
Trivial default constructor.
bool sortingIsCaseSensitive
bool checkChildName(const NameType &name) const
RootNodeSpacer root
The root node.
HashTable< TAllocator, typename NodeKey::ValueDescriptor, typename NodeKey::Hash, typename NodeKey::EqualTo, lang::Caching::Enabled, TRecycling > nodeTable
TNode hook
The root node. Points twice to itself when the list is empty.
Node root
Full version of the root node, without initialization of member T.