LibSWOC++ 1.5.15
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 };
613
614public:
616 IPRangeView() = default;
617
619 bool operator==(IPRange const &r) const;
620
622 bool valid() const;
623
624 // @return @c true if the range is empty (invalid views are empty)
625 bool empty() const;
626
628 self_type &clear();
629
631 self_type &assign(IP4Range const &r);
632
634 self_type &assign(IP6Range const &r);
635
637 bool is_ip4() const;
638
640 bool is_ip6() const;
641
647 bool is(sa_family_t family) const;
648
654 bool contains(IPAddr const& addr) const;
655
661 bool contains(IP6Addr const& addr) const;
662
668 bool contains(IP4Addr const& addr) const;
669
671 IP4Range const &ip4() const;
672
674 IP6Range const &ip6() const;
675
678
680 IPAddr min() const;
681
683 IPAddr max() const;
684
686 bool operator==(self_type const &that) const;
687
689 bool operator!=(self_type const &that) const;
690
698 networks() const {
699 return IPRange::NetSource(*this);
700 }
701
703
704protected:
705 storage_type _raw = {std::monostate()};
706 sa_family_t _family = AF_UNSPEC;
707};
708
710class IP4Net {
711 using self_type = IP4Net;
712public:
713 IP4Net() = default;
714 IP4Net(self_type const &that) = default;
715
725 IP4Net(IP4Addr addr, IPMask mask);
726
727 IP4Net(swoc::TextView text) { this->load(text); }
728
734 bool load(swoc::TextView text);
735
737 bool empty() const;
738
740 IP4Addr min() const;
741
743 IP4Addr max() const;
744
746 IPMask const &mask() const;
747
749 IP4Range as_range() const;
750
757 self_type &assign(IP4Addr const &addr, IPMask const &mask);
758
760 self_type &
762 _mask.clear();
763 return *this;
764 }
765
767 bool operator==(self_type const &that) const;
768
770 bool operator!=(self_type const &that) const;
771
772protected:
775};
776
778class IP6Net {
779 using self_type = IP6Net;
780public:
781 IP6Net() = default;
782 IP6Net(self_type const &that) = default;
783
793 IP6Net(IP6Addr addr, IPMask mask);
794
802 IP6Net(TextView text) { this->load(text); }
803
809 bool load(swoc::TextView text);
810
812 bool empty() const;
813
815 IP6Addr min() const;
816
818 IP6Addr max() const;
819
821 IPMask const &mask() const;
822
824 IP6Range as_range() const;
825
832 self_type &assign(IP6Addr const &addr, IPMask const &mask);
833
835 self_type &
837 _mask.clear();
838 return *this;
839 }
840
842 bool operator==(self_type const &that) const;
843
845 bool operator!=(self_type const &that) const;
846
847protected:
850};
851
855class IPNet {
856 using self_type = IPNet;
857public:
858 IPNet() = default;
859 IPNet(self_type const &that) = default;
860
870 IPNet(IPAddr const &addr, IPMask const &mask);
871
879 IPNet(TextView text);
880
886 bool load(swoc::TextView text);
887
889 bool empty() const;
890
892 IPAddr min() const;
893
895 IPAddr max() const;
896
898 IPMask::raw_type width() const;
899
901 IPMask const &mask() const;
902
904 IPRange as_range() const;
905
907 bool
908 is_ip4() const {
909 return _addr.is_ip4();
910 }
911
913 bool
914 is_ip6() const {
915 return _addr.is_ip6();
916 }
917
919 sa_family_t
920 family() const {
921 return _addr.family();
922 }
923
925 IP4Net ip4() const;
926
928 IP6Net ip6() const;
929
936 self_type &assign(IPAddr const &addr, IPMask const &mask);
937
939 self_type &clear();
940
942 bool operator==(self_type const &that) const;
943
945 bool operator!=(self_type const &that) const;
946
947protected:
950};
951
952// --------------------------------------------------------------------------
953namespace detail {
971template <typename PAYLOAD> struct ip_space_const_value_type {
972 using self_type = ip_space_const_value_type;
973
975 PAYLOAD *_payload = nullptr;
976
977 ip_space_const_value_type() = default;
978
980 self_type &clear();
981
988 self_type &assign(IP4Range const &r, PAYLOAD &payload);
989
996 self_type &assign(IP6Range const &r, PAYLOAD &payload);
997
1003 self_type &assign(self_type const &that);
1004
1006 std::tuple<IPRangeView, PAYLOAD &>
1007 tuple() const {
1008 return {_rv, *_payload};
1009 }
1010
1012 bool operator==(std::tuple<swoc::IPRange, PAYLOAD> const &t) const;
1013
1015 IPRange
1016 range() const {
1017 return _rv;
1018 }
1019
1022 range_view() const {
1023 return _rv;
1024 }
1025
1027 PAYLOAD const &
1028 payload() const {
1029 return *_payload;
1030 }
1031};
1032
1045template <typename PAYLOAD> struct ip_space_value_type : ip_space_const_value_type<PAYLOAD> {
1046 using self_type = ip_space_value_type;
1047 using super_type = ip_space_const_value_type<PAYLOAD>;
1048
1050 PAYLOAD &
1052 return *super_type::_payload;
1053 }
1054};
1055
1056template <typename PAYLOAD>
1057auto
1059 _rv.clear();
1060 _payload = nullptr;
1061 return *this;
1062}
1063
1064template <typename PAYLOAD>
1065auto
1067 _rv.assign(r);
1068 _payload = &payload;
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
1082ip_space_const_value_type<PAYLOAD>::assign(ip_space_const_value_type::self_type const &that) -> self_type & {
1083 _rv = that._rv;
1084 _payload = that._payload;
1085 return *this;
1086}
1087
1088template <typename PAYLOAD>
1089bool
1090ip_space_const_value_type<PAYLOAD>::operator==(std::tuple<swoc::IPRange, PAYLOAD> const &t) const {
1091 return _rv == std::get<0>(t) && std::get<1>(t) == *_payload;
1092}
1093
1094} // namespace detail
1095
1109template <typename PAYLOAD> class IPSpace {
1110 using self_type = IPSpace;
1111 using IP4Space = DiscreteSpace<IP4Addr, PAYLOAD>;
1112 using IP6Space = DiscreteSpace<IP6Addr, PAYLOAD>;
1113
1114public:
1115 using payload_t = PAYLOAD;
1118
1120 IPSpace() = default;
1121
1130 self_type &mark(IPRange const &range, PAYLOAD const &payload);
1131
1139 self_type &mark_bulk(std::pair<DiscreteRange<IP4Addr>, PAYLOAD>* range_payloads, size_t size, bool is_sorted = false);
1140
1142 self_type &mark_bulk(std::vector<std::pair<DiscreteRange<IP4Addr>, PAYLOAD>>& range_payloads, bool is_sorted = false);
1143
1151 self_type &mark_bulk(std::pair<DiscreteRange<IP6Addr>, PAYLOAD>* range_payloads, size_t size, bool is_sorted = false);
1152
1154 self_type &mark_bulk(std::vector<std::pair<DiscreteRange<IP6Addr>, PAYLOAD>>& range_payloads, bool is_sorted = false);
1155
1164 self_type &fill(IPRange const &range, PAYLOAD const &payload);
1165
1171 self_type &erase(IPRange const &range);
1172
1192 template <typename F, typename U = PAYLOAD> self_type &blend(IPRange const &range, U const &color, F &&blender);
1193
1194 template <typename F, typename U = PAYLOAD> self_type &blend(IP4Range const &range, U const &color, F &&blender);
1195
1196 template <typename F, typename U = PAYLOAD> self_type &blend(IP6Range const &range, U const &color, F &&blender);
1197
1199 size_t count() const;
1200
1202 size_t count_ip4() const;
1203
1205 size_t count_ip6() const;
1206
1212 size_t count(sa_family_t f) const;
1213
1215 bool empty() const;
1216
1218 void clear();
1219
1239 using self_type = const_iterator;
1240 friend class IPSpace;
1241
1242 public:
1244 // STL algorithm compliance.
1245 using iterator_category = std::bidirectional_iterator_tag;
1246 using pointer = value_type const *;
1247 using reference = value_type const &;
1248 using difference_type = int;
1249
1251 const_iterator() = default;
1252
1254 const_iterator(self_type const &that) = default;
1255
1257 self_type &operator=(self_type const &that);
1258
1262 self_type &operator++();
1263
1267 self_type &operator--();
1268
1272 self_type operator++(int);
1273
1277 self_type operator--(int);
1278
1281 reference operator*() const;
1282
1285 pointer operator->() const;
1286
1288 bool operator==(self_type const &that) const;
1289
1291 bool operator!=(self_type const &that) const;
1292
1293 protected:
1294 // These are stored non-const to make implementing @c iterator easier. The containing class provides the
1295 // required @c const protection. Internally a tuple of iterators is stored for forward iteration. If
1296 // the primary (ipv4) iterator is at the end, then use the secondary (ipv6) iterator. The reverse
1297 // is done for reverse iteration. This depends on the extra support @c IntrusiveDList iterators
1298 // provide.
1299 typename IP4Space::iterator _iter_4;
1300 typename IP6Space::iterator _iter_6;
1302 value_type _value;
1303
1311 const_iterator(typename IP4Space::const_iterator const &iter4, typename IP6Space::const_iterator const &iter6);
1312
1313 // These are required because the actual range type for the subspaces is @c DiscreteRange<T>
1314 // and returning that type without a cast creates a temporary which causes some nasty side effects.
1315
1317 IP4Range const &
1318 r4() {
1319 return static_cast<IP4Range const &>(_iter_4->range());
1320 }
1321
1322 IP6Range const &
1323 r6() {
1324 return static_cast<IP6Range const &>(_iter_6->range());
1325 }
1326 };
1327
1334 class iterator : public const_iterator {
1335 using self_type = iterator;
1336 using super_type = const_iterator;
1337
1338 friend class IPSpace;
1339
1340 protected:
1341 using super_type::super_type;
1345
1346 public:
1349 using pointer = value_type *;
1350 using reference = value_type &;
1351
1353 iterator() = default;
1354
1356 iterator(self_type const &that) = default;
1357
1359 self_type &operator=(self_type const &that);
1360
1364 self_type &operator++();
1365
1369 self_type &operator--();
1370
1374 self_type operator++(int);
1375
1379 self_type operator--(int);
1380
1383 reference operator*() const;
1384
1387 pointer operator->() const;
1388
1389 protected:
1390 // Retrieve the value and convert from the super (const) type value to the value for iterator.
1391 value_type &value() const;
1392 };
1393
1399 iterator find(IPAddr const &addr);
1400
1406 const_iterator find(IPAddr const &addr) const;
1407
1413 iterator find(IP4Addr const &addr);
1414
1420 const_iterator find(IP4Addr const &addr) const;
1421
1427 iterator find(IP6Addr const &addr);
1428
1434 const_iterator find(IP6Addr const &addr) const;
1435
1437 iterator begin();
1438
1440 const_iterator begin() const;
1441
1443 iterator end();
1444
1446 const_iterator end() const;
1447
1449 iterator begin_ip4();
1451 const_iterator begin_ip4() const;
1452
1454 iterator end_ip4();
1456 const_iterator end_ip4() const;
1457
1459 iterator begin_ip6();
1461 const_iterator begin_ip6() const;
1463 iterator end_ip6();
1465 const_iterator end_ip6() const;
1466
1468 const_iterator begin(sa_family_t family) const;
1469
1471 const_iterator end(sa_family_t family) const;
1472
1478 std::pair<iterator, iterator>
1480 auto &&[begin, end] = _ip4.intersection(r);
1481 return {this->iterator_at(begin), this->iterator_at(end)};
1482 }
1483
1489 std::pair<iterator, iterator>
1491 auto &&[begin, end] = _ip6.intersection(r);
1492 return {this->iterator_at(begin), this->iterator_at(end)};
1493 }
1494
1500 std::pair<iterator, iterator>
1502 if (r.is_ip4()) {
1503 return this->intersection(r.ip4());
1504 } else if (r.is_ip6()) {
1505 return this->intersection(r.ip6());
1506 }
1507 return {this->end(), this->end()};
1508 }
1509
1510protected:
1511 IP4Space _ip4;
1512 IP6Space _ip6;
1513
1514 iterator
1515 iterator_at(typename IP4Space::const_iterator const &spot) {
1516 return iterator(spot, _ip6.begin());
1517 }
1518 iterator
1519 iterator_at(typename IP6Space::const_iterator const &spot) {
1520 return iterator(_ip4.end(), spot);
1521 }
1522
1523 friend class IPRangeSet;
1524};
1525
1535 using self_type = IPRangeSet;
1536
1540 static inline constexpr struct Mark {
1541 using self_type = Mark;
1544 bool operator==(self_type const &that);
1545 bool operator!=(self_type const &that);
1546 } MARK{};
1547
1549 using Space = swoc::IPSpace<Mark>;
1550
1551public:
1553 IPRangeSet() = default;
1554
1562 self_type &mark(swoc::IPRange const &r);
1563
1571 self_type &fill(swoc::IPRange const &r);
1572
1578 self_type &erase(swoc::IPRange const &r);
1579
1581 bool contains(swoc::IPAddr const &addr) const;
1582
1584 size_t count() const;
1585
1586 bool empty() const;
1587
1589 void clear();
1590
1593 using self_type = const_iterator;
1594 using super_type = Space::const_iterator;
1595 friend class IPRangeSet;
1596
1597 public:
1598 using value_type = IPRangeView;
1599 // STL algorithm compliance.
1600 using iterator_category = std::bidirectional_iterator_tag;
1601 using pointer = value_type const *;
1602 using reference = value_type const &;
1603 using difference_type = int;
1604
1606 const_iterator() = default;
1607
1609 const_iterator(self_type const &that) = default;
1610
1612 self_type &operator=(self_type const &that) = default;
1613
1617 self_type &operator++();
1618
1622 self_type &operator--();
1623
1627 self_type operator++(int);
1628
1632 self_type operator--(int);
1633
1636 reference operator*() const;
1637
1640 pointer operator->() const;
1641
1643 bool operator==(self_type const &that) const;
1644
1646 bool operator!=(self_type const &that) const;
1647
1648 protected:
1649 const_iterator(super_type const &spot) : _iter(spot) {}
1650
1651 super_type _iter;
1653 };
1654
1655 using iterator = const_iterator;
1656
1659 begin() const {
1660 return _addrs.begin();
1661 }
1662
1663 const_iterator
1664 end() const {
1665 return _addrs.end();
1666 }
1667
1668protected:
1670 Space _addrs;
1671};
1672
1673inline auto
1674IPRangeSet::mark(swoc::IPRange const &r) -> self_type & {
1675 _addrs.mark(r, MARK);
1676 return *this;
1677}
1678
1679inline auto
1680IPRangeSet::fill(swoc::IPRange const &r) -> self_type & {
1681 _addrs.mark(r, MARK);
1682 return *this;
1683}
1684
1685inline auto
1686IPRangeSet::erase(swoc::IPRange const &r) -> self_type & {
1687 _addrs.erase(r);
1688 return *this;
1689}
1690
1691inline bool
1693 return _addrs.find(addr) != _addrs.end();
1694}
1695
1696inline size_t
1698 return _addrs.count();
1699}
1700
1701inline bool
1702IPRangeSet::empty() const {
1703 return _addrs.empty();
1704}
1705
1706inline void
1708 _addrs.clear();
1709}
1710
1711inline bool
1712IPRangeSet::Mark::operator==(IPRangeSet::Mark::self_type const &) {
1713 return true;
1714}
1715
1716inline bool
1717IPRangeSet::Mark::operator!=(IPRangeSet::Mark::self_type const &) {
1718 return false;
1719}
1720
1721template <typename PAYLOAD>
1722IPSpace<PAYLOAD>::const_iterator::const_iterator(typename IP4Space::const_iterator const &iter4,
1723 typename IP6Space::const_iterator const &iter6)
1724 : _iter_4(static_cast<typename IP4Space::iterator const &>(iter4)),
1725 _iter_6(static_cast<typename IP6Space::iterator const &>(iter6)) {
1726 if (_iter_4.has_next()) {
1727 _value.assign(this->r4(), _iter_4->payload());
1728 } else if (_iter_6.has_next()) {
1729 _value.assign(this->r6(), _iter_6->payload());
1730 }
1731}
1732
1733template <typename PAYLOAD>
1734auto
1735IPSpace<PAYLOAD>::const_iterator::operator=(self_type const &that) -> self_type & {
1736 _iter_4 = that._iter_4;
1737 _iter_6 = that._iter_6;
1738 _value.assign(that._value);
1739 return *this;
1740}
1741
1742template <typename PAYLOAD>
1743auto
1745 bool incr_p = false;
1746 if (_iter_4.has_next()) {
1747 ++_iter_4;
1748 incr_p = true;
1749 if (_iter_4.has_next()) {
1750 _value.assign(this->r4(), _iter_4->payload());
1751 return *this;
1752 }
1753 }
1754
1755 if (_iter_6.has_next()) {
1756 if (incr_p || (++_iter_6).has_next()) {
1757 _value.assign(this->r6(), _iter_6->payload());
1758 return *this;
1759 }
1760 }
1761 _value.clear();
1762 return *this;
1763}
1764
1765template <typename PAYLOAD>
1766auto
1768 self_type zret(*this);
1769 ++*this;
1770 return zret;
1771}
1772
1773template <typename PAYLOAD>
1774auto
1776 if (_iter_6.has_prev()) {
1777 --_iter_6;
1778 _value.assign(this->r6(), _iter_6->payload());
1779 return *this;
1780 }
1781 if (_iter_4.has_prev()) {
1782 --_iter_4;
1783 _value.assign(this->r4(), _iter_4->payload());
1784 return *this;
1785 }
1786 _value.clear();
1787 return *this;
1788}
1789
1790template <typename PAYLOAD>
1791auto
1793 self_type zret(*this);
1794 --*this;
1795 return zret;
1796}
1797
1798template <typename PAYLOAD>
1799auto
1801 return _value;
1802}
1803
1804template <typename PAYLOAD>
1805auto
1807 return &_value;
1808}
1809
1810/* Bit of subtlety with equality - although it seems that if @a _iter_4 is valid, it doesn't matter
1811 * where @a _iter6 is (because it is really the iterator location that's being checked), it's
1812 * necessary to do the @a _iter_4 validity on both iterators to avoid the case of a false positive
1813 * where different internal iterators are valid. However, in practice the other (non-active)
1814 * iterator won't have an arbitrary value, it will be either @c begin or @c end in step with the
1815 * active iterator therefore it's effective and cheaper to just check both values.
1816 */
1817
1818template <typename PAYLOAD>
1819bool
1821 return _iter_4 == that._iter_4 && _iter_6 == that._iter_6;
1822}
1823
1824template <typename PAYLOAD>
1825bool
1827 return _iter_4 != that._iter_4 || _iter_6 != that._iter_6;
1828}
1829
1830template <typename PAYLOAD>
1831auto
1832IPSpace<PAYLOAD>::iterator::operator=(self_type const &that) -> self_type & {
1833 this->super_type::operator=(that);
1834 return *this;
1835}
1836
1837template <typename PAYLOAD>
1838auto
1839IPSpace<PAYLOAD>::iterator::value() const -> value_type & {
1840 return reinterpret_cast<value_type &>(const_cast<self_type *>(this)->_value);
1841}
1842
1843template <typename PAYLOAD>
1844auto
1846 return &(this->value());
1847}
1848
1849template <typename PAYLOAD>
1850auto
1852 return this->value();
1853}
1854
1855template <typename PAYLOAD>
1856auto
1858 this->super_type::operator++();
1859 return *this;
1860}
1861
1862template <typename PAYLOAD>
1863auto
1865 self_type zret{*this};
1866 ++*this;
1867 return zret;
1868}
1869
1870template <typename PAYLOAD>
1871auto
1873 this->super_type::operator--();
1874 return *this;
1875}
1876
1877template <typename PAYLOAD>
1878auto
1880 self_type zret{*this};
1881 --*this;
1882 return zret;
1883}
1884
1886
1887// +++ IPRange +++
1888
1889inline IP4Range::IP4Range(string_view const &text) {
1890 this->load(text);
1891}
1892
1893inline auto
1895 return {NetSource{*this}};
1896}
1897
1898inline IP6Range::IP6Range(string_view const &text) {
1899 this->load(text);
1900}
1901
1902inline auto
1904 return {NetSource{*this}};
1905}
1906
1907inline IPRange::IPRange(IP4Range const &range) : _family(AF_INET) {
1908 _range._ip4 = range;
1909}
1910
1911inline IPRange::IPRange(IP6Range const &range) : _family(AF_INET6) {
1912 _range._ip6 = range;
1913}
1914
1915inline IPRange::IPRange(IP4Addr const &min, IP4Addr const &max) {
1916 this->assign(min, max);
1917}
1918
1919inline IPRange::IPRange(IP6Addr const &min, IP6Addr const &max) {
1920 this->assign(min, max);
1921}
1922
1923inline IPRange::IPRange(string_view const &text) {
1924 this->load(text);
1925}
1926
1927inline IPRange::IPRange(IPRangeView const &view) {
1928 if (AF_INET == view._family) {
1929 *this = *view._raw._4;
1930 } else if (AF_INET6 == view._family) {
1931 *this = *view._raw._6;
1932 }
1933}
1934
1935inline auto
1936IPRange::assign(IP4Addr const &min, IP4Addr const &max) -> self_type & {
1937 _range._ip4.assign(min, max);
1938 _family = AF_INET;
1939 return *this;
1940}
1941
1942inline auto
1943IPRange::assign(IP6Addr const &min, IP6Addr const &max) -> self_type & {
1944 _range._ip6.assign(min, max);
1945 _family = AF_INET6;
1946 return *this;
1947}
1948
1949inline auto
1950IPRange::operator=(const IPRangeView &rv) -> self_type & {
1951 if (AF_INET == rv._family) {
1952 *this = *rv._raw._4;
1953 } else if (AF_INET6 == rv._family) {
1954 *this = *rv._raw._6;
1955 }
1956 return *this;
1957}
1958
1959inline auto
1960IPRange::clear() -> self_type & {
1961 _family = AF_UNSPEC;
1962 return *this;
1963}
1964
1965inline auto
1967 return {NetSource{*this}};
1968}
1969
1970inline bool
1971IPRange::is(sa_family_t family) const {
1972 return family == _family;
1973}
1974
1975inline bool
1976IPRange::operator!=(const self_type &that) const {
1977 return !(*this == that);
1978}
1979
1980inline bool
1982 return AF_INET == _family;
1983}
1984
1985inline bool
1987 return AF_INET6 == _family;
1988}
1989
1990inline sa_family_t IPRange::family() const {
1991 return _family;
1992}
1993inline IP4Range const& IPRange::ip4() const {
1994 return _range._ip4;
1995}
1996
1997inline IP6Range const& IPRange::ip6() const {
1998 return _range._ip6;
1999}
2000
2001inline auto
2002IPRangeView::clear() -> self_type & {
2003 _family = AF_UNSPEC;
2004 return *this;
2005}
2006
2007inline bool
2008IPRangeView::empty() const {
2009 if (AF_INET6 == _family) {
2010 return _raw._6->empty();
2011 } else if (AF_INET == _family) {
2012 return _raw._4->empty();
2013 } else {
2014 return true;
2015 }
2016}
2017
2018inline bool
2020 return AF_INET == _family;
2021}
2022
2023inline bool
2025 return AF_INET6 == _family;
2026}
2027
2028inline bool
2029IPRangeView::is(sa_family_t f) const {
2030 return f == _family;
2031}
2032
2033inline bool IPRange::contains(IPAddr const & addr) const {
2034 if (addr.family() != _family) {
2035 return false;
2036 }
2037 if (this->ip4()) {
2038 return _range._ip4.contains(addr.ip4());
2039 } else if (this->is_ip6()) {
2040 return _range._ip6.contains(addr.ip6());
2041 }
2042 return false;
2043}
2044
2045inline bool IPRange::contains(IP6Addr const & addr) const {
2046 return this->is_ip6() && _range._ip6.contains(addr);
2047}
2048
2049inline bool IPRange::contains(IP4Addr const & addr) const {
2050 return this->is_ip4() && _range._ip4.contains(addr);
2051}
2052
2053inline IP4Range const &
2055 return *_raw._4;
2056}
2057
2058inline IP6Range const &
2060 return *_raw._6;
2061}
2062
2063inline bool
2065 return AF_INET == _family || AF_INET6 == _family;
2066}
2067
2068inline auto
2069IPRangeView::assign(IP4Range const &r) -> self_type & {
2070 _family = r.family();
2071 _raw._4 = &r;
2072 return *this;
2073}
2074
2075inline auto
2076IPRangeView::assign(IP6Range const &r) -> self_type & {
2077 _family = r.family();
2078 _raw._6 = &r;
2079 return *this;
2080}
2081
2082inline bool
2083IPRangeView::operator!=(IPRangeView::self_type const &that) const {
2084 return !(*this == that);
2085}
2086
2087inline IPAddr
2089 return AF_INET == _family ? _raw._4->min() : AF_INET6 == _family ? _raw._6->min() : IPAddr::INVALID;
2090}
2091
2092inline IPAddr
2094 return AF_INET == _family ? _raw._4->max() : AF_INET6 == _family ? _raw._6->max() : IPAddr::INVALID;
2095}
2096
2097inline bool IPRangeView::contains(IPAddr const& addr) const {
2098 if (_family != addr.family()) {
2099 return false;
2100 }
2101 return (_family == addr.family() ) &&
2102 ( ( this->is_ip4() && _raw._4->contains(addr.ip4()) ) ||
2103 ( this->is_ip6() && _raw._6->contains(addr.ip6()) )
2104 );
2105}
2106
2107inline bool IPRangeView::contains(IP6Addr const& addr) const {
2108 return this->is_ip6() && _raw._6->contains(addr);
2109}
2110
2111inline bool IPRangeView::contains(IP4Addr const& addr) const {
2112 return this->is_ip4() && _raw._4->contains(addr);
2113}
2114
2115// +++ IPNet +++
2116
2118
2119inline IPMask const &
2121 return _mask;
2122}
2123
2124inline bool
2126 return !_mask.is_valid();
2127}
2128
2129inline IP4Addr
2131 return _addr;
2132}
2133
2134inline IP4Addr
2136 return _addr | _mask;
2137}
2138
2139inline IP4Range
2141 return {this->min(), this->max()};
2142}
2143
2144inline bool
2145IP4Net::operator==(self_type const &that) const {
2146 return _mask == that._mask && _addr == that._addr;
2147}
2148
2149inline bool
2150IP4Net::operator!=(self_type const &that) const {
2151 return _mask != that._mask || _addr != that._addr;
2152}
2153
2154inline IP4Net::self_type &
2155IP4Net::assign(IP4Addr const &addr, IPMask const &mask) {
2156 _addr = addr & mask;
2157 _mask = mask;
2158 return *this;
2159}
2160
2162
2163inline IPMask const &
2165 return _mask;
2166}
2167
2168inline bool
2170 return !_mask.is_valid();
2171}
2172
2173inline IP6Addr
2175 return _addr;
2176}
2177
2178inline IP6Addr
2180 return _addr | _mask;
2181}
2182
2183inline IP6Range
2185 return {this->min(), this->max()};
2186}
2187
2188inline bool
2189IP6Net::operator==(self_type const &that) const {
2190 return _mask == that._mask && _addr == that._addr;
2191}
2192
2193inline bool
2194IP6Net::operator!=(self_type const &that) const {
2195 return _mask != that._mask || _addr != that._addr;
2196}
2197
2198inline IP6Net::self_type &
2199IP6Net::assign(IP6Addr const &addr, IPMask const &mask) {
2200 _addr = addr & mask;
2201 _mask = mask;
2202 return *this;
2203}
2204
2205inline IPNet::IPNet(IPAddr const &addr, IPMask const &mask) : _addr(addr & mask), _mask(mask) {}
2206
2208 this->load(text);
2209}
2210
2211inline bool
2213 return !_mask.is_valid();
2214}
2215
2216inline IPAddr
2217IPNet::min() const {
2218 return _addr;
2219}
2220
2221inline IPAddr
2222IPNet::max() const {
2223 return _addr | _mask;
2224}
2225
2226inline IPMask::raw_type
2228 return _mask.width();
2229}
2230
2231inline IPMask const &
2233 return _mask;
2234}
2235
2236inline IPRange
2238 return {this->min(), this->max()};
2239}
2240
2241inline IPNet::self_type &
2242IPNet::assign(IPAddr const &addr, IPMask const &mask) {
2243 _addr = addr & mask;
2244 _mask = mask;
2245 return *this;
2246}
2247
2248inline bool
2249IPNet::operator==(IPNet::self_type const &that) const {
2250 return _mask == that._mask && _addr == that._addr;
2251}
2252
2253inline bool
2254IPNet::operator!=(IPNet::self_type const &that) const {
2255 return _mask != that._mask || _addr != that._addr;
2256}
2257
2258inline bool
2259operator==(IPNet const &lhs, IP4Net const &rhs) {
2260 return lhs.is_ip4() && lhs.ip4() == rhs;
2261}
2262
2263inline bool
2264operator==(IP4Net const &lhs, IPNet const &rhs) {
2265 return rhs.is_ip4() && rhs.ip4() == lhs;
2266}
2267
2268inline bool
2269operator==(IPNet const &lhs, IP6Net const &rhs) {
2270 return lhs.is_ip6() && lhs.ip6() == rhs;
2271}
2272
2273inline bool
2274operator==(IP6Net const &lhs, IPNet const &rhs) {
2275 return rhs.is_ip6() && rhs.ip6() == lhs;
2276}
2277
2278inline IP4Net
2279IPNet::ip4() const {
2280 return IP4Net{_addr.ip4(), _mask};
2281}
2282
2283inline IP6Net
2284IPNet::ip6() const {
2285 return IP6Net{_addr.ip6(), _mask};
2286}
2287
2288inline auto
2289IPNet::clear() -> self_type & {
2290 _mask.clear();
2291 return *this;
2292}
2293
2294// +++ Range -> Network classes +++
2295
2296inline bool
2297IP4Range::NetSource::is_valid(swoc::IP4Addr mask) const {
2298 return ((mask._addr & _range._min._addr) == _range._min._addr) && ((_range._min._addr | ~mask._addr) <= _range._max._addr);
2299}
2300
2301inline IP4Net
2303 return IP4Net{_range.min(), IPMask{_cidr}};
2304}
2305
2308 return *this;
2309}
2310
2313 return self_type{range_type{}};
2314}
2315
2316inline bool
2318 return _range.empty();
2319}
2320
2321inline IPMask
2323 return IPMask{_cidr};
2324}
2325
2326inline auto
2328 return this;
2329}
2330
2331inline IP4Addr const &
2333 return _range.min();
2334}
2335
2336inline bool
2337IP4Range::NetSource::operator==(IP4Range::NetSource::self_type const &that) const {
2338 return ((_cidr == that._cidr) && (_range == that._range)) || (_range.empty() && that._range.empty());
2339}
2340
2341inline bool
2342IP4Range::NetSource::operator!=(IP4Range::NetSource::self_type const &that) const {
2343 return !(*this == that);
2344}
2345
2346inline auto
2348 return *this;
2349}
2350
2351inline auto
2353 return self_type{range_type{}};
2354}
2355
2356inline bool
2358 return _range.empty();
2359}
2360
2361inline IP6Net
2363 return IP6Net{_range.min(), _mask};
2364}
2365
2366inline auto
2368 return this;
2369}
2370
2371inline bool
2372IP6Range::NetSource::is_valid(IPMask const &mask) {
2373 return ((_range.min() & mask) == _range.min()) && ((_range.min() | mask) <= _range.max());
2374}
2375
2376inline bool
2377IP6Range::NetSource::operator==(IP6Range::NetSource::self_type const &that) const {
2378 return ((_mask == that._mask) && (_range == that._range)) || (_range.empty() && that._range.empty());
2379}
2380
2381inline bool
2382IP6Range::NetSource::operator!=(IP6Range::NetSource::self_type const &that) const {
2383 return !(*this == that);
2384}
2385
2386inline IP6Addr const &
2388 return _range.min();
2389}
2390
2391inline IPMask
2393 return _mask;
2394}
2395
2397 if (range.is_ip4()) {
2398 new (&_ip4) decltype(_ip4)(range.ip4());
2399 _family = AF_INET;
2400 } else if (range.is_ip6()) {
2401 new (&_ip6) decltype(_ip6)(range.ip6());
2402 _family = AF_INET6;
2403 }
2404}
2405
2407 if (rv.is_ip4()) {
2408 new (&_ip4) decltype(_ip4)(rv.ip4());
2409 _family = AF_INET;
2410 } else if (rv.is_ip6()) {
2411 new (&_ip6) decltype(_ip6)(rv.ip6());
2412 _family = AF_INET6;
2413 }
2414}
2415
2416inline auto
2418 return *this;
2419}
2420
2421inline auto
2423 return AF_INET == _family ? self_type{IP4Range{}} : AF_INET6 == _family ? self_type{IP6Range{}} : self_type{IPRange{}};
2424}
2425
2426inline IPAddr
2428 if (AF_INET == _family) {
2429 return _ip4.addr();
2430 } else if (AF_INET6 == _family) {
2431 return _ip6.addr();
2432 }
2433 return {};
2434}
2435
2436inline IPMask
2438 if (AF_INET == _family) {
2439 return _ip4.mask();
2440 } else if (AF_INET6 == _family) {
2441 return _ip6.mask();
2442 }
2443 return {};
2444}
2445
2446inline IPNet
2448 return {this->addr(), this->mask()};
2449}
2450
2451inline auto
2453 if (AF_INET == _family) {
2454 ++_ip4;
2455 } else if (AF_INET6 == _family) {
2456 ++_ip6;
2457 }
2458 return *this;
2459}
2460
2461inline auto
2463 return this;
2464}
2465
2466inline bool
2467IPRange::NetSource::operator==(self_type const &that) const {
2468 if (_family != that._family) {
2469 return false;
2470 }
2471 if (AF_INET == _family) {
2472 return _ip4 == that._ip4;
2473 } else if (AF_INET6 == _family) {
2474 return _ip6 == that._ip6;
2475 } else if (AF_UNSPEC == _family) {
2476 return true;
2477 }
2478 return false;
2479}
2480
2481inline bool
2482IPRange::NetSource::operator!=(self_type const &that) const {
2483 return !(*this == that);
2484}
2485
2486// --- IPSpace
2487
2488template <typename PAYLOAD>
2489auto
2490IPSpace<PAYLOAD>::mark_bulk(std::pair<DiscreteRange<IP4Addr>, PAYLOAD>* range_payloads, size_t size, bool is_sorted) -> self_type & {
2491 _ip4.mark_bulk(range_payloads, size, is_sorted);
2492 return *this;
2493}
2494
2495template <typename PAYLOAD>
2496auto
2497IPSpace<PAYLOAD>::mark_bulk(std::pair<DiscreteRange<IP6Addr>, PAYLOAD>* range_payloads, size_t size, bool is_sorted) -> self_type & {
2498 _ip6.mark_bulk(range_payloads, size, is_sorted);
2499 return *this;
2500}
2501
2502template <typename PAYLOAD>
2503auto
2504IPSpace<PAYLOAD>::mark_bulk(std::vector<std::pair<DiscreteRange<IP4Addr>, PAYLOAD>>& range_payloads, bool is_sorted) -> self_type & {
2505 _ip4.mark_bulk(range_payloads, is_sorted);
2506 return *this;
2507}
2508
2509template <typename PAYLOAD>
2510auto
2511IPSpace<PAYLOAD>::mark_bulk(std::vector<std::pair<DiscreteRange<IP6Addr>, PAYLOAD>>& range_payloads, bool is_sorted) -> self_type & {
2512 _ip6.mark_bulk(range_payloads, is_sorted);
2513 return *this;
2514}
2515
2516template <typename PAYLOAD>
2517auto
2518IPSpace<PAYLOAD>::mark(IPRange const &range, PAYLOAD const &payload) -> self_type & {
2519 if (range.is(AF_INET)) {
2520 _ip4.mark(range.ip4(), payload);
2521 } else if (range.is(AF_INET6)) {
2522 _ip6.mark(range.ip6(), payload);
2523 }
2524 return *this;
2525}
2526
2527template <typename PAYLOAD>
2528auto
2529IPSpace<PAYLOAD>::fill(IPRange const &range, PAYLOAD const &payload) -> self_type & {
2530 if (range.is(AF_INET6)) {
2531 _ip6.fill(range.ip6(), payload);
2532 } else if (range.is(AF_INET)) {
2533 _ip4.fill(range.ip4(), payload);
2534 }
2535 return *this;
2536}
2537
2538template <typename PAYLOAD>
2539auto
2540IPSpace<PAYLOAD>::erase(IPRange const &range) -> self_type & {
2541 if (range.is(AF_INET)) {
2542 _ip4.erase(range.ip4());
2543 } else if (range.is(AF_INET6)) {
2544 _ip6.erase(range.ip6());
2545 }
2546 return *this;
2547}
2548
2549template <typename PAYLOAD>
2550template <typename F, typename U>
2551auto
2552IPSpace<PAYLOAD>::blend(IPRange const &range, U const &color, F &&blender) -> self_type & {
2553 if (range.is(AF_INET)) {
2554 _ip4.blend(range.ip4(), color, blender);
2555 } else if (range.is(AF_INET6)) {
2556 _ip6.blend(range.ip6(), color, blender);
2557 }
2558 return *this;
2559}
2560
2561template <typename PAYLOAD>
2562template <typename F, typename U>
2563auto
2564IPSpace<PAYLOAD>::blend(IP4Range const &range, U const &color, F &&blender) -> self_type & {
2565 _ip4.blend(range, color, std::forward<F>(blender));
2566 return *this;
2567}
2568
2569template <typename PAYLOAD>
2570template <typename F, typename U>
2571auto
2572IPSpace<PAYLOAD>::blend(IP6Range const &range, U const &color, F &&blender) -> self_type & {
2573 _ip6.blend(range, color, std::forward<F>(blender));
2574 return *this;
2575}
2576
2577template <typename PAYLOAD>
2578void
2580 _ip4.clear();
2581 _ip6.clear();
2582}
2583
2584template <typename PAYLOAD>
2585auto
2587 return iterator{_ip4.begin(), _ip6.begin()};
2588}
2589
2590template <typename PAYLOAD>
2591auto
2593 return const_cast<self_type *>(this)->begin();
2594}
2595
2596template <typename PAYLOAD>
2597auto
2599 return iterator{_ip4.end(), _ip6.end()};
2600}
2601
2602template <typename PAYLOAD>
2603auto
2605 return const_cast<self_type *>(this)->end();
2606}
2607
2608template <typename PAYLOAD>
2609auto
2611 return this->begin();
2612}
2613
2614template <typename PAYLOAD>
2615auto
2617 return this->begin();
2618}
2619
2620template <typename PAYLOAD>
2621auto
2623 return {_ip4.end(), _ip6.begin()};
2624}
2625
2626template <typename PAYLOAD>
2627auto
2629 return const_cast<self_type *>(this)->end_ip4();
2630}
2631
2632template <typename PAYLOAD>
2633auto
2635 return {_ip4.end(), _ip6.begin()};
2636}
2637
2638template <typename PAYLOAD>
2639auto
2641 return const_cast<self_type *>(this)->begin_ip6();
2642}
2643
2644template <typename PAYLOAD>
2645auto
2647 return this->end();
2648}
2649
2650template <typename PAYLOAD>
2651auto
2653 return this->end();
2654}
2655
2656template <typename PAYLOAD>
2657auto
2659 if (addr.is_ip4()) {
2660 return this->find(addr.ip4());
2661 } else if (addr.is_ip6()) {
2662 return this->find(addr.ip6());
2663 }
2664 return this->end();
2665}
2666
2667template <typename PAYLOAD>
2668auto
2670 if (addr.is_ip4()) {
2671 return this->find(addr.ip4());
2672 } else if (addr.is_ip6()) {
2673 return this->find(addr.ip6());
2674 }
2675 return this->end();
2676}
2677
2678template <typename PAYLOAD>
2679auto
2681 if (auto spot = _ip4.find(addr); spot != _ip4.end()) {
2682 return {spot, _ip6.begin()};
2683 }
2684 return this->end();
2685}
2686
2687template <typename PAYLOAD>
2688auto
2690 if (auto spot = _ip4.find(addr); spot != _ip4.end()) {
2691 return {spot, _ip6.begin()};
2692 }
2693 return this->end();
2694}
2695
2696template <typename PAYLOAD>
2697auto
2699 return {_ip4.end(), _ip6.find(addr)};
2700}
2701
2702template <typename PAYLOAD>
2703auto
2705 return const_iterator{_ip4.end(), _ip6.find(addr)};
2706}
2707
2708template <typename PAYLOAD>
2709auto
2711 if (AF_INET == family) {
2712 return this->begin_ip4();
2713 } else if (AF_INET6 == family) {
2714 return this->begin_ip6();
2715 }
2716 return this->end();
2717}
2718
2719template <typename PAYLOAD>
2720auto
2722 if (AF_INET == family) {
2723 return this->end_ip4();
2724 } else if (AF_INET6 == family) {
2725 return this->end_ip6();
2726 }
2727 return this->end();
2728}
2729
2730template <typename PAYLOAD>
2731size_t
2733 return _ip4.count();
2734}
2735
2736template <typename PAYLOAD>
2737size_t
2739 return _ip6.count();
2740}
2741
2742template <typename PAYLOAD>
2743size_t
2745 return _ip4.count() + _ip6.count();
2746}
2747
2748template <typename PAYLOAD>
2749size_t
2750IPSpace<PAYLOAD>::count(sa_family_t f) const {
2751 return IP4Addr::AF_value == f ? _ip4.count() : IP6Addr::AF_value == f ? _ip6.count() : 0;
2752}
2753
2754template <typename PAYLOAD>
2755bool
2757 return _ip4.empty() && _ip6.empty();
2758}
2759
2760inline auto
2762 ++_iter;
2763 return *this;
2764}
2765
2766inline auto
2768 --_iter;
2769 return *this;
2770}
2771
2772inline auto
2774 self_type zret{*this};
2775 ++_iter;
2776 return zret;
2777}
2778
2779inline auto
2781 self_type zret{*this};
2782 --_iter;
2783 return zret;
2784}
2785
2786inline auto
2788 return _iter->_rv;
2789}
2790
2791inline auto
2793 return &(_iter->_rv);
2794}
2795
2796inline bool
2797IPRangeSet::const_iterator::operator==(IPRangeSet::const_iterator::self_type const &that) const {
2798 return _iter == that._iter;
2799}
2800
2801inline bool
2802IPRangeSet::const_iterator::operator!=(IPRangeSet::const_iterator::self_type const &that) const {
2803 return _iter != that._iter;
2804}
2805
2806}} // namespace swoc::SWOC_VERSION_NS
2807
2809namespace std {
2810
2811// -- Tuple support for IP4Net --
2812template <> class tuple_size<swoc::IP4Net> : public std::integral_constant<size_t, 2> {};
2813
2814template <size_t IDX> class tuple_element<IDX, swoc::IP4Net> {
2815 static_assert("swoc::IP4Net tuple index out of range");
2816};
2817
2818template <> class tuple_element<0, swoc::IP4Net> {
2819public:
2820 using type = swoc::IP4Addr;
2821};
2822
2823template <> class tuple_element<1, swoc::IP4Net> {
2824public:
2825 using type = swoc::IPMask;
2826};
2827
2828// -- Tuple support for IP6Net --
2829template <> class tuple_size<swoc::IP6Net> : public std::integral_constant<size_t, 2> {};
2830
2831template <size_t IDX> class tuple_element<IDX, swoc::IP6Net> {
2832 static_assert("swoc::IP6Net tuple index out of range");
2833};
2834
2835template <> class tuple_element<0, swoc::IP6Net> {
2836public:
2837 using type = swoc::IP6Addr;
2838};
2839
2840template <> class tuple_element<1, swoc::IP6Net> {
2841public:
2842 using type = swoc::IPMask;
2843};
2844
2845// -- Tuple support for IPNet --
2846template <> class tuple_size<swoc::IPNet> : public std::integral_constant<size_t, 2> {};
2847
2848template <size_t IDX> class tuple_element<IDX, swoc::IPNet> {
2849 static_assert("swoc::IPNet tuple index out of range");
2850};
2851
2852template <> class tuple_element<0, swoc::IPNet> {
2853public:
2854 using type = swoc::IPAddr;
2855};
2856
2857template <> class tuple_element<1, swoc::IPNet> {
2858public:
2859 using type = swoc::IPMask;
2860};
2861
2862} // namespace std
2863
2864namespace swoc { inline namespace SWOC_VERSION_NS {
2865
2866template <size_t IDX>
2867typename std::tuple_element<IDX, IP4Net>::type
2868get(swoc::IP4Net const &net) {
2869 if constexpr (IDX == 0) {
2870 return net.min();
2871 } else if constexpr (IDX == 1) {
2872 return net.mask();
2873 }
2874}
2875
2876template <size_t IDX>
2877typename std::tuple_element<IDX, IP6Net>::type
2878get(swoc::IP6Net const &net) {
2879 if constexpr (IDX == 0) {
2880 return net.min();
2881 } else if constexpr (IDX == 1) {
2882 return net.mask();
2883 }
2884}
2885
2886template <size_t IDX>
2887typename std::tuple_element<IDX, IPNet>::type
2888get(swoc::IPNet const &net) {
2889 if constexpr (IDX == 0) {
2890 return net.min();
2891 } else if constexpr (IDX == 1) {
2892 return net.mask();
2893 }
2894}
2896
2897}} // namespace swoc::SWOC_VERSION_NS
2898
2899// Tuple support for IPSpace values.
2901
2902namespace std {
2903
2904template <typename P> class tuple_size<swoc::detail::ip_space_value_type<P>> : public integral_constant<size_t, 2> {};
2905template <typename P> class tuple_size<swoc::detail::ip_space_const_value_type<P>> : public integral_constant<size_t, 2> {};
2906
2907template <size_t IDX, typename P> class tuple_element<IDX, swoc::detail::ip_space_value_type<P>> {
2908 static_assert("swoc::IPSpace::value_type tuple index out of range");
2909};
2910template <size_t IDX, typename P> class tuple_element<IDX, swoc::detail::ip_space_const_value_type<P>> {
2911 static_assert("swoc::IPSpace::value_type tuple index out of range");
2912};
2913
2914template <typename P> class tuple_element<0, swoc::detail::ip_space_value_type<P>> {
2915public:
2916 using type = swoc::IPRangeView const &;
2917};
2918
2919template <typename P> class tuple_element<1, swoc::detail::ip_space_value_type<P>> {
2920public:
2921 using type = P &;
2922};
2923
2924template <typename P> class tuple_element<0, swoc::detail::ip_space_const_value_type<P>> {
2925public:
2926 using type = swoc::IPRangeView const &;
2927};
2928
2929template <typename P> class tuple_element<1, swoc::detail::ip_space_const_value_type<P>> {
2930public:
2931 using type = P const &;
2932};
2933
2934} // namespace std
2935
2936namespace swoc { inline namespace SWOC_VERSION_NS { namespace detail {
2937template <size_t IDX, typename P>
2938auto
2939get(ip_space_const_value_type<P> const &p) -> typename std::tuple_element<IDX, ip_space_const_value_type<P>>::type {
2940 if constexpr (IDX == 0) {
2941 return p._rv;
2942 } else if constexpr (IDX == 1) {
2943 return *(p._payload);
2944 }
2945}
2946
2947template <size_t IDX, typename P>
2948auto
2949get(ip_space_value_type<P> const &p) -> typename std::tuple_element<IDX, ip_space_value_type<P>>::type {
2950 if constexpr (IDX == 0) {
2951 return p._rv;
2952 } else if constexpr (IDX == 1) {
2953 return *(p._payload);
2954 }
2955}
2956}}} // namespace swoc::SWOC_VERSION_NS::detail
2957
2958// Support unqualified @c get because ADL doesn't seem to work.
2959using swoc::detail::get;
2960// Support @c std::get
2961namespace std {
2962using swoc::detail::get;
2963}
2964
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:710
bool empty() const
Definition IPRange.h:2125
IP4Addr max() const
Definition IPRange.h:2135
self_type & clear()
Reset network to invalid state.
Definition IPRange.h:761
self_type & assign(IP4Addr const &addr, IPMask const &mask)
Definition IPRange.h:2155
bool load(swoc::TextView text)
Definition swoc_ip.cc:851
IPMask _mask
Network mask.
Definition IPRange.h:774
IP4Range as_range() const
Definition IPRange.h:2140
IP4Net(self_type const &that)=default
Copy constructor.
IP4Net()=default
Construct invalid network.
IPMask const & mask() const
Definition IPRange.h:2120
IP4Addr _addr
Network address (also lower_node).
Definition IPRange.h:773
bool operator==(self_type const &that) const
Equality.
Definition IPRange.h:2145
bool operator!=(self_type const &that) const
Inequality.
Definition IPRange.h:2150
IP4Addr min() const
Definition IPRange.h:2130
IP4Addr _mask
Mask for current network.
Definition IPRange.h:168
NetSource(self_type const &that)=default
Copy constructor.
IP4Net operator*() const
Definition IPRange.h:2302
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:2322
bool empty() const
Return true if there are valid networks, false if not.
Definition IPRange.h:2317
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:2332
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:2342
NetSource(range_type const &range)
Construct from range.
Definition swoc_ip.cc:991
static iterator end()
Past last network.
Definition IPRange.h:2312
bool operator==(self_type const &that) const
Equality.
Definition IPRange.h:2337
iterator begin() const
First network.
Definition IPRange.h:2307
self_type * operator->()
Access this as if it were an IP4Net.
Definition IPRange.h:2327
bool load(string_view text)
< Import assign methods.
Definition swoc_ip.cc:954
NetSource networks() const
Definition IPRange.h:1894
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:778
IP6Addr min() const
Definition IPRange.h:2174
IP6Net(TextView text)
Definition IPRange.h:802
IPMask _mask
Network mask.
Definition IPRange.h:849
bool empty() const
Definition IPRange.h:2169
self_type & assign(IP6Addr const &addr, IPMask const &mask)
Definition IPRange.h:2199
IPMask const & mask() const
Definition IPRange.h:2164
IP6Net()=default
Construct invalid network.
self_type & clear()
Reset network to invalid state.
Definition IPRange.h:836
IP6Addr max() const
Definition IPRange.h:2179
bool operator==(self_type const &that) const
Equality.
Definition IPRange.h:2189
IP6Range as_range() const
Definition IPRange.h:2184
IP6Net(self_type const &that)=default
Copy constructor.
bool operator!=(self_type const &that) const
Inequality.
Definition IPRange.h:2194
IP6Addr _addr
Network address (also lower_node).
Definition IPRange.h:848
bool load(swoc::TextView text)
Definition swoc_ip.cc:874
IP6Addr const & addr() const
Definition IPRange.h:2387
bool operator!=(self_type const &that) const
Inequality.
Definition IPRange.h:2382
self_type operator++(int)
Move to next network.
IP6Net operator*() const
Definition IPRange.h:2362
iterator begin() const
First network.
Definition IPRange.h:2347
IPMask _mask
Current CIDR value.
Definition IPRange.h:310
IPMask mask() const
Definition IPRange.h:2392
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:2352
self_type & operator++()
Move to next network.
Definition swoc_ip.cc:1207
bool operator==(self_type const &that) const
Equality.
Definition IPRange.h:2377
self_type * operator->()
Access this as if it were an IP6Net.
Definition IPRange.h:2367
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:1903
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:2227
IP6Net ip6() const
Definition IPRange.h:2284
IPRange as_range() const
Definition IPRange.h:2237
IP4Net ip4() const
Definition IPRange.h:2279
bool operator==(self_type const &that) const
Equality.
Definition IPRange.h:2249
self_type & assign(IPAddr const &addr, IPMask const &mask)
Definition IPRange.h:2242
IPAddr _addr
Address and family.
Definition IPRange.h:948
IPNet()=default
Construct invalid network.
bool empty() const
Definition IPRange.h:2212
bool load(swoc::TextView text)
Definition swoc_ip.cc:897
bool is_ip6() const
Definition IPRange.h:914
IPMask const & mask() const
Definition IPRange.h:2232
IPAddr max() const
Definition IPRange.h:2222
self_type & clear()
Reset network to invalid state.
Definition IPRange.h:2289
IPAddr min() const
Definition IPRange.h:2217
bool is_ip4() const
Definition IPRange.h:908
IPMask _mask
Network mask.
Definition IPRange.h:949
bool operator!=(self_type const &that) const
Inequality.
Definition IPRange.h:2254
sa_family_t family() const
Address family of network.
Definition IPRange.h:920
Bidirectional constant iterator for iteration over ranges.
Definition IPRange.h:1592
const_iterator()=default
Default constructor.
super_type _iter
Underlying iterator.
Definition IPRange.h:1651
bool operator!=(self_type const &that) const
Inequality.
Definition IPRange.h:2802
self_type & operator=(self_type const &that)=default
Assignment.
reference operator*() const
Definition IPRange.h:2787
const_iterator(self_type const &that)=default
Copy constructor.
IPRange _r
Some less temporary storage for dereferences.
Definition IPRange.h:1652
bool operator==(self_type const &that) const
Equality.
Definition IPRange.h:2797
IPRangeSet()=default
Default construct empty set.
self_type & fill(swoc::IPRange const &r)
Definition IPRange.h:1680
size_t count() const
Definition IPRange.h:1697
void clear()
Remove all addresses in the set.
Definition IPRange.h:1707
self_type & mark(swoc::IPRange const &r)
Definition IPRange.h:1674
self_type & erase(swoc::IPRange const &r)
Definition IPRange.h:1686
const_iterator begin() const
Definition IPRange.h:1659
Space _addrs
The address set.
Definition IPRange.h:1670
const_iterator end() const
Definition IPRange.h:1664
bool contains(swoc::IPAddr const &addr) const
Definition IPRange.h:1692
bool operator==(IPRange const &r) const
Compare to a range.
Definition swoc_ip.cc:1244
IPRange::NetSource networks() const
Definition IPRange.h:698
bool is_ip4() const
Definition IPRange.h:2019
bool contains(IPAddr const &addr) const
Definition IPRange.h:2097
IP6Range const & ip6() const
Definition IPRange.h:2059
IPAddr min() const
Definition IPRange.h:2088
storage_type _raw
Storage for the view pointer.
Definition IPRange.h:705
bool is_ip6() const
Definition IPRange.h:2024
IPAddr max() const
Definition IPRange.h:2093
bool is(sa_family_t family) const
Definition IPRange.h:2029
IP4Range const & ip4() const
Definition IPRange.h:2054
bool operator!=(self_type const &that) const
Inequality.
Definition IPRange.h:2083
self_type & assign(IP4Range const &r)
Update the view.
Definition IPRange.h:2069
sa_family_t _family
Range address family.
Definition IPRange.h:706
bool valid() const
Definition IPRange.h:2064
IPRangeView()=default
Default constructor - invalid view.
self_type & clear()
Reset to invalid view.
Definition IPRange.h:2002
iterator end() const
Past last network.
Definition IPRange.h:2422
self_type * operator->()
Access this as if it were an IP6Net.
Definition IPRange.h:2462
IPAddr addr() const
Definition IPRange.h:2427
bool operator==(self_type const &that) const
Equality.
Definition IPRange.h:2467
std::monostate _nil
Default value, no addresses.
Definition IPRange.h:581
IPNet operator*() const
Definition IPRange.h:2447
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:2417
bool operator!=(self_type const &that) const
Inequality.
Definition IPRange.h:2482
IP4Range::NetSource _ip4
IPv4 addresses.
Definition IPRange.h:582
self_type & operator++()
Move to next network.
Definition IPRange.h:2452
IPRange range_type
Import base range type.
Definition IPRange.h:534
IPMask mask() const
Definition IPRange.h:2437
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:2396
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:1986
bool operator!=(self_type const &that) const
Inequality.
Definition IPRange.h:1976
bool load(std::string_view const &text)
Definition swoc_ip.cc:1111
IP4Range const & ip4() const
Definition IPRange.h:1993
IPRange(IP4Addr addr)
Definition IPRange.h:363
sa_family_t family() const
Definition IPRange.h:1990
NetSource networks() const
Definition IPRange.h:1966
IPRange(IPAddr const &addr)
Definition IPRange.h:357
bool is(sa_family_t family) const
Definition IPRange.h:1971
bool is_ip4() const
Definition IPRange.h:1981
IP6Range _ip6
IPv6 range.
Definition IPRange.h:519
bool contains(IPAddr const &addr) const
Definition IPRange.h:2033
IP4Range _ip4
IPv4 range.
Definition IPRange.h:518
self_type & operator=(IPRangeView const &rv)
Assign from view.
Definition IPRange.h:1950
self_type & assign(IP4Addr const &min, IP4Addr const &max)
Definition IPRange.h:1936
sa_family_t _family
Family of _range.
Definition IPRange.h:523
self_type & clear()
Make the range empty / invalid.
Definition IPRange.h:1960
IP6Range const & ip6() const
Definition IPRange.h:1997
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:1245
IP4Range const & r4()
Definition IPRange.h:1318
const_iterator(self_type const &that)=default
Copy constructor.
IP6Range const & r6()
Definition IPRange.h:1323
bool operator==(self_type const &that) const
Definition IPRange.h:1820
IP6Space::iterator _iter_6
Definition IPRange.h:1300
const_iterator()=default
Default constructor.
self_type & operator=(self_type const &that)
Definition IPRange.h:1735
bool operator!=(self_type const &that) const
Definition IPRange.h:1826
IP4Space::iterator _iter_4
IPv4 sub-space iterator.
Definition IPRange.h:1299
value_type _value
Current value.
Definition IPRange.h:1302
iterator()=default
Default constructor.
detail::ip_space_value_type< PAYLOAD > value_type
Value type of iteration.
Definition IPRange.h:1348
iterator(self_type const &that)=default
Copy constructor.
reference operator*() const
Definition IPRange.h:1851
iterator(const_iterator const &that)
Definition IPRange.h:1344
self_type & operator=(self_type const &that)
Definition IPRange.h:1832
iterator find(IP6Addr const &addr)
Definition IPRange.h:2698
const_iterator end(sa_family_t family) const
Definition IPRange.h:2721
const_iterator end_ip4() const
Definition IPRange.h:2628
const_iterator begin_ip4() const
Definition IPRange.h:2616
self_type & mark(IPRange const &range, PAYLOAD const &payload)
Definition IPRange.h:2518
const_iterator begin_ip6() const
Definition IPRange.h:2640
const_iterator find(IP6Addr const &addr) const
Definition IPRange.h:2704
size_t count_ip4() const
Definition IPRange.h:2732
iterator find(IPAddr const &addr)
Definition IPRange.h:2658
self_type & fill(IPRange const &range, PAYLOAD const &payload)
Definition IPRange.h:2529
PAYLOAD payload_t
Definition IPRange.h:1115
iterator begin_ip6()
Definition IPRange.h:2634
iterator end_ip6()
Definition IPRange.h:2646
size_t count_ip6() const
Definition IPRange.h:2738
iterator begin()
Definition IPRange.h:2586
iterator begin_ip4()
Definition IPRange.h:2610
const_iterator find(IP4Addr const &addr) const
Definition IPRange.h:2689
std::pair< iterator, iterator > intersection(IP6Range const &r)
Definition IPRange.h:1490
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:2511
void clear()
Remove all ranges.
Definition IPRange.h:2579
bool empty() const
Definition IPRange.h:2756
iterator find(IP4Addr const &addr)
Definition IPRange.h:2680
const_iterator begin(sa_family_t family) const
Definition IPRange.h:2710
detail::ip_space_value_type< PAYLOAD > value_type
Iterator value, a range and payload.
Definition IPRange.h:1117
const_iterator begin() const
Definition IPRange.h:2592
self_type & blend(IPRange const &range, U const &color, F &&blender)
std::pair< iterator, iterator > intersection(IPRange const &r)
Definition IPRange.h:1501
const_iterator end() const
Definition IPRange.h:2604
self_type & mark_bulk(std::pair< DiscreteRange< IP6Addr >, PAYLOAD > *range_payloads, size_t size, bool is_sorted=false)
Definition IPRange.h:2497
std::pair< iterator, iterator > intersection(IP4Range const &r)
Definition IPRange.h:1479
iterator end()
Definition IPRange.h:2598
IPSpace()=default
Construct an empty space.
const_iterator end_ip6() const
Definition IPRange.h:2652
size_t count(sa_family_t f) const
Definition IPRange.h:2750
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:2504
const_iterator find(IPAddr const &addr) const
Definition IPRange.h:2669
self_type & mark_bulk(std::pair< DiscreteRange< IP4Addr >, PAYLOAD > *range_payloads, size_t size, bool is_sorted=false)
Definition IPRange.h:2490
iterator end_ip4()
Definition IPRange.h:2622
self_type & erase(IPRange const &range)
Definition IPRange.h:2540
size_t count() const
Definition IPRange.h:2744
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:1007
bool operator==(std::tuple< swoc::IPRange, PAYLOAD > const &t) const
Equality against an equivalent tuple.
Definition IPRange.h:1090
PAYLOAD const & payload() const
Definition IPRange.h:1028
IPRangeView _rv
View to the current range.
Definition IPRange.h:974
self_type & clear()
Reset to default constructed state.
Definition IPRange.h:1058
self_type & assign(IP4Range const &r, PAYLOAD &payload)
Definition IPRange.h:1066
PAYLOAD * _payload
Payload for _range.
Definition IPRange.h:975