97template<
typename TChar=
character,
integer TLocalCapacity= 32>
105 strings::TString <TChar> >;
121 template<
typename TTree>
127 if constexpr (TLocalCapacity <= 0) {
129 node.name.key.CopyTo( buffer );
135 node.name.storage.DbgDisableBufferReplacementWarning();
136 ALIB_DBG(
const TChar* internalBuffer= node.name.storage.Buffer(); )
137 node.name.storage.Append(key);
139 if( internalBuffer != node.name.storage.Buffer() )
156 template<
typename TTree>
158 void FreeNode(
typename TTree::Node& node, TTree& tree ) {
160 if constexpr (TLocalCapacity <= 0)
161 delete[] node.name.key.Buffer();
163 node.name.storage.~TLocalString();
192template<
typename TChar=
character>
216 template<
typename TTree>
218 void InitializeNode(
typename TTree::Node& node, TTree& tree ) { (void) node; (void) tree; }
236 template<
typename TTree>
238 void FreeNode( TTree::Node& node, TTree& tree ) { (void) node; (void) tree; }
268template<
typename TChar=
character>
294 template<
typename TTree>
297 { node.name.storage.Allocate( tree.nodeTable.GetAllocator(), node.name.key ); }
315 template<
typename TTree>
317 void FreeNode(
typename TTree::baseNode& node, TTree& tree ) { (void) node; (void) tree; }
566template<
typename TAllocator,
569 Recycling TRecycling = Recycling::Private>
578 using baseNodeKey =
typename basetree::NodeKey;
579 using baseNodeBase =
typename basetree::NodeBase;
580 using baseNode =
typename basetree::Node;
581 using baseCursor =
typename basetree::CursorBase;
582 using baseConstCursor =
typename basetree::ConstCursorBase;
662 {
return value==other.value; }
699 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>;
739 "Invalid StringTree::Cursor: No binding with a StringTree. "
740 "(Probably default-constructed.)")
748 "Invalid StringTree::Cursor not representing a node of the assigned tree." )
755 using TStringTree = std::conditional_t<!TConst, StringTree, const StringTree>;
766 :
TCursor{ src.node, src.tree } {}
771 :
TCursor{ src.node, src.tree } {}
795 return cmCursor::node == other.node
796 && cmCursor::tree == other.tree;
836 bool IsValid()
const {
return cmCursor::node !=
nullptr; }
850 return TCursor(cmCursor::tree, &cmCursor::tree->
root.root);
857 cmCursor::node = &cmCursor::tree->root.root;
871 return TCursor(
static_cast<cmNode*
>(cmCursor::node->parent), cmCursor::tree);
880 cmCursor::node =
static_cast<cmNode*
>(cmCursor::node->parent);
905 cmCursor::node =
static_cast<cmNode*
>(cmCursor::node->next());
908 cmCursor::node =
nullptr;
932 cmCursor::node=
static_cast<cmNode*
>(cmCursor::node->prev());
935 cmCursor::node=
nullptr;
957 cmCursor::node=
static_cast<cmNode*
>(cmCursor::node->children.first());
960 cmCursor::node=
nullptr;
983 cmCursor::node=
static_cast<cmNode*
>(cmCursor::node->children.last());
986 cmCursor::node=
nullptr;
1004 return TCursor(
static_cast<cmNode*
>(cmCursor::node->findChild(cmCursor::tree, name)),
1024 cmNode* child=
static_cast<cmNode*
>(cmCursor::node->findChild( cmCursor::tree, name ));
1026 cmCursor::node= child;
1048 template<
typename... TArgs>
1050 TArgs&&... args ) {DCS
1053 return std::make_pair(
TCursor(cmCursor::tree,
nullptr),
true );
1055 auto result= cmCursor::node->findOrCreateChild( cmCursor::tree, name,
1056 std::forward<TArgs>(args)... );
1058 return std::make_pair(
TCursor( cmCursor::tree, result.first ), result.second );
1075 template<
typename... TArgs>
1079 cmCursor::node=
nullptr;
1083 auto result= cmCursor::node->findOrCreateChild( cmCursor::tree, name,
1084 std::forward<TArgs>(args)... );
1086 cmCursor::node=
static_cast<cmNode*
>(result.first);
1087 return result.second;
1130 cmNode* grandChild= cmCursor::followPath( remainingPath );
1131 return std::make_pair(
TCursor(grandChild, cmCursor::tree), remainingPath );
1142 cmCursor::node= cmCursor::followPath( remainingPath );
1143 return remainingPath;
1159 template<
typename... TArgs>
1161 TArgs&&... args ) {DCS
1164 "STRINGTREE",
"Invalid StringTree::Cursor given with relative path addressing." )
1166 auto result= cmCursor::followPathCreate( path, std::forward<TArgs>(args)... );
1168 return std::make_pair(
TCursor(
static_cast<cmNode*
>(result.first), cmCursor::tree),
1185 template<
typename... TArgs>
1187 TArgs&&... args ) {DCS
1190 "STRINGTREE",
"Invalid StringTree::Cursor given with relative path addressing." )
1192 auto result= cmCursor::followPathCreate( path, std::forward<TArgs>(args)... );
1193 cmCursor::node=
static_cast<cmNode*
>(result.first);
1194 return result.second;
1210 template<
typename TParent= StringTree>
1211 requires std::derived_from<TParent, StringTree>
1221 template<
bool TRequires= !TConst>
1226 "Root node has no value. Either this operation is unwanted or root node's value\n"
1227 "has to be explicitly set using ConstructRootValue(...)" )
1228 return static_cast<baseNode*
>(cmCursor::node)->data;
1238 "Root node has no value. Either this operation is unwanted or root node's value\n"
1239 "has to be explicitly set using ConstructRootValue(...)" )
1240 return static_cast<const baseNode*
>(cmCursor::node)->data;
1249 template<
bool TRequires= !TConst>
1254 "Root node has no value. Either this operation is unwanted or root node's value\n"
1255 "has to be explicitly set using ConstructRootValue(...)" )
1256 return &
static_cast<baseNode*
>(cmCursor::node)->data;
1265 "Root node has no value. Either this operation is unwanted or root node's value\n"
1266 "has to be explicitly set using ConstructRootValue(...)" )
1267 return &
static_cast<const baseNode*
>(cmCursor::node)->data;
1276 template<
bool TRequires= !TConst>
1281 "Root node has no value. Either this operation is unwanted or root node's value\n"
1282 "has to be explicitly set using ConstructRootValue(...)" )
1283 return static_cast<baseNode*
>(cmCursor::node)->data;
1293 "Root node has no value. Either this operation is unwanted or root node's value\n"
1294 "has to be explicitly set using ConstructRootValue(...)" )
1295 return static_cast<const baseNode*
>(cmCursor::node)->data;
1309 return cmCursor::node->depth();
1328 "Given node belongs to a different StringTree." )
1329 return cmCursor::node->distance( other.node );
1337 return cmCursor::node->qtyChildren != 0;
1346 return cmCursor::node->qtyChildren;
1356 && !cmCursor::node->parent->children.isLast( cmCursor::node );
1366 && !cmCursor::node->parent->children.isFirst( cmCursor::node );
1396 targetString.
Reset();
1398 return cmCursor::node->assemblePath( targetString, cmCursor::node,
nullptr,
1426 targetString.
Reset();
1427 return cmCursor::node->assemblePath( targetString, cmCursor::node, parent.node,
1428 cmCursor::tree->separator );
1458 template<
typename TCheck =
CHK,
typename... TArgs>
1461 if constexpr ( TCheck::value ) {
1464 ALIB_WARNING(
"STRINGTREE",
"Illegal child name \"{}\"", childName )
1465 return Cursor(
nullptr, baseCursor::tree );
1469 if( baseCursor::node->qtyChildren > 0
1470 && baseCursor::tree->
nodeTable.Contains( baseNodeKey( baseCursor::node, childName) ))
1471 return Cursor(
nullptr, baseCursor::tree );
1474 baseNode* child= &baseCursor::tree->nodeTable.EmplaceUnique( baseCursor::node, childName,
1475 std::forward<TArgs>(args)... )
1477 TNodeHandler::InitializeNode( *child, *baseCursor::tree );
1479 baseCursor::node->children.pushEnd( child );
1480 ++baseCursor::node->qtyChildren;
1481 return TCursor( child, baseCursor::tree );
1497 if( baseCursor::node->qtyChildren == 0 )
1500 auto handle= baseCursor::tree->nodeTable.Extract( baseNodeKey( baseCursor::node, childName) );
1501 if( handle.IsEmpty() )
1503 handle.Value().deleteChildren( baseCursor::tree );
1504 TNodeHandler::FreeNode( handle.Value(), *baseCursor::tree );
1505 handle.Value().remove();
1507 --baseCursor::node->qtyChildren;
1528 cmNode* nodeToDelete= child.node;
1530 return baseCursor::node->deleteChild( baseCursor::tree, nodeToDelete );
1540 return baseCursor::node->deleteChildren( baseCursor::tree );
1562 if( baseCursor::node->isRoot() )
1563 return baseCursor::node->deleteChildren( baseCursor::tree );
1565 cmNode * child= baseCursor::node;
1566 baseCursor::node=
static_cast<cmNode*
>(baseCursor::node->parent);
1567 return baseCursor::node->deleteChild( baseCursor::tree, child );
1589 #if ALIB_DEBUG_CRITICAL_SECTIONS
1592 #define DCS ALIB_DCS_WITH(basetree::nodeTable.dcs)
1593 #define DCSSHRD ALIB_DCS_SHARED_WITH(basetree::nodeTable.dcs)
1601 : basetree( allocator, pathSeparator ) {
1602 #if ALIB_DEBUG_CRITICAL_SECTIONS
1603 basetree::nodeTable.dcs.DCSName=
"StringTree";
1610 template<
typename TSharedRecycler= SharedRecyclerType>
1611 requires(!std::same_as<TSharedRecycler, void>)
1613 : basetree( pRecycler, pathSeparator ) {
1614 #if ALIB_DEBUG_CRITICAL_SECTIONS
1615 basetree::nodeTable.dcs.DCSName=
"StringTree";
1622 for(
auto& node : basetree::nodeTable )
1623 TNodeHandler::FreeNode( *
static_cast<baseNode*
>(&node), *
this );
1626 "Possible memory leak! The root node's value object was set but not deleted before\n"
1627 "destruction of this StringTree. To suppress this warning call DestructRootValue()\n"
1628 "before destruction. In case this is not necessary (because the stored type does not\n"
1629 "leak if not destructed), emplace it in macro ALIB_DBG() to remove the call in\n"
1639 #if ALIB_DEBUG_CRITICAL_SECTIONS
1653 #if ALIB_DEBUG_CRITICAL_SECTIONS
1657 void DbgSetDCSName(
const char* name)
const { basetree::nodeTable.dcs.DCSName= name; }
1673 template<
typename... TArgs>
1677 "Root node value is set without prior deletion. Possible memory leak (depending on\n "
1678 "allocation of template type T). This warning is only printed on the first overwrite.")
1679 ++basetree::dbgRootDataSet;
1682 new (&basetree::root.root.data) T( std::forward<TArgs>(args)... );
1692 "Deletion of root node data without prior setting (or double deletion)." )
1693 --basetree::dbgRootDataSet;
1695 basetree::root.root.data.~T();
1708 for(
auto& node : basetree::nodeTable )
1709 TNodeHandler::FreeNode( *
static_cast<baseNode*
>(&node), *
this );
1710 basetree::nodeTable.Clear();
1713 basetree::root.root.children.reset();
1714 basetree::root.root.qtyChildren= 0;
1730 for(
auto& node : basetree::nodeTable )
1731 TNodeHandler::FreeNode( *
static_cast<baseNode*
>(&node), *
this );
1734 basetree::nodeTable.Reset();
1735 basetree::root.root.children.reset();
1736 basetree::root.root.qtyChildren= 0;
1763 bool IsEmpty()
const {
return basetree::nodeTable.Size() == 0; }
1775 { basetree::nodeTable.ReserveRecyclables( qty, reference ); }
1789 const auto&
NodeTable()
const {
return basetree::nodeTable; }
1803 {
return Cursor(
reinterpret_cast<basetree::Node*
>(handle.value),
this ); }
1809 {
return ConstCursor(
reinterpret_cast<basetree::Node*
>(handle.value),
this ); }
1812 #if ALIB_DEBUG_CRITICAL_SECTIONS
1823template<
typename TChar,
integer TLocalCapacity= 32>
1827template<
typename TChar>
1831template<
typename TChar>
1835template<
typename TAllocator,
1838 Recycling TRecycling = Recycling::Private >
#define ALIB_WARNING(domain,...)
#define ALIB_ASSERT_WARNING(cond, domain,...)
#define ALIB_ASSERT_ERROR(cond, domain,...)
TCursor() noexcept=default
SubstringType GoTo(const NameType &path)
int Distance(const TCursor< true > &other) const
TCursor NextSibling() const
TCursor(cmNode *pNode, cmTree *pTree) noexcept
bool operator!=(const TCursor &other) const
std::pair< TCursor, SubstringType > operator()(const NameType &path) const
TCursor & operator=(const TCursor &) noexcept=default
int GoToCreatedPathIfNotExistent(const NameType &path, TArgs &&... args)
const T * operator->() const
void dbgCheckTree() const
TCursor CreateChild(const NameType &childName, TArgs &&... args) const
std::conditional_t<!TConst, StringTree, const StringTree > TStringTree
parameter TConst
strings::TAString< typename cmTree::CharacterType, lang::HeapAllocator > & AssemblePath(strings::TAString< typename cmTree::CharacterType > &targetString, const TCursor< true > &parent, lang::CurrentData targetData=lang::CurrentData::Clear) const
const T & operator*() const
uinteger DeleteChild(TCursor &child) const
TCursor FirstChild() const
std::conditional_t<!TConst, basetree, const basetree > cmTree
TConst
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
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
std::conditional_t<!TConst, baseCursor, baseConstCursor > cmCursor
void dbgCheckTreeAndNode() 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
strings::TAString< typename cmTree::CharacterType, lang::HeapAllocator > & AssemblePath(strings::TAString< typename cmTree::CharacterType > &targetString, lang::CurrentData targetData=lang::CurrentData::Clear) const
void ReserveRecyclables(integer qty, lang::ValueReference reference)
integer RecyclablesCount() const
lang::DbgCriticalSections & DbgGetDCS() const
constexpr CharacterType Separator() const noexcept
const auto & NodeTable() const
TCursor< true > ConstCursor
The constant version of type #"%TCursor".
typename StringTreeNamesAlloc< character >::CharacterType CharacterType
Cursor ImportCursor(CursorHandle handle)
const ConstCursor Root() const
Cursor createCursor(baseNode &node)
typename strings::TSubstring< CharacterType > SubstringType
strings::TString< CharacterType > NameType
void DbgSetDCSName(const char *name) const
AllocatorType & GetAllocator() noexcept
TCursor< false > Cursor
The mutable version of type #"%TCursor".
StringTree(AllocatorType &allocator, CharacterType pathSeparator)
StringTreeNamesAlloc< character > HandlerType
StringTree(CharacterType pathSeparator, TSharedRecycler &pRecycler)
MonoAllocator AllocatorType
void ConstructRootValue(TArgs &&... args)
ConstCursor ImportCursor(ConstCursorHandle handle) const
typename basetree::SharedRecyclerType SharedRecyclerType
TChar CharAtStart() const
uinteger DBG_STATS_STRINGTREE_NAMES
uinteger DBG_STATS_STRINGTREE_NAME_OVERFLOWS
@ Clear
Chooses to clear existing data.
ValueReference
Denotes if a value is interpreted as an absolute or relative number.
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".
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 FreeNode(typename TTree::baseNode &node, TTree &tree)
static void InitializeNode(typename TTree::Node &node, TTree &tree)
TChar CharacterType
The character type that the #"%StringTree" uses for child name and path strings.
std::conditional_t<(TLocalCapacity > 0), strings::TLocalString< TChar, TLocalCapacity >, strings::TString< TChar > > NameStringType
The string-type of a node's name.
TChar CharacterType
The character type that the #"%StringTree" uses for child name and path strings.
static void InitializeNode(typename TTree::Node &node, TTree &tree)
static void FreeNode(typename TTree::Node &node, TTree &tree)
static void FreeNode(TTree::Node &node, TTree &tree)
TChar CharacterType
The character type that the #"%StringTree" uses for child name and path strings.
static void InitializeNode(typename TTree::Node &node, TTree &tree)
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
ConstCursorHandle(const CursorHandle &mutableHandle)
ConstCursorHandle()=default
Defaulted default constructor.
bool IsValid() const noexcept
uinteger value
The encapsulated value.
bool operator==(const ConstCursorHandle &other) const noexcept
ConstCursorHandle(uinteger pValue)
uinteger value
The encapsulated value.
bool IsValid() const noexcept
bool operator==(const CursorHandle &other) const noexcept
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