98template<
typename TChar=
character,
integer TLocalCapacity= 32>
107 strings::TString <TChar> >;
123 template<
typename TTree>
129 if constexpr (TLocalCapacity <= 0) {
131 node.name.key.CopyTo( buffer );
137 node.name.storage.DbgDisableBufferReplacementWarning();
138 ALIB_DBG(
const TChar* internalBuffer= node.name.storage.Buffer(); )
139 node.name.storage.Append(key);
141 if( internalBuffer != node.name.storage.Buffer() )
158 template<
typename TTree>
160 void FreeNode(
typename TTree::Node& node, TTree& tree ) {
162 if constexpr (TLocalCapacity <= 0)
163 delete[] node.name.key.Buffer();
165 node.name.storage.~TLocalString();
195template<
typename TChar=
character>
220 template<
typename TTree>
222 void InitializeNode(
typename TTree::Node& node, TTree& tree ) { (void) node; (void) tree; }
240 template<
typename TTree>
242 void FreeNode( TTree::Node& node, TTree& tree ) { (void) node; (void) tree; }
273template<
typename TChar=
character>
300 template<
typename TTree>
303 { node.name.storage.Allocate( tree.nodeTable.GetAllocator(), node.name.key ); }
321 template<
typename TTree>
323 void FreeNode(
typename TTree::baseNode& node, TTree& tree ) { (void) node; (void) tree; }
570template<
typename TAllocator,
573 Recycling TRecycling = Recycling::Private>
583 using baseNodeKey =
typename basetree::NodeKey;
584 using baseNodeBase =
typename basetree::NodeBase;
585 using baseNode =
typename basetree::Node;
586 using baseCursor =
typename basetree::CursorBase;
587 using baseConstCursor =
typename basetree::ConstCursorBase;
658 {
return value==other.value; }
694 template<
bool TConst>
702 #if ALIB_DEBUG_CRITICAL_SECTIONS
703 #define DCS ALIB_DCS_WITH(cmCursor::tree->nodeTable.dcs)
704 #define DCSSHRD ALIB_DCS_SHARED_WITH(cmCursor::tree->nodeTable.dcs)
714 using cmTree = std::conditional_t<!TConst, basetree, const basetree>;
718 using cmNode = std::conditional_t<!TConst, baseNode, const baseNode>;
722 using cmCursor = std::conditional_t<!TConst, baseCursor, baseConstCursor>;
735 "Invalid StringTree::Cursor: No binding with a StringTree. "
736 "(Probably default-constructed.)")
744 "Invalid StringTree::Cursor not representing a node of the assigned tree." )
751 using TStringTree = std::conditional_t<!TConst, StringTree, const StringTree>;
762 :
TCursor{ src.node, src.tree } {}
767 :
TCursor{ src.node, src.tree } {}
791 return cmCursor::node == other.node
792 && cmCursor::tree == other.tree;
832 bool IsValid()
const {
return cmCursor::node !=
nullptr; }
846 return TCursor(cmCursor::tree, &cmCursor::tree->
root.root);
853 cmCursor::node = &cmCursor::tree->root.root;
867 return TCursor(
static_cast<cmNode*
>(cmCursor::node->parent), cmCursor::tree);
876 cmCursor::node =
static_cast<cmNode*
>(cmCursor::node->parent);
901 cmCursor::node =
static_cast<cmNode*
>(cmCursor::node->next());
904 cmCursor::node =
nullptr;
928 cmCursor::node=
static_cast<cmNode*
>(cmCursor::node->prev());
931 cmCursor::node=
nullptr;
953 cmCursor::node=
static_cast<cmNode*
>(cmCursor::node->children.first());
956 cmCursor::node=
nullptr;
979 cmCursor::node=
static_cast<cmNode*
>(cmCursor::node->children.last());
982 cmCursor::node=
nullptr;
1000 return TCursor(
static_cast<cmNode*
>(cmCursor::node->findChild(cmCursor::tree, name)),
1020 cmNode* child=
static_cast<cmNode*
>(cmCursor::node->findChild( cmCursor::tree, name ));
1022 cmCursor::node= child;
1044 template<
typename... TArgs>
1046 TArgs&&... args ) {DCS
1049 return std::make_pair(
TCursor(cmCursor::tree,
nullptr),
true );
1051 auto result= cmCursor::node->findOrCreateChild( cmCursor::tree, name,
1052 std::forward<TArgs>(args)... );
1054 return std::make_pair(
TCursor( cmCursor::tree, result.first ), result.second );
1071 template<
typename... TArgs>
1075 cmCursor::node=
nullptr;
1079 auto result= cmCursor::node->findOrCreateChild( cmCursor::tree, name,
1080 std::forward<TArgs>(args)... );
1082 cmCursor::node=
static_cast<cmNode*
>(result.first);
1083 return result.second;
1126 cmNode* grandChild= cmCursor::followPath( remainingPath );
1127 return std::make_pair(
TCursor(grandChild, cmCursor::tree), remainingPath );
1140 cmCursor::node= cmCursor::followPath( remainingPath );
1141 return remainingPath;
1158 template<
typename... TArgs>
1160 TArgs&&... args ) {DCS
1163 "STRINGTREE",
"Invalid StringTree::Cursor given with relative path addressing." )
1165 auto result= cmCursor::followPathCreate( path, std::forward<TArgs>(args)... );
1167 return std::make_pair(
TCursor(
static_cast<cmNode*
>(result.first), cmCursor::tree),
1184 template<
typename... TArgs>
1186 TArgs&&... args ) {DCS
1189 "STRINGTREE",
"Invalid StringTree::Cursor given with relative path addressing." )
1191 auto result= cmCursor::followPathCreate( path, std::forward<TArgs>(args)... );
1192 cmCursor::node=
static_cast<cmNode*
>(result.first);
1193 return result.second;
1209 template<
typename TParent= StringTree>
1210 requires std::derived_from<TParent, StringTree>
1220 template<
bool TRequires= !TConst>
1225 "Root node has no value. Either this operation is unwanted or root node's value\n"
1226 "has to be explicitly set using ConstructRootValue(...)" )
1227 return static_cast<baseNode*
>(cmCursor::node)->data;
1237 "Root node has no value. Either this operation is unwanted or root node's value\n"
1238 "has to be explicitly set using ConstructRootValue(...)" )
1239 return static_cast<const baseNode*
>(cmCursor::node)->data;
1248 template<
bool TRequires= !TConst>
1253 "Root node has no value. Either this operation is unwanted or root node's value\n"
1254 "has to be explicitly set using ConstructRootValue(...)" )
1255 return &
static_cast<baseNode*
>(cmCursor::node)->data;
1264 "Root node has no value. Either this operation is unwanted or root node's value\n"
1265 "has to be explicitly set using ConstructRootValue(...)" )
1266 return &
static_cast<const baseNode*
>(cmCursor::node)->data;
1275 template<
bool TRequires= !TConst>
1280 "Root node has no value. Either this operation is unwanted or root node's value\n"
1281 "has to be explicitly set using ConstructRootValue(...)" )
1282 return static_cast<baseNode*
>(cmCursor::node)->data;
1292 "Root node has no value. Either this operation is unwanted or root node's value\n"
1293 "has to be explicitly set using ConstructRootValue(...)" )
1294 return static_cast<const baseNode*
>(cmCursor::node)->data;
1308 return cmCursor::node->depth();
1327 "Given node belongs to a different StringTree." )
1328 return cmCursor::node->distance( other.node );
1336 return cmCursor::node->qtyChildren != 0;
1345 return cmCursor::node->qtyChildren;
1355 && !cmCursor::node->parent->children.isLast( cmCursor::node );
1365 && !cmCursor::node->parent->children.isFirst( cmCursor::node );
1395 targetString.
Reset();
1397 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";
1623 for(
auto& node : basetree::nodeTable )
1624 TNodeHandler::FreeNode( *
static_cast<baseNode*
>(&node), *
this );
1627 "Possible memory leak! The root node's value object was set but not deleted before\n"
1628 "destruction of this StringTree. To suppress this warning call DestructRootValue()\n"
1629 "before destruction. In case this is not necessary (because the stored type does not\n"
1630 "leak if not destructed), emplace it in macro ALIB_DBG() to remove the call in\n"
1640 #if ALIB_DEBUG_CRITICAL_SECTIONS
1654 #if ALIB_DEBUG_CRITICAL_SECTIONS
1658 void DbgSetDCSName(
const char* name)
const { basetree::nodeTable.dcs.DCSName= name; }
1674 template<
typename... TArgs>
1678 "Root node value is set without prior deletion. Possible memory leak (depending on\n "
1679 "allocation of template type T). This warning is only printed on the first overwrite.")
1680 ++basetree::dbgRootDataSet;
1683 new (&basetree::root.root.data) T( std::forward<TArgs>(args)... );
1693 "Deletion of root node data without prior setting (or double deletion)." )
1694 --basetree::dbgRootDataSet;
1696 basetree::root.root.data.~T();
1709 for(
auto& node : basetree::nodeTable )
1710 TNodeHandler::FreeNode( *
static_cast<baseNode*
>(&node), *
this );
1711 basetree::nodeTable.Clear();
1714 basetree::root.root.children.reset();
1715 basetree::root.root.qtyChildren= 0;
1732 for(
auto& node : basetree::nodeTable )
1733 TNodeHandler::FreeNode( *
static_cast<baseNode*
>(&node), *
this );
1736 basetree::nodeTable.Reset();
1737 basetree::root.root.children.reset();
1738 basetree::root.root.qtyChildren= 0;
1765 bool IsEmpty()
const {
return basetree::nodeTable.Size() == 0; }
1777 { basetree::nodeTable.ReserveRecyclables( qty, reference ); }
1791 const auto&
NodeTable()
const {
return basetree::nodeTable; }
1805 {
return Cursor(
reinterpret_cast<typename basetree::Node*
>(handle.value),
this ); }
1811 {
return ConstCursor(
reinterpret_cast<typename basetree::Node*
>(handle.value),
this ); }
1814 #if ALIB_DEBUG_CRITICAL_SECTIONS
1825template<
typename TChar,
integer TLocalCapacity= 32>
1829template<
typename TChar>
1833template<
typename TChar>
1837template<
typename TAllocator,
1840 Recycling TRecycling = Recycling::Private >
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
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
uinteger DeleteChild(TCursor &child) 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
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<TConst>.
typename StringTreeNamesAlloc< character >::CharacterType CharacterType
Cursor ImportCursor(CursorHandle handle)
const ConstCursor Root() const
Cursor createCursor(baseNode &node)
StringTree(CharacterType pathSeparator, TSharedRecycler &pRecycler)
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<TConst>.
StringTree(AllocatorType &allocator, CharacterType pathSeparator)
StringTreeNamesAlloc< character > HandlerType
typename basetree::SharedRecyclerType SharedRecyclerType
MonoAllocator AllocatorType
void ConstructRootValue(TArgs &&... args)
ConstCursor ImportCursor(ConstCursorHandle handle) const
TChar CharAtStart() const
#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
@ 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.
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.
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)
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
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