11#ifndef INCLUDED_BALL_CATEGORYMANAGER_RADIXTREE_CPP03
12#define INCLUDED_BALL_CATEGORYMANAGER_RADIXTREE_CPP03
63#ifdef COMPILING_BALL_CATEGORYMANAGER_RADIXTREE_H
79template <
class t_VALUE>
80class CategoryManager_RadixTree_Node {
116 const CategoryManager_RadixTree_Node& original);
122 const CategoryManager_RadixTree_Node& original,
151 const CategoryManager_RadixTree_Node& rhs);
177 void swap(CategoryManager_RadixTree_Node& other);
208template <
class t_VALUE>
209bool operator==(
const CategoryManager_RadixTree_Node<t_VALUE>& lhs,
210 const CategoryManager_RadixTree_Node<t_VALUE>& rhs);
214template <
class t_VALUE>
215bool operator!=(
const CategoryManager_RadixTree_Node<t_VALUE>& lhs,
216 const CategoryManager_RadixTree_Node<t_VALUE>& rhs);
228template <
class t_VALUE>
229class CategoryManager_RadixTree_ChildNodeGuard {
232 typedef CategoryManager_RadixTree_Node<t_VALUE>
Node;
243 CategoryManager_RadixTree_ChildNodeGuard(
244 const CategoryManager_RadixTree_ChildNodeGuard&)
246 CategoryManager_RadixTree_ChildNodeGuard& operator=(
247 const CategoryManager_RadixTree_ChildNodeGuard&)
256 CategoryManager_RadixTree_ChildNodeGuard(
Node *parent,
282template <
class t_VALUE>
283class CategoryManager_RadixTree {
310 typedef CategoryManager_RadixTree_Node<t_VALUE> Node;
311 typedef CategoryManager_RadixTree_ChildNodeGuard<t_VALUE> ChildNodeGuard;
314#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
317#ifndef BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT
318#define BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT 10
320#ifndef BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A
321#define BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT
323#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 0
328#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 1
329 template <
class Args_01>
335#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 2
336 template <
class Args_01,
344#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 3
345 template <
class Args_01,
355#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 4
356 template <
class Args_01,
368#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 5
369 template <
class Args_01,
383#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 6
384 template <
class Args_01,
400#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 7
401 template <
class Args_01,
419#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 8
420 template <
class Args_01,
440#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 9
441 template <
class Args_01,
463#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_A >= 10
464 template <
class Args_01,
491 template <
class... Args>
526 void cleanupChildAfterErase(
528 typename Node::Children::iterator it,
540 template <
class t_FUNCTOR>
541 static void forEachImp(
const Node *node,
543 const t_FUNCTOR& functor);
550 template <
class t_FUNCTOR>
551 static void forEachImp(Node *node,
553 const t_FUNCTOR& functor);
560 template <
class t_FUNCTOR>
561 static size_type forEachPrefixImp(Node *node,
563 const t_FUNCTOR& functor);
570 template <
class t_FUNCTOR>
571 static size_type forEachPrefixImp(
const Node *node,
573 const t_FUNCTOR& functor);
580 static void printNodeImp(bsl::ostream& stream,
593 template <
class t_TYPE>
594 friend bool operator==(
const CategoryManager_RadixTree<t_TYPE>&,
595 const CategoryManager_RadixTree<t_TYPE>&);
597 template <
class t_TYPE>
598 friend void swap(CategoryManager_RadixTree<t_TYPE>& a,
599 CategoryManager_RadixTree<t_TYPE>& b);
658#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
661#ifndef BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT
662#define BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT 10
664#ifndef BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B
665#define BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT
667#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 0
671#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 1
672 template <
class Args_01>
677#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 2
678 template <
class Args_01,
685#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 3
686 template <
class Args_01,
695#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 4
696 template <
class Args_01,
707#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 5
708 template <
class Args_01,
721#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 6
722 template <
class Args_01,
737#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 7
738 template <
class Args_01,
755#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 8
756 template <
class Args_01,
775#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 9
776 template <
class Args_01,
797#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_B >= 10
798 template <
class Args_01,
824 template <
class... Args>
875 template <
class t_FUNCTOR>
876 void forEach(
const t_FUNCTOR& functor);
884 template <
class t_FUNCTOR>
886 const t_FUNCTOR& functor);
936 template <
class t_FUNCTOR>
937 void forEach(
const t_FUNCTOR& functor)
const;
945 template <
class t_FUNCTOR>
947 const t_FUNCTOR& functor)
const;
962 bsl::ostream&
printNodes(bsl::ostream& stream,
964 int spacesPerLevel = 4)
const;
984template <
class t_VALUE>
985bool operator==(
const CategoryManager_RadixTree<t_VALUE>& lhs,
986 const CategoryManager_RadixTree<t_VALUE>& rhs);
992template <
class t_VALUE>
993bool operator!=(
const CategoryManager_RadixTree<t_VALUE>& lhs,
994 const CategoryManager_RadixTree<t_VALUE>& rhs);
1001template <
class t_VALUE>
1002void swap(CategoryManager_RadixTree<t_VALUE>& a,
1003 CategoryManager_RadixTree<t_VALUE>& b);
1014template <
class t_VALUE>
1016CategoryManager_RadixTree_ChildNodeGuard<t_VALUE>::
1017CategoryManager_RadixTree_ChildNodeGuard(Node *parent,
1018 ChildIterator child)
1027template <
class t_VALUE>
1029CategoryManager_RadixTree_ChildNodeGuard<t_VALUE>::
1030~CategoryManager_RadixTree_ChildNodeGuard()
1033 d_parent_p->children().erase(d_child);
1038template <
class t_VALUE>
1040void CategoryManager_RadixTree_ChildNodeGuard<t_VALUE>::release()
1050template <
class t_VALUE>
1052CategoryManager_RadixTree_Node<t_VALUE>::CategoryManager_RadixTree_Node(
1054 const allocator_type& allocator)
1055: d_prefix(prefix, allocator)
1057, d_children(allocator)
1061template <
class t_VALUE>
1063CategoryManager_RadixTree_Node<t_VALUE>::CategoryManager_RadixTree_Node(
1064 const CategoryManager_RadixTree_Node& original)
1065: d_prefix(original.d_prefix)
1066, d_value(original.d_value, allocator_type())
1067, d_children(original.d_children)
1071template <
class t_VALUE>
1073CategoryManager_RadixTree_Node<t_VALUE>::CategoryManager_RadixTree_Node(
1074 const CategoryManager_RadixTree_Node& original,
1075 const allocator_type& allocator)
1076: d_prefix(original.d_prefix, allocator)
1077, d_value(original.d_value, allocator)
1078, d_children(original.d_children, allocator)
1082template <
class t_VALUE>
1084CategoryManager_RadixTree_Node<t_VALUE>::CategoryManager_RadixTree_Node(
1089, d_value(allocator_type())
1098template <
class t_VALUE>
1100CategoryManager_RadixTree_Node<t_VALUE>::CategoryManager_RadixTree_Node(
1102 const allocator_type& allocator)
1103: d_prefix(
bslmf::MovableRefUtil::move(
1104 bslmf::MovableRefUtil::access(original).d_prefix),
1106, d_value(
bslmf::MovableRefUtil::move(
1107 bslmf::MovableRefUtil::access(original).d_value),
1109, d_children(
bslmf::MovableRefUtil::move(
1110 bslmf::MovableRefUtil::access(original).d_children),
1116template <
class t_VALUE>
1118CategoryManager_RadixTree_Node<t_VALUE>&
1119CategoryManager_RadixTree_Node<t_VALUE>::operator=(
1120 const CategoryManager_RadixTree_Node& rhs)
1124 CategoryManager_RadixTree_Node temp(rhs, get_allocator());
1130template <
class t_VALUE>
1132CategoryManager_RadixTree_Node<t_VALUE>&
1133CategoryManager_RadixTree_Node<t_VALUE>::operator=(
1136 CategoryManager_RadixTree_Node& lvalue =
rhs;
1137 if (
this != &lvalue) {
1138 if (get_allocator() == lvalue.get_allocator()) {
1144 CategoryManager_RadixTree_Node temp(lvalue, get_allocator());
1151template <
class t_VALUE>
1153typename CategoryManager_RadixTree_Node<t_VALUE>::Children&
1154CategoryManager_RadixTree_Node<t_VALUE>::children()
1159template <
class t_VALUE>
1161bsl::string& CategoryManager_RadixTree_Node<t_VALUE>::prefix()
1166template <
class t_VALUE>
1168CategoryManager_RadixTree_Node<t_VALUE>::swap(
1169 CategoryManager_RadixTree_Node& other)
1171 BSLS_ASSERT(get_allocator() == other.get_allocator());
1178template <
class t_VALUE>
1182 return d_value.object();
1186template <
class t_VALUE>
1188const typename CategoryManager_RadixTree_Node<t_VALUE>::Children&
1189CategoryManager_RadixTree_Node<t_VALUE>::children()
const
1194template <
class t_VALUE>
1196const bsl::string& CategoryManager_RadixTree_Node<t_VALUE>::prefix()
const
1201template <
class t_VALUE>
1204CategoryManager_RadixTree_Node<t_VALUE>::value()
const
1206 return d_value.object();
1211template <
class t_VALUE>
1213typename CategoryManager_RadixTree_Node<t_VALUE>::allocator_type
1214CategoryManager_RadixTree_Node<t_VALUE>::get_allocator()
const
1224#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
1227#ifndef BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT
1228#define BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT 10
1230#ifndef BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C
1231#define BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT
1233#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 0
1234template <
class t_VALUE>
1235typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
1236CategoryManager_RadixTree<t_VALUE>::emplaceImp(
1242 if (remainingKey.
empty()) {
1243 if (node->value().has_value()) {
1244 return EmplaceResult(
false, node->value().value());
1246 node->value().emplace();
1247 return EmplaceResult(
true, node->value().value());
1250 const char firstChar = remainingKey[0];
1251 typename Node::Children::iterator it = node->children().
find(firstChar);
1253 if (it == node->children().end()) {
1254 typename Node::Children::iterator iter =
1255 node->children().emplace(firstChar, remainingKey).first;
1256 ChildNodeGuard guard(node, iter);
1257 iter->second.value().emplace();
1259 return EmplaceResult(
true, iter->second.value().value());
1262 Node& child = it->second;
1265 size_type minLen = bsl::min(remainingKey.
size(), childPrefix.
size());
1267 bsl::mismatch(remainingKey.
begin(),
1268 remainingKey.
begin() + minLen,
1269 childPrefix.
begin())
1271 const size_type commonLen = mismatchPos - remainingKey.
begin();
1273 if (commonLen == childPrefix.
size()) {
1274 return emplaceImp(&child,
1275 remainingKey.
substr(commonLen));
1278 Node splitNode(childPrefix.
substr(0, commonLen), get_allocator());
1280 Node childCopy(child, get_allocator());
1281 childCopy.prefix() = childPrefix.
substr(commonLen);
1283 splitNode.children().emplace(childCopy.prefix()[0],
1286 if (commonLen == remainingKey.
size()) {
1287 splitNode.value().emplace();
1290 return EmplaceResult(
true,
1291 it->second.value().value());
1295 const typename Node::Children::iterator newIter =
1296 splitNode.children().emplace(newKey[0], newKey).first;
1297 newIter->second.value().emplace();
1300 return EmplaceResult(
true, newIter->second.value().value());
1304#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 1
1305template <
class t_VALUE>
1306template <
class Args_01>
1307typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
1308CategoryManager_RadixTree<t_VALUE>::emplaceImp(
1315 if (remainingKey.
empty()) {
1316 if (node->value().has_value()) {
1317 return EmplaceResult(
false, node->value().value());
1320 return EmplaceResult(
true, node->value().value());
1323 const char firstChar = remainingKey[0];
1324 typename Node::Children::iterator it = node->children().
find(firstChar);
1326 if (it == node->children().end()) {
1327 typename Node::Children::iterator iter =
1328 node->children().emplace(firstChar, remainingKey).first;
1329 ChildNodeGuard guard(node, iter);
1333 return EmplaceResult(
true, iter->second.value().value());
1336 Node& child = it->second;
1339 size_type minLen = bsl::min(remainingKey.
size(), childPrefix.
size());
1341 bsl::mismatch(remainingKey.
begin(),
1342 remainingKey.
begin() + minLen,
1343 childPrefix.
begin())
1345 const size_type commonLen = mismatchPos - remainingKey.
begin();
1347 if (commonLen == childPrefix.
size()) {
1348 return emplaceImp(&child,
1349 remainingKey.
substr(commonLen),
1353 Node splitNode(childPrefix.
substr(0, commonLen), get_allocator());
1355 Node childCopy(child, get_allocator());
1356 childCopy.prefix() = childPrefix.
substr(commonLen);
1358 splitNode.children().emplace(childCopy.prefix()[0],
1361 if (commonLen == remainingKey.
size()) {
1366 return EmplaceResult(
true,
1367 it->second.value().value());
1371 const typename Node::Children::iterator newIter =
1372 splitNode.children().emplace(newKey[0], newKey).first;
1377 return EmplaceResult(
true, newIter->second.value().value());
1381#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 2
1382template <
class t_VALUE>
1383template <
class Args_01,
1385typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
1386CategoryManager_RadixTree<t_VALUE>::emplaceImp(
1394 if (remainingKey.
empty()) {
1395 if (node->value().has_value()) {
1396 return EmplaceResult(
false, node->value().value());
1400 return EmplaceResult(
true, node->value().value());
1403 const char firstChar = remainingKey[0];
1404 typename Node::Children::iterator it = node->children().
find(firstChar);
1406 if (it == node->children().end()) {
1407 typename Node::Children::iterator iter =
1408 node->children().emplace(firstChar, remainingKey).first;
1409 ChildNodeGuard guard(node, iter);
1415 return EmplaceResult(
true, iter->second.value().value());
1418 Node& child = it->second;
1421 size_type minLen = bsl::min(remainingKey.
size(), childPrefix.
size());
1423 bsl::mismatch(remainingKey.
begin(),
1424 remainingKey.
begin() + minLen,
1425 childPrefix.
begin())
1427 const size_type commonLen = mismatchPos - remainingKey.
begin();
1429 if (commonLen == childPrefix.
size()) {
1430 return emplaceImp(&child,
1431 remainingKey.
substr(commonLen),
1436 Node splitNode(childPrefix.
substr(0, commonLen), get_allocator());
1438 Node childCopy(child, get_allocator());
1439 childCopy.prefix() = childPrefix.
substr(commonLen);
1441 splitNode.children().emplace(childCopy.prefix()[0],
1444 if (commonLen == remainingKey.
size()) {
1451 return EmplaceResult(
true,
1452 it->second.value().value());
1456 const typename Node::Children::iterator newIter =
1457 splitNode.children().emplace(newKey[0], newKey).first;
1464 return EmplaceResult(
true, newIter->second.value().value());
1468#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 3
1469template <
class t_VALUE>
1470template <
class Args_01,
1473typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
1474CategoryManager_RadixTree<t_VALUE>::emplaceImp(
1483 if (remainingKey.
empty()) {
1484 if (node->value().has_value()) {
1485 return EmplaceResult(
false, node->value().value());
1490 return EmplaceResult(
true, node->value().value());
1493 const char firstChar = remainingKey[0];
1494 typename Node::Children::iterator it = node->children().
find(firstChar);
1496 if (it == node->children().end()) {
1497 typename Node::Children::iterator iter =
1498 node->children().emplace(firstChar, remainingKey).first;
1499 ChildNodeGuard guard(node, iter);
1507 return EmplaceResult(
true, iter->second.value().value());
1510 Node& child = it->second;
1513 size_type minLen = bsl::min(remainingKey.
size(), childPrefix.
size());
1515 bsl::mismatch(remainingKey.
begin(),
1516 remainingKey.
begin() + minLen,
1517 childPrefix.
begin())
1519 const size_type commonLen = mismatchPos - remainingKey.
begin();
1521 if (commonLen == childPrefix.
size()) {
1522 return emplaceImp(&child,
1523 remainingKey.
substr(commonLen),
1529 Node splitNode(childPrefix.
substr(0, commonLen), get_allocator());
1531 Node childCopy(child, get_allocator());
1532 childCopy.prefix() = childPrefix.
substr(commonLen);
1534 splitNode.children().emplace(childCopy.prefix()[0],
1537 if (commonLen == remainingKey.
size()) {
1546 return EmplaceResult(
true,
1547 it->second.value().value());
1551 const typename Node::Children::iterator newIter =
1552 splitNode.children().emplace(newKey[0], newKey).first;
1561 return EmplaceResult(
true, newIter->second.value().value());
1565#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 4
1566template <
class t_VALUE>
1567template <
class Args_01,
1571typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
1572CategoryManager_RadixTree<t_VALUE>::emplaceImp(
1582 if (remainingKey.
empty()) {
1583 if (node->value().has_value()) {
1584 return EmplaceResult(
false, node->value().value());
1590 return EmplaceResult(
true, node->value().value());
1593 const char firstChar = remainingKey[0];
1594 typename Node::Children::iterator it = node->children().
find(firstChar);
1596 if (it == node->children().end()) {
1597 typename Node::Children::iterator iter =
1598 node->children().emplace(firstChar, remainingKey).first;
1599 ChildNodeGuard guard(node, iter);
1609 return EmplaceResult(
true, iter->second.value().value());
1612 Node& child = it->second;
1615 size_type minLen = bsl::min(remainingKey.
size(), childPrefix.
size());
1617 bsl::mismatch(remainingKey.
begin(),
1618 remainingKey.
begin() + minLen,
1619 childPrefix.
begin())
1621 const size_type commonLen = mismatchPos - remainingKey.
begin();
1623 if (commonLen == childPrefix.
size()) {
1624 return emplaceImp(&child,
1625 remainingKey.
substr(commonLen),
1632 Node splitNode(childPrefix.
substr(0, commonLen), get_allocator());
1634 Node childCopy(child, get_allocator());
1635 childCopy.prefix() = childPrefix.
substr(commonLen);
1637 splitNode.children().emplace(childCopy.prefix()[0],
1640 if (commonLen == remainingKey.
size()) {
1651 return EmplaceResult(
true,
1652 it->second.value().value());
1656 const typename Node::Children::iterator newIter =
1657 splitNode.children().emplace(newKey[0], newKey).first;
1668 return EmplaceResult(
true, newIter->second.value().value());
1672#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 5
1673template <
class t_VALUE>
1674template <
class Args_01,
1679typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
1680CategoryManager_RadixTree<t_VALUE>::emplaceImp(
1691 if (remainingKey.
empty()) {
1692 if (node->value().has_value()) {
1693 return EmplaceResult(
false, node->value().value());
1700 return EmplaceResult(
true, node->value().value());
1703 const char firstChar = remainingKey[0];
1704 typename Node::Children::iterator it = node->children().
find(firstChar);
1706 if (it == node->children().end()) {
1707 typename Node::Children::iterator iter =
1708 node->children().emplace(firstChar, remainingKey).first;
1709 ChildNodeGuard guard(node, iter);
1721 return EmplaceResult(
true, iter->second.value().value());
1724 Node& child = it->second;
1727 size_type minLen = bsl::min(remainingKey.
size(), childPrefix.
size());
1729 bsl::mismatch(remainingKey.
begin(),
1730 remainingKey.
begin() + minLen,
1731 childPrefix.
begin())
1733 const size_type commonLen = mismatchPos - remainingKey.
begin();
1735 if (commonLen == childPrefix.
size()) {
1736 return emplaceImp(&child,
1737 remainingKey.
substr(commonLen),
1745 Node splitNode(childPrefix.
substr(0, commonLen), get_allocator());
1747 Node childCopy(child, get_allocator());
1748 childCopy.prefix() = childPrefix.
substr(commonLen);
1750 splitNode.children().emplace(childCopy.prefix()[0],
1753 if (commonLen == remainingKey.
size()) {
1766 return EmplaceResult(
true,
1767 it->second.value().value());
1771 const typename Node::Children::iterator newIter =
1772 splitNode.children().emplace(newKey[0], newKey).first;
1785 return EmplaceResult(
true, newIter->second.value().value());
1789#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 6
1790template <
class t_VALUE>
1791template <
class Args_01,
1797typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
1798CategoryManager_RadixTree<t_VALUE>::emplaceImp(
1810 if (remainingKey.
empty()) {
1811 if (node->value().has_value()) {
1812 return EmplaceResult(
false, node->value().value());
1820 return EmplaceResult(
true, node->value().value());
1823 const char firstChar = remainingKey[0];
1824 typename Node::Children::iterator it = node->children().
find(firstChar);
1826 if (it == node->children().end()) {
1827 typename Node::Children::iterator iter =
1828 node->children().emplace(firstChar, remainingKey).first;
1829 ChildNodeGuard guard(node, iter);
1843 return EmplaceResult(
true, iter->second.value().value());
1846 Node& child = it->second;
1849 size_type minLen = bsl::min(remainingKey.
size(), childPrefix.
size());
1851 bsl::mismatch(remainingKey.
begin(),
1852 remainingKey.
begin() + minLen,
1853 childPrefix.
begin())
1855 const size_type commonLen = mismatchPos - remainingKey.
begin();
1857 if (commonLen == childPrefix.
size()) {
1858 return emplaceImp(&child,
1859 remainingKey.
substr(commonLen),
1868 Node splitNode(childPrefix.
substr(0, commonLen), get_allocator());
1870 Node childCopy(child, get_allocator());
1871 childCopy.prefix() = childPrefix.
substr(commonLen);
1873 splitNode.children().emplace(childCopy.prefix()[0],
1876 if (commonLen == remainingKey.
size()) {
1891 return EmplaceResult(
true,
1892 it->second.value().value());
1896 const typename Node::Children::iterator newIter =
1897 splitNode.children().emplace(newKey[0], newKey).first;
1912 return EmplaceResult(
true, newIter->second.value().value());
1916#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 7
1917template <
class t_VALUE>
1918template <
class Args_01,
1925typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
1926CategoryManager_RadixTree<t_VALUE>::emplaceImp(
1939 if (remainingKey.
empty()) {
1940 if (node->value().has_value()) {
1941 return EmplaceResult(
false, node->value().value());
1950 return EmplaceResult(
true, node->value().value());
1953 const char firstChar = remainingKey[0];
1954 typename Node::Children::iterator it = node->children().
find(firstChar);
1956 if (it == node->children().end()) {
1957 typename Node::Children::iterator iter =
1958 node->children().emplace(firstChar, remainingKey).first;
1959 ChildNodeGuard guard(node, iter);
1975 return EmplaceResult(
true, iter->second.value().value());
1978 Node& child = it->second;
1981 size_type minLen = bsl::min(remainingKey.
size(), childPrefix.
size());
1983 bsl::mismatch(remainingKey.
begin(),
1984 remainingKey.
begin() + minLen,
1985 childPrefix.
begin())
1987 const size_type commonLen = mismatchPos - remainingKey.
begin();
1989 if (commonLen == childPrefix.
size()) {
1990 return emplaceImp(&child,
1991 remainingKey.
substr(commonLen),
2001 Node splitNode(childPrefix.
substr(0, commonLen), get_allocator());
2003 Node childCopy(child, get_allocator());
2004 childCopy.prefix() = childPrefix.
substr(commonLen);
2006 splitNode.children().emplace(childCopy.prefix()[0],
2009 if (commonLen == remainingKey.
size()) {
2026 return EmplaceResult(
true,
2027 it->second.value().value());
2031 const typename Node::Children::iterator newIter =
2032 splitNode.children().emplace(newKey[0], newKey).first;
2049 return EmplaceResult(
true, newIter->second.value().value());
2053#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 8
2054template <
class t_VALUE>
2055template <
class Args_01,
2063typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
2064CategoryManager_RadixTree<t_VALUE>::emplaceImp(
2078 if (remainingKey.
empty()) {
2079 if (node->value().has_value()) {
2080 return EmplaceResult(
false, node->value().value());
2090 return EmplaceResult(
true, node->value().value());
2093 const char firstChar = remainingKey[0];
2094 typename Node::Children::iterator it = node->children().
find(firstChar);
2096 if (it == node->children().end()) {
2097 typename Node::Children::iterator iter =
2098 node->children().emplace(firstChar, remainingKey).first;
2099 ChildNodeGuard guard(node, iter);
2117 return EmplaceResult(
true, iter->second.value().value());
2120 Node& child = it->second;
2123 size_type minLen = bsl::min(remainingKey.
size(), childPrefix.
size());
2125 bsl::mismatch(remainingKey.
begin(),
2126 remainingKey.
begin() + minLen,
2127 childPrefix.
begin())
2129 const size_type commonLen = mismatchPos - remainingKey.
begin();
2131 if (commonLen == childPrefix.
size()) {
2132 return emplaceImp(&child,
2133 remainingKey.
substr(commonLen),
2144 Node splitNode(childPrefix.
substr(0, commonLen), get_allocator());
2146 Node childCopy(child, get_allocator());
2147 childCopy.prefix() = childPrefix.
substr(commonLen);
2149 splitNode.children().emplace(childCopy.prefix()[0],
2152 if (commonLen == remainingKey.
size()) {
2171 return EmplaceResult(
true,
2172 it->second.value().value());
2176 const typename Node::Children::iterator newIter =
2177 splitNode.children().emplace(newKey[0], newKey).first;
2196 return EmplaceResult(
true, newIter->second.value().value());
2200#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 9
2201template <
class t_VALUE>
2202template <
class Args_01,
2211typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
2212CategoryManager_RadixTree<t_VALUE>::emplaceImp(
2227 if (remainingKey.
empty()) {
2228 if (node->value().has_value()) {
2229 return EmplaceResult(
false, node->value().value());
2240 return EmplaceResult(
true, node->value().value());
2243 const char firstChar = remainingKey[0];
2244 typename Node::Children::iterator it = node->children().
find(firstChar);
2246 if (it == node->children().end()) {
2247 typename Node::Children::iterator iter =
2248 node->children().emplace(firstChar, remainingKey).first;
2249 ChildNodeGuard guard(node, iter);
2269 return EmplaceResult(
true, iter->second.value().value());
2272 Node& child = it->second;
2275 size_type minLen = bsl::min(remainingKey.
size(), childPrefix.
size());
2277 bsl::mismatch(remainingKey.
begin(),
2278 remainingKey.
begin() + minLen,
2279 childPrefix.
begin())
2281 const size_type commonLen = mismatchPos - remainingKey.
begin();
2283 if (commonLen == childPrefix.
size()) {
2284 return emplaceImp(&child,
2285 remainingKey.
substr(commonLen),
2297 Node splitNode(childPrefix.
substr(0, commonLen), get_allocator());
2299 Node childCopy(child, get_allocator());
2300 childCopy.prefix() = childPrefix.
substr(commonLen);
2302 splitNode.children().emplace(childCopy.prefix()[0],
2305 if (commonLen == remainingKey.
size()) {
2326 return EmplaceResult(
true,
2327 it->second.value().value());
2331 const typename Node::Children::iterator newIter =
2332 splitNode.children().emplace(newKey[0], newKey).first;
2353 return EmplaceResult(
true, newIter->second.value().value());
2357#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_C >= 10
2358template <
class t_VALUE>
2359template <
class Args_01,
2369typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
2370CategoryManager_RadixTree<t_VALUE>::emplaceImp(
2386 if (remainingKey.
empty()) {
2387 if (node->value().has_value()) {
2388 return EmplaceResult(
false, node->value().value());
2400 return EmplaceResult(
true, node->value().value());
2403 const char firstChar = remainingKey[0];
2404 typename Node::Children::iterator it = node->children().
find(firstChar);
2406 if (it == node->children().end()) {
2407 typename Node::Children::iterator iter =
2408 node->children().emplace(firstChar, remainingKey).first;
2409 ChildNodeGuard guard(node, iter);
2431 return EmplaceResult(
true, iter->second.value().value());
2434 Node& child = it->second;
2437 size_type minLen = bsl::min(remainingKey.
size(), childPrefix.
size());
2439 bsl::mismatch(remainingKey.
begin(),
2440 remainingKey.
begin() + minLen,
2441 childPrefix.
begin())
2443 const size_type commonLen = mismatchPos - remainingKey.
begin();
2445 if (commonLen == childPrefix.
size()) {
2446 return emplaceImp(&child,
2447 remainingKey.
substr(commonLen),
2460 Node splitNode(childPrefix.
substr(0, commonLen), get_allocator());
2462 Node childCopy(child, get_allocator());
2463 childCopy.prefix() = childPrefix.
substr(commonLen);
2465 splitNode.children().emplace(childCopy.prefix()[0],
2468 if (commonLen == remainingKey.
size()) {
2491 return EmplaceResult(
true,
2492 it->second.value().value());
2496 const typename Node::Children::iterator newIter =
2497 splitNode.children().emplace(newKey[0], newKey).first;
2520 return EmplaceResult(
true, newIter->second.value().value());
2527template <
class t_VALUE>
2528template <
class... Args>
2529typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
2530CategoryManager_RadixTree<t_VALUE>::emplaceImp(
2537 if (remainingKey.
empty()) {
2538 if (node->value().has_value()) {
2539 return EmplaceResult(
false, node->value().value());
2542 return EmplaceResult(
true, node->value().value());
2545 const char firstChar = remainingKey[0];
2546 typename Node::Children::iterator it = node->children().
find(firstChar);
2548 if (it == node->children().end()) {
2549 typename Node::Children::iterator iter =
2550 node->children().emplace(firstChar, remainingKey).first;
2551 ChildNodeGuard guard(node, iter);
2555 return EmplaceResult(
true, iter->second.value().value());
2558 Node& child = it->second;
2561 size_type minLen = bsl::min(remainingKey.
size(), childPrefix.
size());
2563 bsl::mismatch(remainingKey.
begin(),
2564 remainingKey.
begin() + minLen,
2565 childPrefix.
begin())
2567 const size_type commonLen = mismatchPos - remainingKey.
begin();
2569 if (commonLen == childPrefix.
size()) {
2570 return emplaceImp(&child,
2571 remainingKey.
substr(commonLen),
2575 Node splitNode(childPrefix.
substr(0, commonLen), get_allocator());
2577 Node childCopy(child, get_allocator());
2578 childCopy.prefix() = childPrefix.
substr(commonLen);
2580 splitNode.children().emplace(childCopy.prefix()[0],
2583 if (commonLen == remainingKey.
size()) {
2588 return EmplaceResult(
true,
2589 it->second.value().value());
2593 const typename Node::Children::iterator newIter =
2594 splitNode.children().emplace(newKey[0], newKey).first;
2599 return EmplaceResult(
true, newIter->second.value().value());
2604template <
class t_VALUE>
2605typename CategoryManager_RadixTree<t_VALUE>::size_type
2606CategoryManager_RadixTree<t_VALUE>::eraseAllChildren(
2607 typename CategoryManager_RadixTree<t_VALUE>::Node *node)
2611 size_type count = 0;
2613 typedef typename Node::Children::iterator Iter;
2614 for (Iter it = node->children().begin();
2615 it != node->children().end(); ) {
2616 count += eraseAllChildren(&it->second);
2617 if (it->second.value().has_value()) {
2618 it->second.value().reset();
2622 it = node->children().erase(it);
2628template <
class t_VALUE>
2629void CategoryManager_RadixTree<t_VALUE>::cleanupChildAfterErase(
2631 typename Node::Children::iterator it,
2636 Node& child = it->second;
2638 if (!child.value().has_value() && child.children().empty()) {
2640 node->children().erase(it);
2642 else if (!child.value().has_value() && child.children().size() == 1) {
2645 const typename Node::Children::iterator grandIt =
2646 child.children().begin();
2647 Node& grandchild = grandIt->second;
2650 bsl::string mergedPrefix(child.prefix() + grandchild.prefix(),
2654 Node mergedNode(mergedPrefix, get_allocator());
2656 mergedNode.children() =
2660 node->children().erase(it);
2661 node->children().emplace(firstChar,
2666template <
class t_VALUE>
2667bool CategoryManager_RadixTree<t_VALUE>::eraseImp(
2673 if (remainingKey.
empty()) {
2674 if (!node->value().has_value()) {
2677 node->value().reset();
2681 const char firstChar = remainingKey[0];
2682 typename Node::Children::iterator it = node->children().
find(firstChar);
2684 if (it == node->children().end()) {
2688 Node& child = it->second;
2696 const bool erased = eraseImp(&child,
2704 cleanupChildAfterErase(node, it, firstChar);
2709template <
class t_VALUE>
2710typename CategoryManager_RadixTree<t_VALUE>::size_type
2711CategoryManager_RadixTree<t_VALUE>::erasePrefixImp(
2717 if (remainingPrefix.
empty()) {
2719 size_type count = 0;
2722 if (node->value().has_value()) {
2723 node->value().reset();
2729 typedef typename Node::Children::iterator Iter;
2730 for (Iter it = node->children().begin();
2731 it != node->children().end();
2733 count += erasePrefixImp(&it->second,
"");
2736 node->children().clear();
2741 const char firstChar = remainingPrefix[0];
2742 const typename Node::Children::iterator it =
2743 node->children().
find(firstChar);
2745 if (it == node->children().end()) {
2749 Node& child = it->second;
2754 const size_type count =
2755 erasePrefixImp(&child,
2759 cleanupChildAfterErase(node, it, firstChar);
2763 else if (childPrefix.
starts_with(remainingPrefix)) {
2765 const size_type count = erasePrefixImp(&child,
"");
2766 node->children().erase(it);
2774template <
class t_VALUE>
2775template <
class t_FUNCTOR>
2777CategoryManager_RadixTree<t_VALUE>::forEachImp(
2780 const t_FUNCTOR& functor)
2787 const bsl::string fullKey = keyPrefix + node->prefix();
2790 if (node->value().has_value()) {
2791 functor(fullKey, node->value().value());
2795 typedef typename Node::Children::const_iterator ConstIter;
2796 for (ConstIter it = node->children().begin();
2797 it != node->children().end();
2799 forEachImp(&it->second, fullKey, functor);
2803template <
class t_VALUE>
2804template <
class t_FUNCTOR>
2806CategoryManager_RadixTree<t_VALUE>::forEachImp(
2809 const t_FUNCTOR& functor)
2816 const bsl::string fullKey = keyPrefix + node->prefix();
2819 if (node->value().has_value()) {
2820 functor(fullKey, node->value().value());
2824 typedef typename Node::Children::iterator Iter;
2825 for (Iter it = node->children().begin();
2826 it != node->children().end();
2828 forEachImp(&it->second, fullKey, functor);
2832template <
class t_VALUE>
2833template <
class t_FUNCTOR>
2834typename CategoryManager_RadixTree<t_VALUE>::size_type
2835CategoryManager_RadixTree<t_VALUE>::forEachPrefixImp(
2838 const t_FUNCTOR& functor)
2842 size_type count = 0;
2845 if (node->value()) {
2846 functor(key, *node->value());
2851 typedef typename Node::Children::iterator Iter;
2852 for (Iter it = node->children().begin();
2853 it != node->children().end();
2855 const bsl::string nextKey = key + it->second.prefix();
2856 count += forEachPrefixImp(&it->second, nextKey, functor);
2862template <
class t_VALUE>
2863template <
class t_FUNCTOR>
2864typename CategoryManager_RadixTree<t_VALUE>::size_type
2865CategoryManager_RadixTree<t_VALUE>::forEachPrefixImp(
2868 const t_FUNCTOR& functor)
2872 size_type count = 0;
2875 if (node->value()) {
2876 functor(key, *node->value());
2881 typedef typename Node::Children::const_iterator Iter;
2882 for (Iter it = node->children().begin();
2883 it != node->children().end();
2885 const bsl::string nextKey = key + it->second.prefix();
2886 count += forEachPrefixImp(&it->second, nextKey, functor);
2892template <
class t_VALUE>
2894CategoryManager_RadixTree<t_VALUE>::printNodeImp(
2895 bsl::ostream& stream,
2904 const bool noFirstLineIndent = (currLevel < 0);
2905 const bool singleLineMode = (spacesPerLevel < 0);
2907 const int absLevel = noFirstLineIndent ? -currLevel : currLevel;
2908 const int absSpacesPerLevel = singleLineMode
2912 if (!noFirstLineIndent) {
2913 stream <<
bsl::string(absLevel * absSpacesPerLevel,
' ');
2916 if (singleLineMode) {
2917 stream <<
'{' << depth <<
"} ";
2920 stream <<
'"' << keyPrefix <<
'"';
2921 if (node->value().has_value()) {
2923 stream << node->value().value();
2926 stream <<
": **NO-VALUE**";
2929 stream << (singleLineMode ?
' ' :
'\n');
2931 const int nextLevel = absLevel + 1;
2933 typedef typename Node::Children::const_iterator Iter;
2934 for (Iter it = node->children().begin();
2935 it != node->children().end();
2937 printNodeImp(stream,
2940 keyPrefix + it->second.prefix(),
2941 singleLineMode ? -nextLevel : nextLevel,
2947template <
class t_VALUE>
2949CategoryManager_RadixTree<t_VALUE>::CategoryManager_RadixTree()
2957template <
class t_VALUE>
2959CategoryManager_RadixTree<t_VALUE>::CategoryManager_RadixTree(
2960 const allocator_type& allocator)
2961: d_root(
"", allocator)
2968template <
class t_VALUE>
2970CategoryManager_RadixTree<t_VALUE>::CategoryManager_RadixTree(
2971 const CategoryManager_RadixTree& original,
2972 const allocator_type& allocator)
2973: d_root(original.d_root, allocator)
2974, d_size(original.d_size)
2978template <
class t_VALUE>
2980CategoryManager_RadixTree<t_VALUE>::CategoryManager_RadixTree(
2991template <
class t_VALUE>
2993CategoryManager_RadixTree<t_VALUE>::CategoryManager_RadixTree(
2995 const allocator_type& allocator)
2996: d_root(
bslmf::MovableRefUtil::move(
2997 bslmf::MovableRefUtil::access(original).d_root),
2999, d_size(
bslmf::MovableRefUtil::move(
3000 bslmf::MovableRefUtil::access(original).d_size))
3008template <
class t_VALUE>
3010CategoryManager_RadixTree<t_VALUE>&
3011CategoryManager_RadixTree<t_VALUE>::operator=(
3012 const CategoryManager_RadixTree& rhs)
3015 CategoryManager_RadixTree temp(rhs, get_allocator());
3021template <
class t_VALUE>
3023CategoryManager_RadixTree<t_VALUE>&
3024CategoryManager_RadixTree<t_VALUE>::operator=(
3027 CategoryManager_RadixTree& lvalue =
rhs;
3028 if (
this != &lvalue) {
3029 if (get_allocator() == lvalue.get_allocator()) {
3042#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
3045#ifndef BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT
3046#define BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT 10
3048#ifndef BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D
3049#define BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT
3051#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 0
3052template <
class t_VALUE>
3053typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3056 const EmplaceResult result = emplaceImp(&d_root,
3065#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 1
3066template <
class t_VALUE>
3067template <
class Args_01>
3068typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3072 const EmplaceResult result = emplaceImp(&d_root,
3083#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 2
3084template <
class t_VALUE>
3085template <
class Args_01,
3087typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3092 const EmplaceResult result = emplaceImp(&d_root,
3105#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 3
3106template <
class t_VALUE>
3107template <
class Args_01,
3110typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3116 const EmplaceResult result = emplaceImp(&d_root,
3131#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 4
3132template <
class t_VALUE>
3133template <
class Args_01,
3137typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3144 const EmplaceResult result = emplaceImp(&d_root,
3161#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 5
3162template <
class t_VALUE>
3163template <
class Args_01,
3168typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3176 const EmplaceResult result = emplaceImp(&d_root,
3195#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 6
3196template <
class t_VALUE>
3197template <
class Args_01,
3203typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3212 const EmplaceResult result = emplaceImp(&d_root,
3233#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 7
3234template <
class t_VALUE>
3235template <
class Args_01,
3242typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3252 const EmplaceResult result = emplaceImp(&d_root,
3275#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 8
3276template <
class t_VALUE>
3277template <
class Args_01,
3285typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3296 const EmplaceResult result = emplaceImp(&d_root,
3321#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 9
3322template <
class t_VALUE>
3323template <
class Args_01,
3332typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3344 const EmplaceResult result = emplaceImp(&d_root,
3371#if BALL_CATEGORYMANAGER_RADIXTREE_VARIADIC_LIMIT_D >= 10
3372template <
class t_VALUE>
3373template <
class Args_01,
3383typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3396 const EmplaceResult result = emplaceImp(&d_root,
3428template <
class t_VALUE>
3429template <
class... Args>
3430typename CategoryManager_RadixTree<t_VALUE>::EmplaceResult
3434 const EmplaceResult result = emplaceImp(&d_root,
3446template <
class t_VALUE>
3448void CategoryManager_RadixTree<t_VALUE>::clear()
3450 d_root.children().clear();
3451 d_root.value().reset();
3455template <
class t_VALUE>
3458 const bool erased = eraseImp(&d_root, key);
3465template <
class t_VALUE>
3466typename CategoryManager_RadixTree<t_VALUE>::size_type
3467CategoryManager_RadixTree<t_VALUE>::eraseChildrenOfPrefix(
3470 Node *node = &d_root;
3473 while (pos < prefix.
size()) {
3474 typedef typename Node::Children::iterator Iter;
3476 Iter it = node->children().find(prefix[pos]);
3477 if (it == node->children().end()) {
3481 Node &child = it->second;
3483 if (prefix.
substr(pos, childPrefix.
size()) == childPrefix) {
3485 pos += childPrefix.
size();
3491 return eraseAllChildren(node);
3494template <
class t_VALUE>
3495typename CategoryManager_RadixTree<t_VALUE>::size_type
3496CategoryManager_RadixTree<t_VALUE>::erasePrefix(
const bsl::string_view& prefix)
3499 if (prefix.
empty()) {
3500 const size_type oldSize = d_size;
3505 return erasePrefixImp(&d_root, prefix);
3508template <
class t_VALUE>
3509typename CategoryManager_RadixTree<t_VALUE>::OptValueRef
3513 Node *currentNode = &d_root;
3517 if (remainingKey.
empty()) {
3518 return currentNode->value().has_value()
3519 ?
typename CategoryManager_RadixTree::OptValueRef(
3520 bsl::ref(currentNode->value().value()))
3524 const typename Node::Children::iterator it =
3525 currentNode->children().find(remainingKey[0]);
3527 if (it == currentNode->children().end()) {
3531 Node& child = it->second;
3540 currentNode = &child;
3544template <
class t_VALUE>
3547CategoryManager_RadixTree<t_VALUE>::findLongestCommonPrefix(
3551 OptValueCRef constValue;
3552 const CategoryManager_RadixTree<t_VALUE>* constThis =
3553 const_cast<const CategoryManager_RadixTree*
>(
this);
3555 constThis->findLongestCommonPrefix(&constValue, key);
3558 if (constValue.has_value()) {
3559 *value =
bsl::ref(
const_cast<t_VALUE&
>(constValue.value().get()));
3567template <
class t_VALUE>
3568template <
class t_FUNCTOR>
3569void CategoryManager_RadixTree<t_VALUE>::forEach(
const t_FUNCTOR& functor)
3575 forEachImp(&d_root,
"", functor);
3578template <
class t_VALUE>
3579template <
class t_FUNCTOR>
3580typename CategoryManager_RadixTree<t_VALUE>::size_type
3581CategoryManager_RadixTree<t_VALUE>::forEachPrefix(
3583 const t_FUNCTOR& functor)
3585 Node *node = &d_root;
3588 while (pos < prefix.
size()) {
3590 typedef typename Node::Children::iterator Iter;
3591 for (Iter it = node->children().begin();
3592 it != node->children().end();
3594 const Node& child = it->second;
3597 while (i < childPrefix.
size()
3598 && pos + i < prefix.
size()
3599 && prefix[pos + i] == childPrefix[i]) {
3602 if (i == childPrefix.
size()) {
3605 keySoFar.
append(childPrefix);
3609 }
else if (i == prefix.
size() - pos) {
3616 return forEachPrefixImp(node, prefix, functor);
3627 return forEachPrefixImp(node, prefix.
substr(0, keySoFar.
size()), functor);
3630template <
class t_VALUE>
3632void CategoryManager_RadixTree<t_VALUE>::swap(CategoryManager_RadixTree& other)
3634 BSLS_ASSERT(get_allocator() == other.get_allocator());
3641template <
class t_VALUE>
3643bool CategoryManager_RadixTree<t_VALUE>::contains(
3647 const Node *currentNode = &d_root;
3651 if (remainingKey.
empty()) {
3652 return currentNode->value().has_value();
3655 const typename Node::Children::const_iterator it =
3656 currentNode->children().
find(remainingKey[0]);
3658 if (it == currentNode->children().end()) {
3662 const Node& child = it->second;
3671 currentNode = &child;
3675template <
class t_VALUE>
3676typename CategoryManager_RadixTree<t_VALUE>::size_type
3677CategoryManager_RadixTree<t_VALUE>::countNodes()
const
3679 size_type count = 1;
3682 typedef typename Node::Children::const_iterator Iter;
3683 for (Iter it = d_root.children().begin();
3684 it != d_root.children().end();
3693 while (!stack.
empty()) {
3694 const Node* node = stack.
back();
3697 for (Iter childIt = node->children().begin();
3698 childIt != node->children().end();
3709template <
class t_VALUE>
3711bool CategoryManager_RadixTree<t_VALUE>::empty()
const
3716template <
class t_VALUE>
3717typename CategoryManager_RadixTree<t_VALUE>::OptValueCRef
3721 const Node *currentNode = &d_root;
3725 if (remainingKey.
empty()) {
3726 return currentNode->value().has_value()
3727 ?
typename CategoryManager_RadixTree::OptValueCRef(
3728 bsl::cref(currentNode->value().value()))
3732 const typename Node::Children::const_iterator it =
3733 currentNode->children().find(remainingKey[0]);
3735 if (it == currentNode->children().end()) {
3739 const Node& child = it->second;
3748 currentNode = &child;
3752template <
class t_VALUE>
3754bsl::string_view CategoryManager_RadixTree<t_VALUE>::findLongestCommonPrefix(
3755 OptValueCRef *value,
3759 const Node *node = &d_root;
3760 size_type matched = 0;
3762 size_type lastMatchedLength = 0;
3766 if (node->value().has_value()) {
3767 lastMatchedLength = 0;
3768 lastValueRef =
bsl::cref(node->value().value());
3771 while (pos < key.
size()) {
3772 typedef typename Node::Children::const_iterator Iter;
3773 const Iter it = node->children().find(key[pos]);
3774 if (it == node->children().end()) {
3777 const Node& child = it->second;
3780 while (i < childPrefix.
size()
3781 && pos + i < key.
size()
3782 && key[pos + i] == childPrefix[i]) {
3790 if (i < childPrefix.
size()) {
3798 if (node->value().has_value()) {
3799 lastMatchedLength = matched;
3800 lastValueRef =
bsl::cref(node->value().value());
3804 *value = lastValueRef;
3806 return key.
substr(0, lastMatchedLength);
3809template <
class t_VALUE>
3810template <
class t_FUNCTOR>
3812CategoryManager_RadixTree<t_VALUE>::forEach(
const t_FUNCTOR& functor)
const
3818 forEachImp(&d_root,
"", functor);
3821template <
class t_VALUE>
3822template <
class t_FUNCTOR>
3823typename CategoryManager_RadixTree<t_VALUE>::size_type
3824CategoryManager_RadixTree<t_VALUE>::forEachPrefix(
3826 const t_FUNCTOR& functor)
const
3828 const Node *node = &d_root;
3832 while (pos < prefix.
size()) {
3834 typedef typename Node::Children::const_iterator Iter;
3835 for (Iter it = node->children().begin();
3836 it != node->children().end();
3838 const Node& child = it->second;
3841 while (i < childPrefix.
size()
3842 && pos + i < prefix.
size()
3843 && prefix[pos + i] == childPrefix[i]) {
3846 if (i == childPrefix.
size()) {
3849 keySoFar.
append(childPrefix);
3853 }
else if (i == prefix.
size() - pos) {
3860 return forEachPrefixImp(node, prefix, functor);
3871 return forEachPrefixImp(node, prefix.
substr(0, keySoFar.
size()), functor);
3874template <
class t_VALUE>
3875bsl::ostream& CategoryManager_RadixTree<t_VALUE>::printNodes(
3876 bsl::ostream& stream,
3878 int spacesPerLevel)
const
3880 printNodeImp(stream, 0, &d_root,
"", level, spacesPerLevel);
3884template <
class t_VALUE>
3886typename CategoryManager_RadixTree<t_VALUE>::size_type
3887CategoryManager_RadixTree<t_VALUE>::size()
const
3894template <
class t_VALUE>
3896typename CategoryManager_RadixTree<t_VALUE>::allocator_type
3897CategoryManager_RadixTree<t_VALUE>::get_allocator()
const
3899 return d_root.children().get_allocator();
3909template <
class t_VALUE>
3911 const CategoryManager_RadixTree_Node<t_VALUE>& rhs)
3913 return lhs.prefix() ==
rhs.prefix()
3914 &&
lhs.value() ==
rhs.value()
3915 &&
lhs.children() ==
rhs.children();
3918template <
class t_VALUE>
3921 const CategoryManager_RadixTree_Node<t_VALUE>& rhs)
3932template <
class t_VALUE>
3934 const CategoryManager_RadixTree<t_VALUE>& rhs)
3936 if (
lhs.d_size !=
rhs.d_size) {
3942 return lhs.d_root ==
rhs.d_root;
3945template <
class t_VALUE>
3948 const CategoryManager_RadixTree<t_VALUE>& rhs)
3954template <
class t_VALUE>
3956void ball::swap(CategoryManager_RadixTree<t_VALUE>& a,
3957 CategoryManager_RadixTree<t_VALUE>& b)
3965# error Not valid except when included from ball_categorymanager_radixtree.h
void release()
Definition ball_categorymanager_radixtree.h:862
~CategoryManager_RadixTree_ChildNodeGuard()
Definition ball_categorymanager_radixtree.h:852
Node::Children::iterator ChildIterator
Definition ball_categorymanager_radixtree.h:384
CategoryManager_RadixTree_Node< t_VALUE > Node
Definition ball_categorymanager_radixtree.h:383
void swap(CategoryManager_RadixTree_Node &other)
Definition ball_categorymanager_radixtree.h:990
bsl::allocator allocator_type
Definition ball_categorymanager_radixtree.h:251
Children & children()
Definition ball_categorymanager_radixtree.h:976
bsl::optional< t_VALUE > & value()
Definition ball_categorymanager_radixtree.h:1002
bsl::map< char, CategoryManager_RadixTree_Node > Children
Definition ball_categorymanager_radixtree.h:237
allocator_type get_allocator() const
Return the allocator used by this object to supply memory.
Definition ball_categorymanager_radixtree.h:1036
CategoryManager_RadixTree_Node(const bsl::string_view &prefix, const allocator_type &allocator=allocator_type())
Definition ball_categorymanager_radixtree.h:874
bsl::string & prefix()
Definition ball_categorymanager_radixtree.h:983
CategoryManager_RadixTree_Node & operator=(const CategoryManager_RadixTree_Node &rhs)
Definition ball_categorymanager_radixtree.h:941
size_type eraseChildrenOfPrefix(const bsl::string_view &prefix)
Definition ball_categorymanager_radixtree.h:1611
~CategoryManager_RadixTree()=default
Destroy this object.
OptValueRef find(const bsl::string_view &key)
Definition ball_categorymanager_radixtree.h:1654
bsl::optional< bsl::reference_wrapper< t_VALUE > > OptValueRef
Definition ball_categorymanager_radixtree.h:443
bsl::ostream & printNodes(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
Definition ball_categorymanager_radixtree.h:2019
bool empty() const
Return true if this tree contains no entries, and false otherwise.
Definition ball_categorymanager_radixtree.h:1855
bsl::size_t size_type
Definition ball_categorymanager_radixtree.h:439
bsl::optional< bsl::reference_wrapper< const t_VALUE > > OptValueCRef
Definition ball_categorymanager_radixtree.h:447
bsl::pair< bool, bsl::reference_wrapper< t_VALUE > > EmplaceResult
Definition ball_categorymanager_radixtree.h:457
t_VALUE value_type
Definition ball_categorymanager_radixtree.h:438
friend void swap(CategoryManager_RadixTree< t_TYPE > &a, CategoryManager_RadixTree< t_TYPE > &b)
allocator_type get_allocator() const
Definition ball_categorymanager_radixtree.h:2041
void forEach(const t_FUNCTOR &functor)
Definition ball_categorymanager_radixtree.h:1713
void clear()
Definition ball_categorymanager_radixtree.h:1592
friend bool operator==(const CategoryManager_RadixTree< t_TYPE > &, const CategoryManager_RadixTree< t_TYPE > &)
CategoryManager_RadixTree & operator=(const CategoryManager_RadixTree &rhs)
Definition ball_categorymanager_radixtree.h:1542
size_type forEachPrefix(const bsl::string_view &prefix, const t_FUNCTOR &functor)
Definition ball_categorymanager_radixtree.h:1725
EmplaceResult emplace(const bsl::string_view &key, Args &&... args)
Definition ball_categorymanager_radixtree.h:1577
bsl::allocator allocator_type
Definition ball_categorymanager_radixtree.h:437
size_type erasePrefix(const bsl::string_view &prefix)
Definition ball_categorymanager_radixtree.h:1640
size_type countNodes() const
Definition ball_categorymanager_radixtree.h:1821
bsl::string_view findLongestCommonPrefix(OptValueRef *value, const bsl::string_view &key)
Definition ball_categorymanager_radixtree.h:1691
CategoryManager_RadixTree()
Definition ball_categorymanager_radixtree.h:1480
bool erase(const bsl::string_view &key)
Definition ball_categorymanager_radixtree.h:1600
bool contains(const bsl::string_view &key) const
Definition ball_categorymanager_radixtree.h:1787
size_type size() const
Return the number of entries in this tree.
Definition ball_categorymanager_radixtree.h:2031
Definition bslma_bslallocator.h:588
Definition bslstl_stringview.h:471
BSLS_KEYWORD_CONSTEXPR_CPP14 size_type find(basic_string_view subview, size_type position=0) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stringview.h:2284
BSLS_KEYWORD_CONSTEXPR_CPP17 bool starts_with(basic_string_view subview) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stringview.h:2215
BSLS_KEYWORD_CONSTEXPR_CPP14 basic_string_view substr(size_type position=0, size_type numChars=npos) const
Definition bslstl_stringview.h:2027
BSLS_KEYWORD_CONSTEXPR size_type size() const BSLS_KEYWORD_NOEXCEPT
Return the length of this view.
Definition bslstl_stringview.h:1904
const value_type * const_iterator
Definition bslstl_stringview.h:481
BSLS_KEYWORD_CONSTEXPR const_iterator begin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stringview.h:1830
BSLS_KEYWORD_CONSTEXPR_CPP14 void remove_prefix(size_type numChars)
Definition bslstl_stringview.h:1800
BSLS_KEYWORD_CONSTEXPR bool empty() const BSLS_KEYWORD_NOEXCEPT
Return true if this view has length 0, and false otherwise.
Definition bslstl_stringview.h:1931
Definition bslstl_string.h:1252
basic_string substr(size_type position=0, size_type numChars=npos) const
Definition bslstl_string.h:8013
size_type size() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7292
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Return the allocator used by this string to supply memory.
Definition bslstl_string.h:7423
basic_string & append(const basic_string &suffix)
Definition bslstl_string.h:6188
Definition bslstl_map.h:653
Definition bslstl_optional.h:2043
Definition bslstl_pair.h:1280
reference back()
Definition bslstl_vector.h:2932
bool empty() const BSLS_KEYWORD_NOEXCEPT
Return true if this vector has size 0, and false otherwise.
Definition bslstl_vector.h:3034
Definition bslstl_vector.h:1120
void push_back(const VALUE_TYPE &value)
Definition bslstl_vector.h:4343
void pop_back()
Definition bslstl_vector.h:4375
Definition bslalg_constructorproxy.h:376
static void swap(T *a, T *b)
Definition bslalg_swaputil.h:182
Definition bslmf_movableref.h:752
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2343
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2349
#define BSLS_KEYWORD_DELETED
Definition bsls_keyword.h:651
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:674
bool operator!=(const FileCleanerConfiguration &lhs, const FileCleanerConfiguration &rhs)
bool operator==(const FileCleanerConfiguration &lhs, const FileCleanerConfiguration &rhs)
void swap(OptionValue &a, OptionValue &b)
Definition ball_administration.h:214
void swap(CategoryManager_RadixTree< t_VALUE > &a, CategoryManager_RadixTree< t_VALUE > &b)
bool operator!=(const Attribute &lhs, const Attribute &rhs)
bool operator==(const Attribute &lhs, const Attribute &rhs)
Definition bdlat_valuetypefunctions.h:939
reference_wrapper< const T > cref(const T &object)
reference_wrapper< T > ref(T &object)
Return a reference wrapper that represents the specified object.
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
ALLOCATOR & lhs
Definition bslstl_string.h:3917
basic_string< char > string
Definition bslstl_string.h:844
Definition bdlbb_blob.h:579
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1067
static t_TYPE & access(t_TYPE &ref) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1039