LibSWOC++ 1.5.14
Solid Wall of C++
Loading...
Searching...
No Matches
IPRange.h
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright Network Geographics 2014
6
7#pragma once
8
9#include <string_view>
10#include <variant> // for std::monostate
11#include <tuple>
12
13#include <swoc/DiscreteRange.h>
14#include <swoc/IPAddr.h>
15
16namespace swoc { inline namespace SWOC_VERSION_NS {
17
18using std::string_view;
19
20class IP4Net;
21class IP6Net;
22class IPNet;
23
26class IP4Range : public DiscreteRange<IP4Addr> {
27 using self_type = IP4Range;
28 using super_type = DiscreteRange<IP4Addr>;
29 using metric_type = IP4Addr;
30
31public:
33 constexpr IP4Range() = default;
34
36 IP4Range(IP4Addr const &addr, IPMask const &mask);
37
40 IP4Range(super_type const &r) : super_type(r) {}
41
52 IP4Range(string_view const &text);
53
54 using super_type::super_type;
55
62 self_type &assign(IP4Addr const &addr, IPMask const &mask);
63
64 using super_type::assign;
65
75 bool load(string_view text);
76
83 IPMask network_mask() const;
84
86 sa_family_t
87 family() const {
88 return AF_INET;
89 }
90
91 class NetSource;
92
109 NetSource networks() const;
110};
111
118 using self_type = NetSource;
119public:
121
123 explicit NetSource(range_type const &range);
124
126 NetSource(self_type const &that) = default;
127
129 using iterator = self_type;
132
133 iterator begin() const;
134 static iterator end();
135
137 bool empty() const;
138
140 IP4Net operator*() const;
141
143 self_type *operator->();
144
147 IP4Addr const &addr() const;
148
151 IPMask mask() const;
152
154 self_type &operator++();
155
157 self_type operator++(int);
158
160 bool operator==(self_type const &that) const;
161
163 bool operator!=(self_type const &that) const;
164
165protected:
168 IP4Addr _mask{~static_cast<in_addr_t>(0)};
170
171 void search_wider();
172
173 void search_narrower();
174
175 bool is_valid(IP4Addr mask) const;
176};
177
179class IP6Range : public DiscreteRange<IP6Addr> {
180 using self_type = IP6Range;
181 using super_type = DiscreteRange<IP6Addr>;
182
183public:
186 IP6Range(super_type const &r) : super_type(r) {}
187
196 IP6Range(string_view const &text);
197
198 using super_type::super_type;
199
206 self_type &assign(IP6Addr const &addr, IPMask const &mask);
207
208 using super_type::assign;
209
219 bool load(string_view text);
220
227 IPMask network_mask() const;
228
230 sa_family_t
231 family() const {
232 return AF_INET6;
233 }
234
235 class NetSource;
236
253 NetSource networks() const;
254};
255
262 using self_type = NetSource;
263public:
265
267 explicit NetSource(range_type const &range);
268
270 NetSource(self_type const &that) = default;
271
273 using iterator = self_type;
276
277 iterator begin() const;
278 iterator end() const;
279
281 bool empty() const;
282
284 IP6Net operator*() const;
285
287 self_type *operator->();
288
290 IP6Addr const &addr() const;
291
294 IPMask mask() const;
295
297 self_type &operator++();
298
300 self_type operator++(int);
301
303 bool operator==(self_type const &that) const;
304
306 bool operator!=(self_type const &that) const;
307
308protected:
311
312 void search_wider();
313
314 void search_narrower();
315
316 bool is_valid(IPMask const &mask);
317};
318
319class IPRangeView; // Forward declare.
320
325class IPRange {
326 using self_type = IPRange;
327
328public:
330 IPRange() = default;
331
337 IPRange(IPAddr const &min, IPAddr const &max);
338
344 IPRange(IP4Addr const &min, IP4Addr const &max);
345
351 IPRange(IP6Addr const &min, IP6Addr const &max);
352
357 IPRange(IPAddr const &addr) : IPRange(addr, addr) {}
358
363 IPRange(IP4Addr addr) : IPRange(addr, addr) {}
364
369 IPRange(IP6Addr const &addr) : IPRange(addr, addr) {}
370
372 IPRange(IP4Range const &range);
373
375 IPRange(IP6Range const &range);
376
378 IPRange(IPRangeView const &view);
379
386 IPRange(string_view const &text);
387
394 self_type &assign(IP4Addr const &min, IP4Addr const &max);
395
402 self_type &assign(IP6Addr const &min, IP6Addr const &max);
403
405 self_type &operator=(IPRangeView const &rv);
406
408 bool operator==(self_type const &that) const;
410 bool operator!=(self_type const &that) const;
411
413 bool is_ip4() const;
414
416 bool is_ip6() const;
417
423 bool is(sa_family_t family) const;
424
433 bool load(std::string_view const &text);
434
440 bool contains(IPAddr const& addr) const;
441
447 bool contains(IP6Addr const& addr) const;
448
454 bool contains(IP4Addr const& addr) const;
455
457 IPAddr min() const;
458
460 IPAddr max() const;
461
463 bool empty() const;
464
466 self_type &clear();
467
469 IP4Range const & ip4() const;
470
472 IP6Range const & ip6() const;
473
475 sa_family_t family() const;
476
483 IPMask network_mask() const;
484
486 class NetSource;
487
504 NetSource networks() const;
505
506protected:
516 union {
517 std::monostate _nil;
520 } _range{std::monostate{}};
521
523 sa_family_t _family{AF_UNSPEC};
524};
525
532 using self_type = NetSource;
533public:
535
537 explicit NetSource(range_type const &range);
538
540 explicit NetSource(IPRangeView const &rv);
541
543 NetSource(self_type const &that) = default;
544
546 using iterator = self_type;
549
550 iterator begin() const;
551 iterator end() const;
552
554 IPNet operator*() const;
555
557 self_type *operator->();
558
561 IPAddr addr() const;
562
565 IPMask mask() const;
566
568 self_type &operator++();
569
571 self_type operator++(int);
572
574 bool operator==(self_type const &that) const;
575
577 bool operator!=(self_type const &that) const;
578
579protected:
580 union {
581 std::monostate _nil;
584 };
585
586 sa_family_t _family = AF_UNSPEC;
587};
588
605 using self_type = IPRangeView;
606 friend IPRange;
608 union storage_type {
609 std::monostate _nil;
610 IP4Range const *_4;
611 IP6Range const *_6;
612 void const *_void;
613
614 // These constructors are needed to make the default construction / assignent methods work.
615 // Otherwise the compiler thinks the union isn't initialized.
616 storage_type() = default;
617 storage_type(std::monostate) {}
618 storage_type(storage_type const &that);
619 storage_type &operator=(storage_type const &rhs);
620 };
621
622public:
624 IPRangeView() = default;
625
627 bool operator==(IPRange const &r) const;
628
630 bool valid() const;
631
632 // @return @c true if the range is empty (invalid views are empty)
633 bool empty() const;
634
636 self_type &clear();
637
639 self_type &assign(IP4Range const &r);
640
642 self_type &assign(IP6Range const &r);
643
645 bool is_ip4() const;
646
648 bool is_ip6() const;
649
655 bool is(sa_family_t family) const;
656
662 bool contains(IPAddr const& addr) const;
663
669 bool contains(IP6Addr const& addr) const;
670
676 bool contains(IP4Addr const& addr) const;
677
679 IP4Range const &ip4() const;
680
682 IP6Range const &ip6() const;
683
686
688 IPAddr min() const;
689
691 IPAddr max() const;
692
694 bool operator==(self_type const &that) const;
695
697 bool operator!=(self_type const &that) const;
698
706 networks() const {
707 return IPRange::NetSource(*this);
708 }
709
711
712protected:
713 storage_type _raw = {std::monostate()};
714 sa_family_t _family = AF_UNSPEC;
715};
716
718class IP4Net {
719 using self_type = IP4Net;
720public:
721 IP4Net() = default;
722 IP4Net(self_type const &that) = default;
723
733 IP4Net(IP4Addr addr, IPMask mask);
734
735 IP4Net(swoc::TextView text) { this->load(text); }
736
742 bool load(swoc::TextView text);
743
745 bool empty() const;
746
748 IP4Addr min() const;
749
751 IP4Addr max() const;
752
754 IPMask const &mask() const;
755
757 IP4Range as_range() const;
758
765 self_type &assign(IP4Addr const &addr, IPMask const &mask);
766
768 self_type &
770 _mask.clear();
771 return *this;
772 }
773
775 bool operator==(self_type const &that) const;
776
778 bool operator!=(self_type const &that) const;
779
780protected:
783};
784
786class IP6Net {
787 using self_type = IP6Net;
788public:
789 IP6Net() = default;
790 IP6Net(self_type const &that) = default;
791
801 IP6Net(IP6Addr addr, IPMask mask);
802
810 IP6Net(TextView text) { this->load(text); }
811
817 bool load(swoc::TextView text);
818
820 bool empty() const;
821
823 IP6Addr min() const;
824
826 IP6Addr max() const;
827
829 IPMask const &mask() const;
830
832 IP6Range as_range() const;
833
840 self_type &assign(IP6Addr const &addr, IPMask const &mask);
841
843 self_type &
845 _mask.clear();
846 return *this;
847 }
848
850 bool operator==(self_type const &that) const;
851
853 bool operator!=(self_type const &that) const;
854
855protected:
858};
859
863class IPNet {
864 using self_type = IPNet;
865public:
866 IPNet() = default;
867 IPNet(self_type const &that) = default;
868
878 IPNet(IPAddr const &addr, IPMask const &mask);
879
887 IPNet(TextView text);
888
894 bool load(swoc::TextView text);
895
897 bool empty() const;
898
900 IPAddr min() const;
901
903 IPAddr max() const;
904
906 IPMask::raw_type width() const;
907
909 IPMask const &mask() const;
910
912 IPRange as_range() const;
913
915 bool
916 is_ip4() const {
917 return _addr.is_ip4();
918 }
919
921 bool
922 is_ip6() const {
923 return _addr.is_ip6();
924 }
925
927 sa_family_t
928 family() const {
929 return _addr.family();
930 }
931
933 IP4Net ip4() const;
934
936 IP6Net ip6() const;
937
944 self_type &assign(IPAddr const &addr, IPMask const &mask);
945
947 self_type &clear();
948
950 bool operator==(self_type const &that) const;
951
953 bool operator!=(self_type const &that) const;
954
955protected:
958};
959
960// --------------------------------------------------------------------------
961namespace detail {
979template <typename PAYLOAD> struct ip_space_const_value_type {
980 using self_type = ip_space_const_value_type;
981
983 PAYLOAD *_payload = nullptr;
984
985 ip_space_const_value_type() = default;
986
988 self_type &clear();
989
996 self_type &assign(IP4Range const &r, PAYLOAD &payload);
997
1004 self_type &assign(IP6Range const &r, PAYLOAD &payload);
1005
1011 self_type &assign(self_type const &that);
1012
1014 std::tuple<IPRangeView, PAYLOAD &>
1015 tuple() const {
1016 return {_rv, *_payload};
1017 }
1018
1020 bool operator==(std::tuple<swoc::IPRange, PAYLOAD> const &t) const;
1021
1023 IPRange
1024 range() const {
1025 return _rv;
1026 }
1027
1030 range_view() const {
1031 return _rv;
1032 }
1033
1035 PAYLOAD const &
1036 payload() const {
1037 return *_payload;
1038 }
1039};
1040
1053template <typename PAYLOAD> struct ip_space_value_type : ip_space_const_value_type<PAYLOAD> {
1054 using self_type = ip_space_value_type;
1055 using super_type = ip_space_const_value_type<PAYLOAD>;
1056
1058 PAYLOAD &
1060 return *super_type::_payload;
1061 }
1062};
1063
1064template <typename PAYLOAD>
1065auto
1067 _rv.clear();
1068 _payload = nullptr;
1069 return *this;
1070}
1071
1072template <typename PAYLOAD>
1073auto
1075 _rv.assign(r);
1076 _payload = &payload;
1077 return *this;
1078}
1079
1080template <typename PAYLOAD>
1081auto
1083 _rv.assign(r);
1084 _payload = &payload;
1085 return *this;
1086}
1087
1088template <typename PAYLOAD>
1089auto
1090ip_space_const_value_type<PAYLOAD>::assign(ip_space_const_value_type::self_type const &that) -> self_type & {
1091 _rv = that._rv;
1092 _payload = that._payload;
1093 return *this;
1094}
1095
1096template <typename PAYLOAD>
1097bool
1098ip_space_const_value_type<PAYLOAD>::operator==(std::tuple<swoc::IPRange, PAYLOAD> const &t) const {
1099 return _rv == std::get<0>(t) && std::get<1>(t) == *_payload;
1100}
1101
1102} // namespace detail
1103
1117template <typename PAYLOAD> class IPSpace {
1118 using self_type = IPSpace;
1119 using IP4Space = DiscreteSpace<IP4Addr, PAYLOAD>;
1120 using IP6Space = DiscreteSpace<IP6Addr, PAYLOAD>;
1121
1122public:
1123 using payload_t = PAYLOAD;
1126
1128 IPSpace() = default;
1129
1138 self_type &mark(IPRange const &range, PAYLOAD const &payload);
1139
1147 self_type &mark_bulk(std::pair<DiscreteRange<IP4Addr>, PAYLOAD>* range_payloads, size_t size, bool is_sorted = false);
1148
1150 self_type &mark_bulk(std::vector<std::pair<DiscreteRange<IP4Addr>, PAYLOAD>>& range_payloads, bool is_sorted = false);
1151
1159 self_type &mark_bulk(std::pair<DiscreteRange<IP6Addr>, PAYLOAD>* range_payloads, size_t size, bool is_sorted = false);
1160
1162 self_type &mark_bulk(std::vector<std::pair<DiscreteRange<IP6Addr>, PAYLOAD>>& range_payloads, bool is_sorted = false);
1163
1172 self_type &fill(IPRange const &range, PAYLOAD const &payload);
1173
1179 self_type &erase(IPRange const &range);
1180
1200 template <typename F, typename U = PAYLOAD> self_type &blend(IPRange const &range, U const &color, F &&blender);
1201
1202 template <typename F, typename U = PAYLOAD> self_type &blend(IP4Range const &range, U const &color, F &&blender);
1203
1204 template <typename F, typename U = PAYLOAD> self_type &blend(IP6Range const &range, U const &color, F &&blender);
1205
1207 size_t count() const;
1208
1210 size_t count_ip4() const;
1211
1213 size_t count_ip6() const;
1214
1220 size_t count(sa_family_t f) const;
1221
1223 bool empty() const;
1224
1226 void clear();
1227
1247 using self_type = const_iterator;
1248 friend class IPSpace;
1249
1250 public:
1252 // STL algorithm compliance.
1253 using iterator_category = std::bidirectional_iterator_tag;
1254 using pointer = value_type const *;
1255 using reference = value_type const &;
1256 using difference_type = int;
1257
1259 const_iterator() = default;
1260
1262 const_iterator(self_type const &that) = default;
1263
1265 self_type &operator=(self_type const &that);
1266
1270 self_type &operator++();
1271
1275 self_type &operator--();
1276
1280 self_type operator++(int);
1281
1285 self_type operator--(int);
1286
1289 reference operator*() const;
1290
1293 pointer operator->() const;
1294
1296 bool operator==(self_type const &that) const;
1297
1299 bool operator!=(self_type const &that) const;
1300
1301 protected:
1302 // These are stored non-const to make implementing @c iterator easier. The containing class provides the
1303 // required @c const protection. Internally a tuple of iterators is stored for forward iteration. If
1304 // the primary (ipv4) iterator is at the end, then use the secondary (ipv6) iterator. The reverse
1305 // is done for reverse iteration. This depends on the extra support @c IntrusiveDList iterators
1306 // provide.
1307 typename IP4Space::iterator _iter_4;
1308 typename IP6Space::iterator _iter_6;
1310 value_type _value;
1311
1319 const_iterator(typename IP4Space::const_iterator const &iter4, typename IP6Space::const_iterator const &iter6);
1320
1321 // These are required because the actual range type for the subspaces is @c DiscreteRange<T>
1322 // and returning that type without a cast creates a temporary which causes some nasty side effects.
1323
1325 IP4Range const &
1326 r4() {
1327 return static_cast<IP4Range const &>(_iter_4->range());
1328 }
1329
1330 IP6Range const &
1331 r6() {
1332 return static_cast<IP6Range const &>(_iter_6->range());
1333 }
1334 };
1335
1342 class iterator : public const_iterator {
1343 using self_type = iterator;
1344 using super_type = const_iterator;
1345
1346 friend class IPSpace;
1347
1348 protected:
1349 using super_type::super_type;
1353
1354 public:
1357 using pointer = value_type *;
1358 using reference = value_type &;
1359
1361 iterator() = default;
1362
1364 iterator(self_type const &that) = default;
1365
1367 self_type &operator=(self_type const &that);
1368
1372 self_type &operator++();
1373
1377 self_type &operator--();
1378
1382 self_type operator++(int);
1383
1387 self_type operator--(int);
1388
1391 reference operator*() const;
1392
1395 pointer operator->() const;
1396
1397 protected:
1398 // Retrieve the value and convert from the super (const) type value to the value for iterator.
1399 value_type &value() const;
1400 };
1401
1407 iterator find(IPAddr const &addr);
1408
1414 const_iterator find(IPAddr const &addr) const;
1415
1421 iterator find(IP4Addr const &addr);
1422
1428 const_iterator find(IP4Addr const &addr) const;
1429
1435 iterator find(IP6Addr const &addr);
1436
1442 const_iterator find(IP6Addr const &addr) const;
1443
1445 iterator begin();
1446
1448 const_iterator begin() const;
1449
1451 iterator end();
1452
1454 const_iterator end() const;
1455
1457 iterator begin_ip4();
1459 const_iterator begin_ip4() const;
1460
1462 iterator end_ip4();
1464 const_iterator end_ip4() const;
1465
1467 iterator begin_ip6();
1469 const_iterator begin_ip6() const;
1471 iterator end_ip6();
1473 const_iterator end_ip6() const;
1474
1476 const_iterator begin(sa_family_t family) const;
1477
1479 const_iterator end(sa_family_t family) const;
1480
1486 std::pair<iterator, iterator>
1488 auto &&[begin, end] = _ip4.intersection(r);
1489 return {this->iterator_at(begin), this->iterator_at(end)};
1490 }
1491
1497 std::pair<iterator, iterator>
1499 auto &&[begin, end] = _ip6.intersection(r);
1500 return {this->iterator_at(begin), this->iterator_at(end)};
1501 }
1502
1508 std::pair<iterator, iterator>
1510 if (r.is_ip4()) {
1511 return this->intersection(r.ip4());
1512 } else if (r.is_ip6()) {
1513 return this->intersection(r.ip6());
1514 }
1515 return {this->end(), this->end()};
1516 }
1517
1518protected:
1519 IP4Space _ip4;
1520 IP6Space _ip6;
1521
1522 iterator
1523 iterator_at(typename IP4Space::const_iterator const &spot) {
1524 return iterator(spot, _ip6.begin());
1525 }
1526 iterator
1527 iterator_at(typename IP6Space::const_iterator const &spot) {
1528 return iterator(_ip4.end(), spot);
1529 }
1530
1531 friend class IPRangeSet;
1532};
1533
1543 using self_type = IPRangeSet;
1544
1548 static inline constexpr struct Mark {
1549 using self_type = Mark;
1552 bool operator==(self_type const &that);
1553 bool operator!=(self_type const &that);
1554 } MARK{};
1555
1557 using Space = swoc::IPSpace<Mark>;
1558
1559public:
1561 IPRangeSet() = default;
1562
1570 self_type &mark(swoc::IPRange const &r);
1571
1579 self_type &fill(swoc::IPRange const &r);
1580
1582 bool contains(swoc::IPAddr const &addr) const;
1583
1585 size_t count() const;
1586
1587 bool empty() const;
1588
1590 void clear();
1591
1594 using self_type = const_iterator;
1595 using super_type = Space::const_iterator;
1596 friend class IPRangeSet;
1597
1598 public:
1599 using value_type = IPRangeView;
1600 // STL algorithm compliance.
1601 using iterator_category = std::bidirectional_iterator_tag;
1602 using pointer = value_type const *;
1603 using reference = value_type const &;
1604 using difference_type = int;
1605
1607 const_iterator() = default;
1608
1610 const_iterator(self_type const &that) = default;
1611
1613 self_type &operator=(self_type const &that) = default;
1614
1618 self_type &operator++();
1619
1623 self_type &operator--();
1624
1628 self_type operator++(int);
1629
1633 self_type operator--(int);
1634
1637 reference operator*() const;
1638
1641 pointer operator->() const;
1642
1644 bool operator==(self_type const &that) const;
1645
1647 bool operator!=(self_type const &that) const;
1648
1649 protected:
1650 const_iterator(super_type const &spot) : _iter(spot) {}
1651
1652 super_type _iter;
1654 };
1655
1656 using iterator = const_iterator;
1657
1660 begin() const {
1661 return _addrs.begin();
1662 }
1663
1664 const_iterator
1665 end() const {
1666 return _addrs.end();
1667 }
1668
1669protected:
1671 Space _addrs;
1672};
1673
1674inline auto
1675IPRangeSet::mark(swoc::IPRange const &r) -> self_type & {
1676 _addrs.mark(r, MARK);
1677 return *this;
1678}
1679
1680inline auto
1681IPRangeSet::fill(swoc::IPRange const &r) -> self_type & {
1682 _addrs.mark(r, MARK);
1683 return *this;
1684}
1685
1686inline bool
1688 return _addrs.find(addr) != _addrs.end();
1689}
1690
1691inline size_t
1693 return _addrs.count();
1694}
1695
1696inline bool
1697IPRangeSet::empty() const {
1698 return _addrs.empty();
1699}
1700
1701inline void
1703 _addrs.clear();
1704}
1705
1706inline bool
1707IPRangeSet::Mark::operator==(IPRangeSet::Mark::self_type const &) {
1708 return true;
1709}
1710
1711inline bool
1712IPRangeSet::Mark::operator!=(IPRangeSet::Mark::self_type const &) {
1713 return false;
1714}
1715
1716template <typename PAYLOAD>
1717IPSpace<PAYLOAD>::const_iterator::const_iterator(typename IP4Space::const_iterator const &iter4,
1718 typename IP6Space::const_iterator const &iter6)
1719 : _iter_4(static_cast<typename IP4Space::iterator const &>(iter4)),
1720 _iter_6(static_cast<typename IP6Space::iterator const &>(iter6)) {
1721 if (_iter_4.has_next()) {
1722 _value.assign(this->r4(), _iter_4->payload());
1723 } else if (_iter_6.has_next()) {
1724 _value.assign(this->r6(), _iter_6->payload());
1725 }
1726}
1727
1728template <typename PAYLOAD>
1729auto
1730IPSpace<PAYLOAD>::const_iterator::operator=(self_type const &that) -> self_type & {
1731 _iter_4 = that._iter_4;
1732 _iter_6 = that._iter_6;
1733 _value.assign(that._value);
1734 return *this;
1735}
1736
1737template <typename PAYLOAD>
1738auto
1740 bool incr_p = false;
1741 if (_iter_4.has_next()) {
1742 ++_iter_4;
1743 incr_p = true;
1744 if (_iter_4.has_next()) {
1745 _value.assign(this->r4(), _iter_4->payload());
1746 return *this;
1747 }
1748 }
1749
1750 if (_iter_6.has_next()) {
1751 if (incr_p || (++_iter_6).has_next()) {
1752 _value.assign(this->r6(), _iter_6->payload());
1753 return *this;
1754 }
1755 }
1756 _value.clear();
1757 return *this;
1758}
1759
1760template <typename PAYLOAD>
1761auto
1763 self_type zret(*this);
1764 ++*this;
1765 return zret;
1766}
1767
1768template <typename PAYLOAD>
1769auto
1771 if (_iter_6.has_prev()) {
1772 --_iter_6;
1773 _value.assign(this->r6(), _iter_6->payload());
1774 return *this;
1775 }
1776 if (_iter_4.has_prev()) {
1777 --_iter_4;
1778 _value.assign(this->r4(), _iter_4->payload());
1779 return *this;
1780 }
1781 _value.clear();
1782 return *this;
1783}
1784
1785template <typename PAYLOAD>
1786auto
1788 self_type zret(*this);
1789 --*this;
1790 return zret;
1791}
1792
1793template <typename PAYLOAD>
1794auto
1796 return _value;
1797}
1798
1799template <typename PAYLOAD>
1800auto
1802 return &_value;
1803}
1804
1805/* Bit of subtlety with equality - although it seems that if @a _iter_4 is valid, it doesn't matter
1806 * where @a _iter6 is (because it is really the iterator location that's being checked), it's
1807 * necessary to do the @a _iter_4 validity on both iterators to avoid the case of a false positive
1808 * where different internal iterators are valid. However, in practice the other (non-active)
1809 * iterator won't have an arbitrary value, it will be either @c begin or @c end in step with the
1810 * active iterator therefore it's effective and cheaper to just check both values.
1811 */
1812
1813template <typename PAYLOAD>
1814bool
1816 return _iter_4 == that._iter_4 && _iter_6 == that._iter_6;
1817}
1818
1819template <typename PAYLOAD>
1820bool
1822 return _iter_4 != that._iter_4 || _iter_6 != that._iter_6;
1823}
1824
1825template <typename PAYLOAD>
1826auto
1827IPSpace<PAYLOAD>::iterator::operator=(self_type const &that) -> self_type & {
1828 this->super_type::operator=(that);
1829 return *this;
1830}
1831
1832template <typename PAYLOAD>
1833auto
1834IPSpace<PAYLOAD>::iterator::value() const -> value_type & {
1835 return reinterpret_cast<value_type &>(const_cast<self_type *>(this)->_value);
1836}
1837
1838template <typename PAYLOAD>
1839auto
1841 return &(this->value());
1842}
1843
1844template <typename PAYLOAD>
1845auto
1847 return this->value();
1848}
1849
1850template <typename PAYLOAD>
1851auto
1853 this->super_type::operator++();
1854 return *this;
1855}
1856
1857template <typename PAYLOAD>
1858auto
1860 self_type zret{*this};
1861 ++*this;
1862 return zret;
1863}
1864
1865template <typename PAYLOAD>
1866auto
1868 this->super_type::operator--();
1869 return *this;
1870}
1871
1872template <typename PAYLOAD>
1873auto
1875 self_type zret{*this};
1876 --*this;
1877 return zret;
1878}
1879
1881
1882// +++ IPRange +++
1883
1884inline IPRangeView::storage_type::storage_type(IPRangeView::storage_type const &that) : _void(that._void) {}
1885
1886inline IPRangeView::storage_type &
1887IPRangeView::storage_type::operator=(IPRangeView::storage_type const &rhs) {
1888 _void = rhs._void;
1889 return *this;
1890}
1891
1892inline IP4Range::IP4Range(string_view const &text) {
1893 this->load(text);
1894}
1895
1896inline auto
1898 return {NetSource{*this}};
1899}
1900
1901inline IP6Range::IP6Range(string_view const &text) {
1902 this->load(text);
1903}
1904
1905inline auto
1907 return {NetSource{*this}};
1908}
1909
1910inline IPRange::IPRange(IP4Range const &range) : _family(AF_INET) {
1911 _range._ip4 = range;
1912}
1913
1914inline IPRange::IPRange(IP6Range const &range) : _family(AF_INET6) {
1915 _range._ip6 = range;
1916}
1917
1918inline IPRange::IPRange(IP4Addr const &min, IP4Addr const &max) {
1919 this->assign(min, max);
1920}
1921
1922inline IPRange::IPRange(IP6Addr const &min, IP6Addr const &max) {
1923 this->assign(min, max);
1924}
1925
1926inline IPRange::IPRange(string_view const &text) {
1927 this->load(text);
1928}
1929
1930inline IPRange::IPRange(IPRangeView const &view) {
1931 if (AF_INET == view._family) {
1932 *this = *view._raw._4;
1933 } else if (AF_INET6 == view._family) {
1934 *this = *view._raw._6;
1935 }
1936}
1937
1938inline auto
1939IPRange::assign(IP4Addr const &min, IP4Addr const &max) -> self_type & {
1940 _range._ip4.assign(min, max);
1941 _family = AF_INET;
1942 return *this;
1943}
1944
1945inline auto
1946IPRange::assign(IP6Addr const &min, IP6Addr const &max) -> self_type & {
1947 _range._ip6.assign(min, max);
1948 _family = AF_INET6;
1949 return *this;
1950}
1951
1952inline auto
1953IPRange::operator=(const IPRangeView &rv) -> self_type & {
1954 if (AF_INET == rv._family) {
1955 *this = *rv._raw._4;
1956 } else if (AF_INET6 == rv._family) {
1957 *this = *rv._raw._6;
1958 }
1959 return *this;
1960}
1961
1962inline auto
1963IPRange::clear() -> self_type & {
1964 _family = AF_UNSPEC;
1965 return *this;
1966}
1967
1968inline auto
1970 return {NetSource{*this}};
1971}
1972
1973inline bool
1974IPRange::is(sa_family_t family) const {
1975 return family == _family;
1976}
1977
1978inline bool
1979IPRange::operator!=(const self_type &that) const {
1980 return !(*this == that);
1981}
1982
1983inline bool
1985 return AF_INET == _family;
1986}
1987
1988inline bool
1990 return AF_INET6 == _family;
1991}
1992
1993inline sa_family_t IPRange::family() const {
1994 return _family;
1995}
1996inline IP4Range const& IPRange::ip4() const {
1997 return _range._ip4;
1998}
1999
2000inline IP6Range const& IPRange::ip6() const {
2001 return _range._ip6;
2002}
2003
2004inline auto
2005IPRangeView::clear() -> self_type & {
2006 _family = AF_UNSPEC;
2007 return *this;
2008}
2009
2010inline bool
2011IPRangeView::empty() const {
2012 if (AF_INET6 == _family) {
2013 return _raw._6->empty();
2014 } else if (AF_INET == _family) {
2015 return _raw._4->empty();
2016 } else {
2017 return true;
2018 }
2019}
2020
2021inline bool
2023 return AF_INET == _family;
2024}
2025
2026inline bool
2028 return AF_INET6 == _family;
2029}
2030
2031inline bool
2032IPRangeView::is(sa_family_t f) const {
2033 return f == _family;
2034}
2035
2036inline bool IPRange::contains(IPAddr const & addr) const {
2037 if (addr.family() != _family) {
2038 return false;
2039 }
2040 if (this->ip4()) {
2041 return _range._ip4.contains(addr.ip4());
2042 } else if (this->is_ip6()) {
2043 return _range._ip6.contains(addr.ip6());
2044 }
2045 return false;
2046}
2047
2048inline bool IPRange::contains(IP6Addr const & addr) const {
2049 return this->is_ip6() && _range._ip6.contains(addr);
2050}
2051
2052inline bool IPRange::contains(IP4Addr const & addr) const {
2053 return this->is_ip4() && _range._ip4.contains(addr);
2054}
2055
2056inline IP4Range const &
2058 return *_raw._4;
2059}
2060
2061inline IP6Range const &
2063 return *_raw._6;
2064}
2065
2066inline bool
2068 return AF_INET == _family || AF_INET6 == _family;
2069}
2070
2071inline auto
2072IPRangeView::assign(IP4Range const &r) -> self_type & {
2073 _family = r.family();
2074 _raw._4 = &r;
2075 return *this;
2076}
2077
2078inline auto
2079IPRangeView::assign(IP6Range const &r) -> self_type & {
2080 _family = r.family();
2081 _raw._6 = &r;
2082 return *this;
2083}
2084
2085inline bool
2086IPRangeView::operator!=(IPRangeView::self_type const &that) const {
2087 return !(*this == that);
2088}
2089
2090inline IPAddr
2092 return AF_INET == _family ? _raw._4->min() : AF_INET6 == _family ? _raw._6->min() : IPAddr::INVALID;
2093}
2094
2095inline IPAddr
2097 return AF_INET == _family ? _raw._4->max() : AF_INET6 == _family ? _raw._6->max() : IPAddr::INVALID;
2098}
2099
2100inline bool IPRangeView::contains(IPAddr const& addr) const {
2101 if (_family != addr.family()) {
2102 return false;
2103 }
2104 return (_family == addr.family() ) &&
2105 ( ( this->is_ip4() && _raw._4->contains(addr.ip4()) ) ||
2106 ( this->is_ip6() && _raw._6->contains(addr.ip6()) )
2107 );
2108}
2109
2110inline bool IPRangeView::contains(IP6Addr const& addr) const {
2111 return this->is_ip6() && _raw._6->contains(addr);
2112}
2113
2114inline bool IPRangeView::contains(IP4Addr const& addr) const {
2115 return this->is_ip4() && _raw._4->contains(addr);
2116}
2117
2118// +++ IPNet +++
2119
2121
2122inline IPMask const &
2124 return _mask;
2125}
2126
2127inline bool
2129 return !_mask.is_valid();
2130}
2131
2132inline IP4Addr
2134 return _addr;
2135}
2136
2137inline IP4Addr
2139 return _addr | _mask;
2140}
2141
2142inline IP4Range
2144 return {this->min(), this->max()};
2145}
2146
2147inline bool
2148IP4Net::operator==(self_type const &that) const {
2149 return _mask == that._mask && _addr == that._addr;
2150}
2151
2152inline bool
2153IP4Net::operator!=(self_type const &that) const {
2154 return _mask != that._mask || _addr != that._addr;
2155}
2156
2157inline IP4Net::self_type &
2158IP4Net::assign(IP4Addr const &addr, IPMask const &mask) {
2159 _addr = addr & mask;
2160 _mask = mask;
2161 return *this;
2162}
2163
2165
2166inline IPMask const &
2168 return _mask;
2169}
2170
2171inline bool
2173 return !_mask.is_valid();
2174}
2175
2176inline IP6Addr
2178 return _addr;
2179}
2180
2181inline IP6Addr
2183 return _addr | _mask;
2184}
2185
2186inline IP6Range
2188 return {this->min(), this->max()};
2189}
2190
2191inline bool
2192IP6Net::operator==(self_type const &that) const {
2193 return _mask == that._mask && _addr == that._addr;
2194}
2195
2196inline bool
2197IP6Net::operator!=(self_type const &that) const {
2198 return _mask != that._mask || _addr != that._addr;
2199}
2200
2201inline IP6Net::self_type &
2202IP6Net::assign(IP6Addr const &addr, IPMask const &mask) {
2203 _addr = addr & mask;
2204 _mask = mask;
2205 return *this;
2206}
2207
2208inline IPNet::IPNet(IPAddr const &addr, IPMask const &mask) : _addr(addr & mask), _mask(mask) {}
2209
2211 this->load(text);
2212}
2213
2214inline bool
2216 return !_mask.is_valid();
2217}
2218
2219inline IPAddr
2220IPNet::min() const {
2221 return _addr;
2222}
2223
2224inline IPAddr
2225IPNet::max() const {
2226 return _addr | _mask;
2227}
2228
2229inline IPMask::raw_type
2231 return _mask.width();
2232}
2233
2234inline IPMask const &
2236 return _mask;
2237}
2238
2239inline IPRange
2241 return {this->min(), this->max()};
2242}
2243
2244inline IPNet::self_type &
2245IPNet::assign(IPAddr const &addr, IPMask const &mask) {
2246 _addr = addr & mask;
2247 _mask = mask;
2248 return *this;
2249}
2250
2251inline bool
2252IPNet::operator==(IPNet::self_type const &that) const {
2253 return _mask == that._mask && _addr == that._addr;
2254}
2255
2256inline bool
2257IPNet::operator!=(IPNet::self_type const &that) const {
2258 return _mask != that._mask || _addr != that._addr;
2259}
2260
2261inline bool
2262operator==(IPNet const &lhs, IP4Net const &rhs) {
2263 return lhs.is_ip4() && lhs.ip4() == rhs;
2264}
2265
2266inline bool
2267operator==(IP4Net const &lhs, IPNet const &rhs) {
2268 return rhs.is_ip4() && rhs.ip4() == lhs;
2269}
2270
2271inline bool
2272operator==(IPNet const &lhs, IP6Net const &rhs) {
2273 return lhs.is_ip6() && lhs.ip6() == rhs;
2274}
2275
2276inline bool
2277operator==(IP6Net const &lhs, IPNet const &rhs) {
2278 return rhs.is_ip6() && rhs.ip6() == lhs;
2279}
2280
2281inline IP4Net
2282IPNet::ip4() const {
2283 return IP4Net{_addr.ip4(), _mask};
2284}
2285
2286inline IP6Net
2287IPNet::ip6() const {
2288 return IP6Net{_addr.ip6(), _mask};
2289}
2290
2291inline auto
2292IPNet::clear() -> self_type & {
2293 _mask.clear();
2294 return *this;
2295}
2296
2297// +++ Range -> Network classes +++
2298
2299inline bool
2300IP4Range::NetSource::is_valid(swoc::IP4Addr mask) const {
2301 return ((mask._addr & _range._min._addr) == _range._min._addr) && ((_range._min._addr | ~mask._addr) <= _range._max._addr);
2302}
2303
2304inline IP4Net
2306 return IP4Net{_range.min(), IPMask{_cidr}};
2307}
2308
2311 return *this;
2312}
2313
2316 return self_type{range_type{}};
2317}
2318
2319inline bool
2321 return _range.empty();
2322}
2323
2324inline IPMask
2326 return IPMask{_cidr};
2327}
2328
2329inline auto
2331 return this;
2332}
2333
2334inline IP4Addr const &
2336 return _range.min();
2337}
2338
2339inline bool
2340IP4Range::NetSource::operator==(IP4Range::NetSource::self_type const &that) const {
2341 return ((_cidr == that._cidr) && (_range == that._range)) || (_range.empty() && that._range.empty());
2342}
2343
2344inline bool
2345IP4Range::NetSource::operator!=(IP4Range::NetSource::self_type const &that) const {
2346 return !(*this == that);
2347}
2348
2349inline auto
2351 return *this;
2352}
2353
2354inline auto
2356 return self_type{range_type{}};
2357}
2358
2359inline bool
2361 return _range.empty();
2362}
2363
2364inline IP6Net
2366 return IP6Net{_range.min(), _mask};
2367}
2368
2369inline auto
2371 return this;
2372}
2373
2374inline bool
2375IP6Range::NetSource::is_valid(IPMask const &mask) {
2376 return ((_range.min() & mask) == _range.min()) && ((_range.min() | mask) <= _range.max());
2377}
2378
2379inline bool
2380IP6Range::NetSource::operator==(IP6Range::NetSource::self_type const &that) const {
2381 return ((_mask == that._mask) && (_range == that._range)) || (_range.empty() && that._range.empty());
2382}
2383
2384inline bool
2385IP6Range::NetSource::operator!=(IP6Range::NetSource::self_type const &that) const {
2386 return !(*this == that);
2387}
2388
2389inline IP6Addr const &
2391 return _range.min();
2392}
2393
2394inline IPMask
2396 return _mask;
2397}
2398
2400 if (range.is_ip4()) {
2401 new (&_ip4) decltype(_ip4)(range.ip4());
2402 _family = AF_INET;
2403 } else if (range.is_ip6()) {
2404 new (&_ip6) decltype(_ip6)(range.ip6());
2405 _family = AF_INET6;
2406 }
2407}
2408
2410 if (rv.is_ip4()) {
2411 new (&_ip4) decltype(_ip4)(rv.ip4());
2412 _family = AF_INET;
2413 } else if (rv.is_ip6()) {
2414 new (&_ip6) decltype(_ip6)(rv.ip6());
2415 _family = AF_INET6;
2416 }
2417}
2418
2419inline auto
2421 return *this;
2422}
2423
2424inline auto
2426 return AF_INET == _family ? self_type{IP4Range{}} : AF_INET6 == _family ? self_type{IP6Range{}} : self_type{IPRange{}};
2427}
2428
2429inline IPAddr
2431 if (AF_INET == _family) {
2432 return _ip4.addr();
2433 } else if (AF_INET6 == _family) {
2434 return _ip6.addr();
2435 }
2436 return {};
2437}
2438
2439inline IPMask
2441 if (AF_INET == _family) {
2442 return _ip4.mask();
2443 } else if (AF_INET6 == _family) {
2444 return _ip6.mask();
2445 }
2446 return {};
2447}
2448
2449inline IPNet
2451 return {this->addr(), this->mask()};
2452}
2453
2454inline auto
2456 if (AF_INET == _family) {
2457 ++_ip4;
2458 } else if (AF_INET6 == _family) {
2459 ++_ip6;
2460 }
2461 return *this;
2462}
2463
2464inline auto
2466 return this;
2467}
2468
2469inline bool
2470IPRange::NetSource::operator==(self_type const &that) const {
2471 if (_family != that._family) {
2472 return false;
2473 }
2474 if (AF_INET == _family) {
2475 return _ip4 == that._ip4;
2476 } else if (AF_INET6 == _family) {
2477 return _ip6 == that._ip6;
2478 } else if (AF_UNSPEC == _family) {
2479 return true;
2480 }
2481 return false;
2482}
2483
2484inline bool
2485IPRange::NetSource::operator!=(self_type const &that) const {
2486 return !(*this == that);
2487}
2488
2489// --- IPSpace
2490
2491template <typename PAYLOAD>
2492auto
2493IPSpace<PAYLOAD>::mark_bulk(std::pair<DiscreteRange<IP4Addr>, PAYLOAD>* range_payloads, size_t size, bool is_sorted) -> self_type & {
2494 _ip4.mark_bulk(range_payloads, size, is_sorted);
2495 return *this;
2496}
2497
2498template <typename PAYLOAD>
2499auto
2500IPSpace<PAYLOAD>::mark_bulk(std::pair<DiscreteRange<IP6Addr>, PAYLOAD>* range_payloads, size_t size, bool is_sorted) -> self_type & {
2501 _ip6.mark_bulk(range_payloads, size, is_sorted);
2502 return *this;
2503}
2504
2505template <typename PAYLOAD>
2506auto
2507IPSpace<PAYLOAD>::mark_bulk(std::vector<std::pair<DiscreteRange<IP4Addr>, PAYLOAD>>& range_payloads, bool is_sorted) -> self_type & {
2508 _ip4.mark_bulk(range_payloads, is_sorted);
2509 return *this;
2510}
2511
2512template <typename PAYLOAD>
2513auto
2514IPSpace<PAYLOAD>::mark_bulk(std::vector<std::pair<DiscreteRange<IP6Addr>, PAYLOAD>>& range_payloads, bool is_sorted) -> self_type & {
2515 _ip6.mark_bulk(range_payloads, is_sorted);
2516 return *this;
2517}
2518
2519template <typename PAYLOAD>
2520auto
2521IPSpace<PAYLOAD>::mark(IPRange const &range, PAYLOAD const &payload) -> self_type & {
2522 if (range.is(AF_INET)) {
2523 _ip4.mark(range.ip4(), payload);
2524 } else if (range.is(AF_INET6)) {
2525 _ip6.mark(range.ip6(), payload);
2526 }
2527 return *this;
2528}
2529
2530template <typename PAYLOAD>
2531auto
2532IPSpace<PAYLOAD>::fill(IPRange const &range, PAYLOAD const &payload) -> self_type & {
2533 if (range.is(AF_INET6)) {
2534 _ip6.fill(range.ip6(), payload);
2535 } else if (range.is(AF_INET)) {
2536 _ip4.fill(range.ip4(), payload);
2537 }
2538 return *this;
2539}
2540
2541template <typename PAYLOAD>
2542auto
2543IPSpace<PAYLOAD>::erase(IPRange const &range) -> self_type & {
2544 if (range.is(AF_INET)) {
2545 _ip4.erase(range.ip4());
2546 } else if (range.is(AF_INET6)) {
2547 _ip6.erase(range.ip6());
2548 }
2549 return *this;
2550}
2551
2552template <typename PAYLOAD>
2553template <typename F, typename U>
2554auto
2555IPSpace<PAYLOAD>::blend(IPRange const &range, U const &color, F &&blender) -> self_type & {
2556 if (range.is(AF_INET)) {
2557 _ip4.blend(range.ip4(), color, blender);
2558 } else if (range.is(AF_INET6)) {
2559 _ip6.blend(range.ip6(), color, blender);
2560 }
2561 return *this;
2562}
2563
2564template <typename PAYLOAD>
2565template <typename F, typename U>
2566auto
2567IPSpace<PAYLOAD>::blend(IP4Range const &range, U const &color, F &&blender) -> self_type & {
2568 _ip4.blend(range, color, std::forward<F>(blender));
2569 return *this;
2570}
2571
2572template <typename PAYLOAD>
2573template <typename F, typename U>
2574auto
2575IPSpace<PAYLOAD>::blend(IP6Range const &range, U const &color, F &&blender) -> self_type & {
2576 _ip6.blend(range, color, std::forward<F>(blender));
2577 return *this;
2578}
2579
2580template <typename PAYLOAD>
2581void
2583 _ip4.clear();
2584 _ip6.clear();
2585}
2586
2587template <typename PAYLOAD>
2588auto
2590 return iterator{_ip4.begin(), _ip6.begin()};
2591}
2592
2593template <typename PAYLOAD>
2594auto
2596 return const_cast<self_type *>(this)->begin();
2597}
2598
2599template <typename PAYLOAD>
2600auto
2602 return iterator{_ip4.end(), _ip6.end()};
2603}
2604
2605template <typename PAYLOAD>
2606auto
2608 return const_cast<self_type *>(this)->end();
2609}
2610
2611template <typename PAYLOAD>
2612auto
2614 return this->begin();
2615}
2616
2617template <typename PAYLOAD>
2618auto
2620 return this->begin();
2621}
2622
2623template <typename PAYLOAD>
2624auto
2626 return {_ip4.end(), _ip6.begin()};
2627}
2628
2629template <typename PAYLOAD>
2630auto
2632 return const_cast<self_type *>(this)->end_ip4();
2633}
2634
2635template <typename PAYLOAD>
2636auto
2638 return {_ip4.end(), _ip6.begin()};
2639}
2640
2641template <typename PAYLOAD>
2642auto
2644 return const_cast<self_type *>(this)->begin_ip6();
2645}
2646
2647template <typename PAYLOAD>
2648auto
2650 return this->end();
2651}
2652
2653template <typename PAYLOAD>
2654auto
2656 return this->end();
2657}
2658
2659template <typename PAYLOAD>
2660auto
2662 if (addr.is_ip4()) {
2663 return this->find(addr.ip4());
2664 } else if (addr.is_ip6()) {
2665 return this->find(addr.ip6());
2666 }
2667 return this->end();
2668}
2669
2670template <typename PAYLOAD>
2671auto
2673 if (addr.is_ip4()) {
2674 return this->find(addr.ip4());
2675 } else if (addr.is_ip6()) {
2676 return this->find(addr.ip6());
2677 }
2678 return this->end();
2679}
2680
2681template <typename PAYLOAD>
2682auto
2684 if (auto spot = _ip4.find(addr); spot != _ip4.end()) {
2685 return {spot, _ip6.begin()};
2686 }
2687 return this->end();
2688}
2689
2690template <typename PAYLOAD>
2691auto
2693 if (auto spot = _ip4.find(addr); spot != _ip4.end()) {
2694 return {spot, _ip6.begin()};
2695 }
2696 return this->end();
2697}
2698
2699template <typename PAYLOAD>
2700auto
2702 return {_ip4.end(), _ip6.find(addr)};
2703}
2704
2705template <typename PAYLOAD>
2706auto
2708 return const_iterator{_ip4.end(), _ip6.find(addr)};
2709}
2710
2711template <typename PAYLOAD>
2712auto
2714 if (AF_INET == family) {
2715 return this->begin_ip4();
2716 } else if (AF_INET6 == family) {
2717 return this->begin_ip6();
2718 }
2719 return this->end();
2720}
2721
2722template <typename PAYLOAD>
2723auto
2725 if (AF_INET == family) {
2726 return this->end_ip4();
2727 } else if (AF_INET6 == family) {
2728 return this->end_ip6();
2729 }
2730 return this->end();
2731}
2732
2733template <typename PAYLOAD>
2734size_t
2736 return _ip4.count();
2737}
2738
2739template <typename PAYLOAD>
2740size_t
2742 return _ip6.count();
2743}
2744
2745template <typename PAYLOAD>
2746size_t
2748 return _ip4.count() + _ip6.count();
2749}
2750
2751template <typename PAYLOAD>
2752size_t
2753IPSpace<PAYLOAD>::count(sa_family_t f) const {
2754 return IP4Addr::AF_value == f ? _ip4.count() : IP6Addr::AF_value == f ? _ip6.count() : 0;
2755}
2756
2757template <typename PAYLOAD>
2758bool
2760 return _ip4.empty() && _ip6.empty();
2761}
2762
2763inline auto
2765 ++_iter;
2766 return *this;
2767}
2768
2769inline auto
2771 --_iter;
2772 return *this;
2773}
2774
2775inline auto
2777 self_type zret{*this};
2778 ++_iter;
2779 return zret;
2780}
2781
2782inline auto
2784 self_type zret{*this};
2785 --_iter;
2786 return zret;
2787}
2788
2789inline auto
2791 return _iter->_rv;
2792}
2793
2794inline auto
2796 return &(_iter->_rv);
2797}
2798
2799inline bool
2800IPRangeSet::const_iterator::operator==(IPRangeSet::const_iterator::self_type const &that) const {
2801 return _iter == that._iter;
2802}
2803
2804inline bool
2805IPRangeSet::const_iterator::operator!=(IPRangeSet::const_iterator::self_type const &that) const {
2806 return _iter != that._iter;
2807}
2808
2809}} // namespace swoc::SWOC_VERSION_NS
2810
2812namespace std {
2813
2814// -- Tuple support for IP4Net --
2815template <> class tuple_size<swoc::IP4Net> : public std::integral_constant<size_t, 2> {};
2816
2817template <size_t IDX> class tuple_element<IDX, swoc::IP4Net> {
2818 static_assert("swoc::IP4Net tuple index out of range");
2819};
2820
2821template <> class tuple_element<0, swoc::IP4Net> {
2822public:
2823 using type = swoc::IP4Addr;
2824};
2825
2826template <> class tuple_element<1, swoc::IP4Net> {
2827public:
2828 using type = swoc::IPMask;
2829};
2830
2831// -- Tuple support for IP6Net --
2832template <> class tuple_size<swoc::IP6Net> : public std::integral_constant<size_t, 2> {};
2833
2834template <size_t IDX> class tuple_element<IDX, swoc::IP6Net> {
2835 static_assert("swoc::IP6Net tuple index out of range");
2836};
2837
2838template <> class tuple_element<0, swoc::IP6Net> {
2839public:
2840 using type = swoc::IP6Addr;
2841};
2842
2843template <> class tuple_element<1, swoc::IP6Net> {
2844public:
2845 using type = swoc::IPMask;
2846};
2847
2848// -- Tuple support for IPNet --
2849template <> class tuple_size<swoc::IPNet> : public std::integral_constant<size_t, 2> {};
2850
2851template <size_t IDX> class tuple_element<IDX, swoc::IPNet> {
2852 static_assert("swoc::IPNet tuple index out of range");
2853};
2854
2855template <> class tuple_element<0, swoc::IPNet> {
2856public:
2857 using type = swoc::IPAddr;
2858};
2859
2860template <> class tuple_element<1, swoc::IPNet> {
2861public:
2862 using type = swoc::IPMask;
2863};
2864
2865} // namespace std
2866
2867namespace swoc { inline namespace SWOC_VERSION_NS {
2868
2869template <size_t IDX>
2870typename std::tuple_element<IDX, IP4Net>::type
2871get(swoc::IP4Net const &net) {
2872 if constexpr (IDX == 0) {
2873 return net.min();
2874 } else if constexpr (IDX == 1) {
2875 return net.mask();
2876 }
2877}
2878
2879template <size_t IDX>
2880typename std::tuple_element<IDX, IP6Net>::type
2881get(swoc::IP6Net const &net) {
2882 if constexpr (IDX == 0) {
2883 return net.min();
2884 } else if constexpr (IDX == 1) {
2885 return net.mask();
2886 }
2887}
2888
2889template <size_t IDX>
2890typename std::tuple_element<IDX, IPNet>::type
2891get(swoc::IPNet const &net) {
2892 if constexpr (IDX == 0) {
2893 return net.min();
2894 } else if constexpr (IDX == 1) {
2895 return net.mask();
2896 }
2897}
2899
2900}} // namespace swoc::SWOC_VERSION_NS
2901
2902// Tuple support for IPSpace values.
2904
2905namespace std {
2906
2907template <typename P> class tuple_size<swoc::detail::ip_space_value_type<P>> : public integral_constant<size_t, 2> {};
2908template <typename P> class tuple_size<swoc::detail::ip_space_const_value_type<P>> : public integral_constant<size_t, 2> {};
2909
2910template <size_t IDX, typename P> class tuple_element<IDX, swoc::detail::ip_space_value_type<P>> {
2911 static_assert("swoc::IPSpace::value_type tuple index out of range");
2912};
2913template <size_t IDX, typename P> class tuple_element<IDX, swoc::detail::ip_space_const_value_type<P>> {
2914 static_assert("swoc::IPSpace::value_type tuple index out of range");
2915};
2916
2917template <typename P> class tuple_element<0, swoc::detail::ip_space_value_type<P>> {
2918public:
2919 using type = swoc::IPRangeView const &;
2920};
2921
2922template <typename P> class tuple_element<1, swoc::detail::ip_space_value_type<P>> {
2923public:
2924 using type = P &;
2925};
2926
2927template <typename P> class tuple_element<0, swoc::detail::ip_space_const_value_type<P>> {
2928public:
2929 using type = swoc::IPRangeView const &;
2930};
2931
2932template <typename P> class tuple_element<1, swoc::detail::ip_space_const_value_type<P>> {
2933public:
2934 using type = P const &;
2935};
2936
2937} // namespace std
2938
2939namespace swoc { inline namespace SWOC_VERSION_NS { namespace detail {
2940template <size_t IDX, typename P>
2941auto
2942get(ip_space_const_value_type<P> const &p) -> typename std::tuple_element<IDX, ip_space_const_value_type<P>>::type {
2943 if constexpr (IDX == 0) {
2944 return p._rv;
2945 } else if constexpr (IDX == 1) {
2946 return *(p._payload);
2947 }
2948}
2949
2950template <size_t IDX, typename P>
2951auto
2952get(ip_space_value_type<P> const &p) -> typename std::tuple_element<IDX, ip_space_value_type<P>>::type {
2953 if constexpr (IDX == 0) {
2954 return p._rv;
2955 } else if constexpr (IDX == 1) {
2956 return *(p._payload);
2957 }
2958}
2959}}} // namespace swoc::SWOC_VERSION_NS::detail
2960
2961// Support unqualified @c get because ADL doesn't seem to work.
2962using swoc::detail::get;
2963// Support @c std::get
2964namespace std {
2965using swoc::detail::get;
2966}
2967
bool operator==(RBNode *n, RBNode::Color c)
Definition RBTree.cc:19
T _max
the maximum value in the interval
T _min
The minimum value in the interval.
static constexpr size_t WIDTH
Definition IPAddr.h:33
in_addr_t _addr
Address in host order.
Definition IPAddr.h:192
static constexpr sa_family_t AF_value
Address family type.
Definition IPAddr.h:37
An IPv4 network.
Definition IPRange.h:718
bool empty() const
Definition IPRange.h:2128
IP4Addr max() const
Definition IPRange.h:2138
self_type & clear()
Reset network to invalid state.
Definition IPRange.h:769
self_type & assign(IP4Addr const &addr, IPMask const &mask)
Definition IPRange.h:2158
bool load(swoc::TextView text)
Definition swoc_ip.cc:851
IPMask _mask
Network mask.
Definition IPRange.h:782
IP4Range as_range() const
Definition IPRange.h:2143
IP4Net(self_type const &that)=default
Copy constructor.
IP4Net()=default
Construct invalid network.
IPMask const & mask() const
Definition IPRange.h:2123
IP4Addr _addr
Network address (also lower_node).
Definition IPRange.h:781
bool operator==(self_type const &that) const
Equality.
Definition IPRange.h:2148
bool operator!=(self_type const &that) const
Inequality.
Definition IPRange.h:2153
IP4Addr min() const
Definition IPRange.h:2133
IP4Addr _mask
Mask for current network.
Definition IPRange.h:168
NetSource(self_type const &that)=default
Copy constructor.
IP4Net operator*() const
Definition IPRange.h:2305
self_type iterator
This class acts as a container and an iterator.
Definition IPRange.h:129
IPMask::raw_type _cidr
Current CIDR value.
Definition IPRange.h:169
IPMask mask() const
Definition IPRange.h:2325
bool empty() const
Return true if there are valid networks, false if not.
Definition IPRange.h:2320
self_type & operator++()
Move to next network.
Definition swoc_ip.cc:998
IP4Range range_type
Import base range type.
Definition IPRange.h:120
IP4Addr const & addr() const
Definition IPRange.h:2335
iterator const_iterator
All iteration is constant so no distinction between iterators.
Definition IPRange.h:131
bool operator!=(self_type const &that) const
Inequality.
Definition IPRange.h:2345
NetSource(range_type const &range)
Construct from range.
Definition swoc_ip.cc:991
static iterator end()
Past last network.
Definition IPRange.h:2315
bool operator==(self_type const &that) const
Equality.
Definition IPRange.h:2340
iterator begin() const
First network.
Definition IPRange.h:2310
self_type * operator->()
Access this as if it were an IP4Net.
Definition IPRange.h:2330
bool load(string_view text)
< Import assign methods.
Definition swoc_ip.cc:954
NetSource networks() const
Definition IPRange.h:1897
constexpr IP4Range()=default
Default constructor, invalid range.
IP4Range(super_type const &r)
Definition IPRange.h:40
sa_family_t family() const
Definition IPRange.h:87
static constexpr size_t WIDTH
Number of bits in the address.
Definition IPAddr.h:207
static constexpr sa_family_t AF_value
Address family type.
Definition IPAddr.h:209
IPv6 network.
Definition IPRange.h:786
IP6Addr min() const
Definition IPRange.h:2177
IP6Net(TextView text)
Definition IPRange.h:810
IPMask _mask
Network mask.
Definition IPRange.h:857
bool empty() const
Definition IPRange.h:2172
self_type & assign(IP6Addr const &addr, IPMask const &mask)
Definition IPRange.h:2202
IPMask const & mask() const
Definition IPRange.h:2167
IP6Net()=default
Construct invalid network.
self_type & clear()
Reset network to invalid state.
Definition IPRange.h:844
IP6Addr max() const
Definition IPRange.h:2182
bool operator==(self_type const &that) const
Equality.
Definition IPRange.h:2192
IP6Range as_range() const
Definition IPRange.h:2187
IP6Net(self_type const &that)=default
Copy constructor.
bool operator!=(self_type const &that) const
Inequality.
Definition IPRange.h:2197
IP6Addr _addr
Network address (also lower_node).
Definition IPRange.h:856
bool load(swoc::TextView text)
Definition swoc_ip.cc:874
IP6Addr const & addr() const
Definition IPRange.h:2390
bool operator!=(self_type const &that) const
Inequality.
Definition IPRange.h:2385
self_type operator++(int)
Move to next network.
IP6Net operator*() const
Definition IPRange.h:2365
iterator begin() const
First network.
Definition IPRange.h:2350
IPMask _mask
Current CIDR value.
Definition IPRange.h:310
IPMask mask() const
Definition IPRange.h:2395
IP6Range _range
Remaining range.
Definition IPRange.h:309
self_type iterator
This class acts as a container and an iterator.
Definition IPRange.h:273
NetSource(range_type const &range)
Construct from range.
Definition swoc_ip.cc:1200
iterator const_iterator
All iteration is constant so no distinction between iterators.
Definition IPRange.h:275
NetSource(self_type const &that)=default
Copy constructor.
iterator end() const
Past last network.
Definition IPRange.h:2355
self_type & operator++()
Move to next network.
Definition swoc_ip.cc:1207
bool operator==(self_type const &that) const
Equality.
Definition IPRange.h:2380
self_type * operator->()
Access this as if it were an IP6Net.
Definition IPRange.h:2370
IP6Range range_type
Import base range type.
Definition IPRange.h:264
Inclusive range of IPv6 addresses.
Definition IPRange.h:179
sa_family_t family() const
Definition IPRange.h:231
bool load(string_view text)
< Import assign methods.
Definition swoc_ip.cc:1075
IP6Range(super_type const &r)
Definition IPRange.h:186
NetSource networks() const
Definition IPRange.h:1906
IP6Addr const & ip6() const
Definition IPAddr.h:1377
IP4Addr const & ip4() const
Definition IPAddr.h:1369
sa_family_t family() const
Definition IPAddr.h:1264
uint8_t raw_type
Storage for mask width.
Definition IPAddr.h:673
IPNet(self_type const &that)=default
Copy constructor.
IPMask::raw_type width() const
Definition IPRange.h:2230
IP6Net ip6() const
Definition IPRange.h:2287
IPRange as_range() const
Definition IPRange.h:2240
IP4Net ip4() const
Definition IPRange.h:2282
bool operator==(self_type const &that) const
Equality.
Definition IPRange.h:2252
self_type & assign(IPAddr const &addr, IPMask const &mask)
Definition IPRange.h:2245
IPAddr _addr
Address and family.
Definition IPRange.h:956
IPNet()=default
Construct invalid network.
bool empty() const
Definition IPRange.h:2215
bool load(swoc::TextView text)
Definition swoc_ip.cc:897
bool is_ip6() const
Definition IPRange.h:922
IPMask const & mask() const
Definition IPRange.h:2235
IPAddr max() const
Definition IPRange.h:2225
self_type & clear()
Reset network to invalid state.
Definition IPRange.h:2292
IPAddr min() const
Definition IPRange.h:2220
bool is_ip4() const
Definition IPRange.h:916
IPMask _mask
Network mask.
Definition IPRange.h:957
bool operator!=(self_type const &that) const
Inequality.
Definition IPRange.h:2257
sa_family_t family() const
Address family of network.
Definition IPRange.h:928
Bidirectional constant iterator for iteration over ranges.
Definition IPRange.h:1593
const_iterator()=default
Default constructor.
super_type _iter
Underlying iterator.
Definition IPRange.h:1652
bool operator!=(self_type const &that) const
Inequality.
Definition IPRange.h:2805
self_type & operator=(self_type const &that)=default
Assignment.
reference operator*() const
Definition IPRange.h:2790
const_iterator(self_type const &that)=default
Copy constructor.
IPRange _r
Some less temporary storage for dereferences.
Definition IPRange.h:1653
bool operator==(self_type const &that) const
Equality.
Definition IPRange.h:2800
IPRangeSet()=default
Default construct empty set.
self_type & fill(swoc::IPRange const &r)
Definition IPRange.h:1681
size_t count() const
Definition IPRange.h:1692
void clear()
Remove all addresses in the set.
Definition IPRange.h:1702
self_type & mark(swoc::IPRange const &r)
Definition IPRange.h:1675
const_iterator begin() const
Definition IPRange.h:1660
Space _addrs
The address set.
Definition IPRange.h:1671
const_iterator end() const
Definition IPRange.h:1665
bool contains(swoc::IPAddr const &addr) const
Definition IPRange.h:1687
bool operator==(IPRange const &r) const
Compare to a range.
Definition swoc_ip.cc:1244
IPRange::NetSource networks() const
Definition IPRange.h:706
bool is_ip4() const
Definition IPRange.h:2022
bool contains(IPAddr const &addr) const
Definition IPRange.h:2100
IP6Range const & ip6() const
Definition IPRange.h:2062
IPAddr min() const
Definition IPRange.h:2091
storage_type _raw
Storage for the view pointer.
Definition IPRange.h:713
bool is_ip6() const
Definition IPRange.h:2027
IPAddr max() const
Definition IPRange.h:2096
bool is(sa_family_t family) const
Definition IPRange.h:2032
IP4Range const & ip4() const
Definition IPRange.h:2057
bool operator!=(self_type const &that) const
Inequality.
Definition IPRange.h:2086
self_type & assign(IP4Range const &r)
Update the view.
Definition IPRange.h:2072
sa_family_t _family
Range address family.
Definition IPRange.h:714
bool valid() const
Definition IPRange.h:2067
IPRangeView()=default
Default constructor - invalid view.
self_type & clear()
Reset to invalid view.
Definition IPRange.h:2005
iterator end() const
Past last network.
Definition IPRange.h:2425
self_type * operator->()
Access this as if it were an IP6Net.
Definition IPRange.h:2465
IPAddr addr() const
Definition IPRange.h:2430
bool operator==(self_type const &that) const
Equality.
Definition IPRange.h:2470
std::monostate _nil
Default value, no addresses.
Definition IPRange.h:581
IPNet operator*() const
Definition IPRange.h:2450
NetSource(self_type const &that)=default
Copy constructor.
self_type iterator
This class acts as a container and an iterator.
Definition IPRange.h:546
sa_family_t _family
Mark for union content.
Definition IPRange.h:586
iterator begin() const
First network.
Definition IPRange.h:2420
bool operator!=(self_type const &that) const
Inequality.
Definition IPRange.h:2485
IP4Range::NetSource _ip4
IPv4 addresses.
Definition IPRange.h:582
self_type & operator++()
Move to next network.
Definition IPRange.h:2455
IPRange range_type
Import base range type.
Definition IPRange.h:534
IPMask mask() const
Definition IPRange.h:2440
iterator const_iterator
All iteration is constant so no distinction between iterators.
Definition IPRange.h:548
self_type operator++(int)
Move to next network.
IP6Range::NetSource _ip6
IPv6 addresses.
Definition IPRange.h:583
NetSource(range_type const &range)
Construct from range.
Definition IPRange.h:2399
std::monostate _nil
Make constructor easier to implement.
Definition IPRange.h:517
IPRange(IP6Addr const &addr)
Definition IPRange.h:369
bool is_ip6() const
Definition IPRange.h:1989
bool operator!=(self_type const &that) const
Inequality.
Definition IPRange.h:1979
bool load(std::string_view const &text)
Definition swoc_ip.cc:1111
IP4Range const & ip4() const
Definition IPRange.h:1996
IPRange(IP4Addr addr)
Definition IPRange.h:363
sa_family_t family() const
Definition IPRange.h:1993
NetSource networks() const
Definition IPRange.h:1969
IPRange(IPAddr const &addr)
Definition IPRange.h:357
bool is(sa_family_t family) const
Definition IPRange.h:1974
bool is_ip4() const
Definition IPRange.h:1984
IP6Range _ip6
IPv6 range.
Definition IPRange.h:519
bool contains(IPAddr const &addr) const
Definition IPRange.h:2036
IP4Range _ip4
IPv4 range.
Definition IPRange.h:518
self_type & operator=(IPRangeView const &rv)
Assign from view.
Definition IPRange.h:1953
self_type & assign(IP4Addr const &min, IP4Addr const &max)
Definition IPRange.h:1939
sa_family_t _family
Family of _range.
Definition IPRange.h:523
self_type & clear()
Make the range empty / invalid.
Definition IPRange.h:1963
IP6Range const & ip6() const
Definition IPRange.h:2000
IPRange()=default
Default constructor - construct invalid range.
IPAddr max() const
Definition swoc_ip.cc:1139
IPAddr min() const
Definition swoc_ip.cc:1126
std::bidirectional_iterator_tag iterator_category
Import for API compliance.
Definition IPRange.h:1253
IP4Range const & r4()
Definition IPRange.h:1326
const_iterator(self_type const &that)=default
Copy constructor.
IP6Range const & r6()
Definition IPRange.h:1331
bool operator==(self_type const &that) const
Definition IPRange.h:1815
IP6Space::iterator _iter_6
Definition IPRange.h:1308
const_iterator()=default
Default constructor.
self_type & operator=(self_type const &that)
Definition IPRange.h:1730
bool operator!=(self_type const &that) const
Definition IPRange.h:1821
IP4Space::iterator _iter_4
IPv4 sub-space iterator.
Definition IPRange.h:1307
value_type _value
Current value.
Definition IPRange.h:1310
iterator()=default
Default constructor.
detail::ip_space_value_type< PAYLOAD > value_type
Value type of iteration.
Definition IPRange.h:1356
iterator(self_type const &that)=default
Copy constructor.
reference operator*() const
Definition IPRange.h:1846
iterator(const_iterator const &that)
Definition IPRange.h:1352
self_type & operator=(self_type const &that)
Definition IPRange.h:1827
iterator find(IP6Addr const &addr)
Definition IPRange.h:2701
const_iterator end(sa_family_t family) const
Definition IPRange.h:2724
const_iterator end_ip4() const
Definition IPRange.h:2631
const_iterator begin_ip4() const
Definition IPRange.h:2619
self_type & mark(IPRange const &range, PAYLOAD const &payload)
Definition IPRange.h:2521
const_iterator begin_ip6() const
Definition IPRange.h:2643
const_iterator find(IP6Addr const &addr) const
Definition IPRange.h:2707
size_t count_ip4() const
Definition IPRange.h:2735
iterator find(IPAddr const &addr)
Definition IPRange.h:2661
self_type & fill(IPRange const &range, PAYLOAD const &payload)
Definition IPRange.h:2532
PAYLOAD payload_t
Definition IPRange.h:1123
iterator begin_ip6()
Definition IPRange.h:2637
iterator end_ip6()
Definition IPRange.h:2649
size_t count_ip6() const
Definition IPRange.h:2741
iterator begin()
Definition IPRange.h:2589
iterator begin_ip4()
Definition IPRange.h:2613
const_iterator find(IP4Addr const &addr) const
Definition IPRange.h:2692
std::pair< iterator, iterator > intersection(IP6Range const &r)
Definition IPRange.h:1498
self_type & mark_bulk(std::vector< std::pair< DiscreteRange< IP6Addr >, PAYLOAD > > &range_payloads, bool is_sorted=false)
vector-based interface for the previous function.
Definition IPRange.h:2514
void clear()
Remove all ranges.
Definition IPRange.h:2582
bool empty() const
Definition IPRange.h:2759
iterator find(IP4Addr const &addr)
Definition IPRange.h:2683
const_iterator begin(sa_family_t family) const
Definition IPRange.h:2713
detail::ip_space_value_type< PAYLOAD > value_type
Iterator value, a range and payload.
Definition IPRange.h:1125
const_iterator begin() const
Definition IPRange.h:2595
self_type & blend(IPRange const &range, U const &color, F &&blender)
std::pair< iterator, iterator > intersection(IPRange const &r)
Definition IPRange.h:1509
const_iterator end() const
Definition IPRange.h:2607
self_type & mark_bulk(std::pair< DiscreteRange< IP6Addr >, PAYLOAD > *range_payloads, size_t size, bool is_sorted=false)
Definition IPRange.h:2500
std::pair< iterator, iterator > intersection(IP4Range const &r)
Definition IPRange.h:1487
iterator end()
Definition IPRange.h:2601
IPSpace()=default
Construct an empty space.
const_iterator end_ip6() const
Definition IPRange.h:2655
size_t count(sa_family_t f) const
Definition IPRange.h:2753
self_type & mark_bulk(std::vector< std::pair< DiscreteRange< IP4Addr >, PAYLOAD > > &range_payloads, bool is_sorted=false)
vector-based interface for the previous function.
Definition IPRange.h:2507
const_iterator find(IPAddr const &addr) const
Definition IPRange.h:2672
self_type & mark_bulk(std::pair< DiscreteRange< IP4Addr >, PAYLOAD > *range_payloads, size_t size, bool is_sorted=false)
Definition IPRange.h:2493
iterator end_ip4()
Definition IPRange.h:2625
self_type & erase(IPRange const &range)
Definition IPRange.h:2543
size_t count() const
Definition IPRange.h:2747
STL namespace.
For template deduction guides.
Definition ArenaWriter.cc:9
bool operator==(IPAddr const &lhs, sockaddr const *sa)
Equality.
Definition swoc_ip.cc:650
bool operator!=(IP4Addr const &lhs, IP4Addr const &rhs)
Definition IPAddr.h:845
std::tuple< IPRangeView, PAYLOAD & > tuple() const
Support assignemnt to std::tie.
Definition IPRange.h:1015
bool operator==(std::tuple< swoc::IPRange, PAYLOAD > const &t) const
Equality against an equivalent tuple.
Definition IPRange.h:1098
PAYLOAD const & payload() const
Definition IPRange.h:1036
IPRangeView _rv
View to the current range.
Definition IPRange.h:982
self_type & clear()
Reset to default constructed state.
Definition IPRange.h:1066
self_type & assign(IP4Range const &r, PAYLOAD &payload)
Definition IPRange.h:1074
PAYLOAD * _payload
Payload for _range.
Definition IPRange.h:983