This is an automated email from the ASF dual-hosted git repository.

bneradt pushed a commit to branch dev-1-0-14
in repository https://gitbox.apache.org/repos/asf/trafficserver-libswoc.git

commit 914c5c28946f14a079834a8eb70973855f948cf4
Author: Alan M. Carroll <[email protected]>
AuthorDate: Mon Mar 2 07:23:42 2020 -0600

    Better testing of network extraction.
---
 swoc++/include/swoc/swoc_ip.h | 930 ++++++++++++++++++++++++++----------------
 swoc++/src/swoc_ip.cc         |  42 ++
 unit_tests/test_ip.cc         | 283 +++++++++++--
 3 files changed, 861 insertions(+), 394 deletions(-)

diff --git a/swoc++/include/swoc/swoc_ip.h b/swoc++/include/swoc/swoc_ip.h
index 736a6e6..788c727 100644
--- a/swoc++/include/swoc/swoc_ip.h
+++ b/swoc++/include/swoc/swoc_ip.h
@@ -14,8 +14,7 @@
 #include <swoc/RBTree.h>
 #include <values.h>
 
-namespace swoc
-{
+namespace swoc {
 class IP4Addr;
 class IP6Addr;
 class IPAddr;
@@ -46,10 +45,12 @@ union IPEndpoint {
 
   /// Default construct invalid instance.
   IPEndpoint();
+
   /// Construct from the @a text representation of an address.
-  IPEndpoint(string_view const &text);
+  IPEndpoint(string_view const&text);
+
   // Construct from @a IPAddr
-  IPEndpoint(IPAddr const &addr);
+  IPEndpoint(IPAddr const&addr);
 
   /** Break a string in to IP address relevant tokens.
    *
@@ -62,7 +63,8 @@ union IPEndpoint {
    * Any of the out parameters can be @c nullptr in which case they are not 
updated.
    * This parses and discards the IPv6 brackets.
    */
-  static bool tokenize(string_view src, string_view *host = nullptr, 
string_view *port = nullptr, string_view *rest = nullptr);
+  static bool tokenize(string_view src, string_view *host = nullptr, 
string_view *port = nullptr
+                       , string_view *rest = nullptr);
 
   /** Parse a string for an IP address.
 
@@ -71,16 +73,16 @@ union IPEndpoint {
 
       @return @c true on success, @c false otherwise.
   */
-  bool parse(string_view const &str);
+  bool parse(string_view const&str);
 
   /// Invalidate a @c sockaddr.
   static void invalidate(sockaddr *addr);
 
   /// Invalidate this endpoint.
-  self_type &invalidate();
+  self_type&invalidate();
 
   /// Copy constructor.
-  self_type &operator=(self_type const &that);
+  self_type&operator=(self_type const&that);
 
   /** Copy (assign) the contents of @a src to @a dst.
    *
@@ -96,18 +98,20 @@ union IPEndpoint {
   /** Assign from a socket address.
       The entire address (all parts) are copied if the @a ip is valid.
   */
-  self_type &assign(sockaddr const *addr);
+  self_type&assign(sockaddr const *addr);
 
   /// Assign from an @a addr and @a port.
-  self_type &assign(IPAddr const &addr, in_port_t port = 0);
+  self_type&assign(IPAddr const&addr, in_port_t port = 0);
 
   /// Copy to @a sa.
-  const self_type &fill(sockaddr *addr) const;
+  const self_type&fill(sockaddr *addr) const;
 
   /// Test for valid IP address.
   bool is_valid() const;
+
   /// Test for IPv4.
   bool is_ip4() const;
+
   /// Test for IPv6.
   bool is_ip6() const;
 
@@ -123,28 +127,34 @@ union IPEndpoint {
   /// Set to be the ANY address for family @a family.
   /// @a family must be @c AF_INET or @c AF_INET6.
   /// @return This object.
-  self_type &set_to_any(int family);
+  self_type&set_to_any(int family);
 
   /// Set to be loopback address for family @a family.
   /// @a family must be @c AF_INET or @c AF_INET6.
   /// @return This object.
-  self_type &set_to_loopback(int family);
+  self_type&set_to_loopback(int family);
 
   /// Port in network order.
-  in_port_t &port();
+  in_port_t&port();
+
   /// Port in network order.
   in_port_t port() const;
+
   /// Port in host horder.
   in_port_t host_order_port() const;
+
   /// Port in network order from @a sockaddr.
-  static in_port_t &port(sockaddr *sa);
+  static in_port_t&port(sockaddr *sa);
+
   /// Port in network order from @a sockaddr.
   static in_port_t port(sockaddr const *sa);
+
   /// Port in host order directly from a @c sockaddr
   static in_port_t host_order_port(sockaddr const *sa);
 
   /// Automatic conversion to @c sockaddr.
   operator sockaddr *() { return &sa; }
+
   /// Automatic conversion to @c sockaddr.
   operator sockaddr const *() const { return &sa; }
 
@@ -158,6 +168,7 @@ union IPEndpoint {
 class IP4Addr {
   using self_type = IP4Addr; ///< Self reference type.
   friend class IP4Range;
+
 public:
   static constexpr size_t SIZE = sizeof(in_addr_t); ///< Size of IPv4 address 
in bytes.
   static constexpr size_t WIDTH = BITSPERBYTE * SIZE; ///< # of bits in an 
address.
@@ -170,44 +181,50 @@ public:
   /// @note Host order seems odd, but all of the standard network macro values 
such as @c INADDR_LOOPBACK
   /// are in host order.
   explicit constexpr IP4Addr(in_addr_t addr);
+
   /// Construct from @c sockaddr_in.
   explicit IP4Addr(sockaddr_in const *sa);
+
   /// Construct from text representation.
   /// If the @a text is invalid the result is an invalid instance.
-  IP4Addr(string_view const &text);
+  IP4Addr(string_view const&text);
+
   /// Construct from generic address @a addr.
-  explicit IP4Addr(IPAddr const& addr);
+  explicit IP4Addr(IPAddr const&addr);
 
   /// Assign from IPv4 raw address.
-  self_type &operator=(in_addr_t ip);
+  self_type&operator=(in_addr_t ip);
+
   /// Set to the address in @a addr.
-  self_type &operator=(sockaddr_in const *sa);
+  self_type&operator=(sockaddr_in const *sa);
 
   /// Increment address.
-  self_type &operator++();
+  self_type&operator++();
 
   /// Decrement address.
-  self_type &operator--();
+  self_type&operator--();
 
   /** Byte access.
    *
    * @param idx Byte index.
    * @return The byte at @a idx in the address.
    */
-  uint8_t operator [] (unsigned idx) const {
+  uint8_t operator[](unsigned idx) const {
     return reinterpret_cast<bytes const&>(_addr)[idx];
   }
 
   /// Apply @a mask to address, leaving the network portion.
-  self_type &operator&=(IPMask const& mask);
+  self_type&operator&=(IPMask const&mask);
+
   /// Apply @a mask to address, creating the broadcast address.
-  self_type &operator|=(IPMask const& mask);
+  self_type&operator|=(IPMask const&mask);
 
   /// Write this adddress and @a port to the sockaddr @a sa.
   sockaddr_in *fill(sockaddr_in *sa, in_port_t port = 0) const;
 
   /// @return The address in network order.
   in_addr_t network_order() const;
+
   /// @return The address in host order.
   in_addr_t host_order() const;
 
@@ -217,10 +234,10 @@ public:
 
       @return @c true on success, @c false otherwise.
   */
-  bool load(string_view const &text);
+  bool load(string_view const&text);
 
   /// Standard ternary compare.
-  int cmp(self_type const &that) const;
+  int cmp(self_type const&that) const;
 
   /// Get the IP address family.
   /// @return @c AF_INET
@@ -237,14 +254,14 @@ public:
    * @param n Number of bits to shift left.
    * @return @a this.
    */
-  self_type & operator <<= (unsigned n);
+  self_type&operator<<=(unsigned n);
 
   /** Right shift.
    *
    * @param n Number of bits to shift right.
    * @return @a this.
    */
-  self_type & operator >>= (unsigned n);
+  self_type&operator>>=(unsigned n);
 
   /** Bitwise AND.
    *
@@ -253,7 +270,7 @@ public:
    *
    * The bits in @a this are set to the bitwise AND of the corresponding bits 
in @a this and @a that.
    */
-  self_type & operator &= (self_type const& that);
+  self_type&operator&=(self_type const&that);
 
   /** Bitwise OR.
    *
@@ -262,7 +279,7 @@ public:
    *
    * The bits in @a this are set to the bitwise OR of the corresponding bits 
in @a this and @a that.
    */
-  self_type & operator |= (self_type const& that);
+  self_type&operator|=(self_type const&that);
 
   /** Convert between network and host order.
    *
@@ -278,10 +295,13 @@ protected:
   /// Access by bytes.
   using bytes = std::array<uint8_t, 4>;
 
-  friend bool operator==(self_type const &, self_type const &);
-  friend bool operator!=(self_type const &, self_type const &);
-  friend bool operator<(self_type const &, self_type const &);
-  friend bool operator<=(self_type const &, self_type const &);
+  friend bool operator==(self_type const&, self_type const&);
+
+  friend bool operator!=(self_type const&, self_type const&);
+
+  friend bool operator<(self_type const&, self_type const&);
+
+  friend bool operator<=(self_type const&, self_type const&);
 
   in_addr_t _addr = INADDR_ANY; ///< Address in host order.
 };
@@ -292,10 +312,12 @@ protected:
 class IP6Addr {
   using self_type = IP6Addr; ///< Self reference type.
   friend class IP6Range;
+
   friend class IPMask;
+
 public:
   static constexpr size_t WIDTH = 128; ///< Number of bits in the address.
-  static constexpr size_t SIZE  = WIDTH / BITSPERBYTE;    ///< Size of address 
in bytes.
+  static constexpr size_t SIZE = WIDTH / BITSPERBYTE;    ///< Size of address 
in bytes.
 
   using quad_type                      = uint16_t;            ///< Size of one 
segment of an IPv6 address.
   static constexpr size_t N_QUADS = SIZE / sizeof(quad_type); ///< # of quads 
in an IPv6 address.
@@ -334,34 +356,36 @@ public:
   static const self_type MAX;
 
   IP6Addr() = default; ///< Default constructor - 0 address.
-  IP6Addr(self_type const& that) = default;
+  IP6Addr(self_type const&that) = default;
 
   /// Construct using IPv6 @a addr.
-  explicit IP6Addr(in6_addr const & addr);
+  explicit IP6Addr(in6_addr const&addr);
+
   /// Construct from @c sockaddr_in.
   explicit IP6Addr(sockaddr_in6 const *addr) {
     *this = addr;
   }
+
   /// Construct from text representation.
   /// If the @a text is invalid the result is an invalid instance.
-  IP6Addr(string_view const& text);
+  IP6Addr(string_view const&text);
 
   /// Construct from generic @a addr.
-  IP6Addr(IPAddr const& addr);
+  IP6Addr(IPAddr const&addr);
 
   /** Left shift.
    *
    * @param n Number of bits to shift left.
    * @return @a this.
    */
-  self_type & operator <<= (unsigned n);
+  self_type&operator<<=(unsigned n);
 
   /** Right shift.
    *
    * @param n Number of bits to shift right.
    * @return @a this.
    */
-  self_type & operator >>= (unsigned n);
+  self_type&operator>>=(unsigned n);
 
   /** Bitwise AND.
    *
@@ -370,7 +394,7 @@ public:
    *
    * The bits in @a this are set to the bitwise AND of the corresponding bits 
in @a this and @a that.
    */
-  self_type & operator &= (self_type const& that);
+  self_type&operator&=(self_type const&that);
 
   /** Bitwise OR.
    *
@@ -379,24 +403,25 @@ public:
    *
    * The bits in @a this are set to the bitwise OR of the corresponding bits 
in @a this and @a that.
    */
-  self_type & operator |= (self_type const& that);
+  self_type&operator|=(self_type const&that);
 
   /// Increment address.
-  self_type &operator++();
+  self_type&operator++();
 
   /// Decrement address.
-  self_type &operator--();
+  self_type&operator--();
 
   /// Assign from IPv6 raw address.
-  self_type &operator=(in6_addr const& ip);
+  self_type&operator=(in6_addr const&ip);
+
   /// Set to the address in @a addr.
-  self_type &operator=(sockaddr_in6 const *addr);
+  self_type&operator=(sockaddr_in6 const *addr);
 
   /// Write to @c sockaddr using network order and @a port.
   sockaddr *copy_to(sockaddr *sa, in_port_t port = 0) const;
 
   /// Copy address to @a addr in network order.
-  in6_addr & copy_to(in6_addr & addr) const;
+  in6_addr&copy_to(in6_addr&addr) const;
 
   /// Return the address in network order.
   in6_addr network_order() const;
@@ -408,10 +433,10 @@ public:
 
       @return @c true on success, @c false otherwise.
   */
-  bool load(string_view const &str);
+  bool load(string_view const&str);
 
   /// Generic compare.
-  int cmp(self_type const &that) const;
+  int cmp(self_type const&that) const;
 
   /// Get the address family.
   /// @return The address family.
@@ -423,26 +448,31 @@ public:
   /// Test for loopback
   bool is_multicast() const { return IN6_IS_ADDR_MULTICAST(_addr._raw.data()); 
}
 
-  self_type & clear() {
+  self_type&clear() {
     _addr._store[0] = _addr._store[1] = 0;
     return *this;
   }
 
-  self_type & operator &= (IPMask const& mask);
-  self_type & operator |= (IPMask const& mask);
+  self_type&operator&=(IPMask const&mask);
+
+  self_type&operator|=(IPMask const&mask);
+
+  static void reorder(in6_addr&dst, raw_type const&src);
 
-  static void reorder(in6_addr & dst, raw_type const & src);
-  static void reorder(raw_type & dst, in6_addr const& src);
+  static void reorder(raw_type&dst, in6_addr const&src);
 
 protected:
-  friend bool operator==(self_type const &, self_type const &);
-  friend bool operator!=(self_type const &, self_type const &);
-  friend bool operator<(self_type const &, self_type const &);
-  friend bool operator<=(self_type const &, self_type const &);
+  friend bool operator==(self_type const&, self_type const&);
+
+  friend bool operator!=(self_type const&, self_type const&);
+
+  friend bool operator<(self_type const&, self_type const&);
+
+  friend bool operator<=(self_type const&, self_type const&);
 
   /// Type for digging around inside the address, with the various forms of 
access.
   union {
-    word_store_type _store = {0 }; ///< 0 is MSW, 1 is LSW.
+    word_store_type _store = {0}; ///< 0 is MSW, 1 is LSW.
     quad_store_type _quad; ///< By quad.
     raw_type _raw; ///< By byte.
   } _addr;
@@ -452,7 +482,7 @@ protected:
 
   /// Index of quads in @a _addr._quad.
   /// This converts from the position in the text format to the quads in the 
binary format.
-  static constexpr std::array<unsigned, N_QUADS> QUAD_IDX = { 3,2,1,0,7,6,5,4 
};
+  static constexpr std::array<unsigned, N_QUADS> QUAD_IDX = {3, 2, 1, 0, 7, 6, 
5, 4};
 
   static void reorder(unsigned char dst[WORD_SIZE], unsigned char const 
src[WORD_SIZE]);
 
@@ -463,94 +493,115 @@ protected:
    */
   IP6Addr(word_store_type::value_type msw, word_store_type::value_type lsw) : 
_addr{msw, lsw} {}
 
-  friend IP6Addr operator & (IP6Addr const& addr, IPMask const& mask);
-  friend IP6Addr operator | (IP6Addr const& addr, IPMask const& mask);
+  friend IP6Addr operator&(IP6Addr const&addr, IPMask const&mask);
+
+  friend IP6Addr operator|(IP6Addr const&addr, IPMask const&mask);
 };
 
 /** Storage for an IP address.
  */
 class IPAddr {
   friend class IPRange;
+
   using self_type = IPAddr; ///< Self reference type.
 public:
   IPAddr() = default; ///< Default constructor - invalid result.
-  IPAddr(self_type const& that) = default; ///< Copy constructor.
+  IPAddr(self_type const&that) = default; ///< Copy constructor.
 
   /// Construct using IPv4 @a addr.
   explicit IPAddr(in_addr_t addr);
+
   /// Construct using an IPv4 @a addr
-  IPAddr(IP4Addr const &addr) : _family(AF_INET), _addr{addr} {}
+  IPAddr(IP4Addr const&addr) : _family(AF_INET), _addr{addr} {}
+
   /// Construct using IPv6 @a addr.
-  explicit IPAddr(in6_addr const &addr);
+  explicit IPAddr(in6_addr const&addr);
+
   /// construct using an IPv6 @a addr
-  IPAddr(IP6Addr const &addr) : _family(AF_INET6), _addr{addr} {}
+  IPAddr(IP6Addr const&addr) : _family(AF_INET6), _addr{addr} {}
+
   /// Construct from @c sockaddr.
   explicit IPAddr(sockaddr const *addr);
+
   /// Construct from @c IPEndpoint.
-  explicit IPAddr(IPEndpoint const &addr);
+  explicit IPAddr(IPEndpoint const&addr);
+
   /// Construct from text representation.
   /// If the @a text is invalid the result is an invalid instance.
-  explicit IPAddr(string_view const& text);
+  explicit IPAddr(string_view const&text);
 
   /// Set to the address in @a addr.
-  self_type &assign(sockaddr const *addr);
+  self_type&assign(sockaddr const *addr);
+
   /// Set to the address in @a addr.
-  self_type &assign(sockaddr_in const *addr);
+  self_type&assign(sockaddr_in const *addr);
+
   /// Set to the address in @a addr.
-  self_type &assign(sockaddr_in6 const *addr);
+  self_type&assign(sockaddr_in6 const *addr);
+
   /// Set to the address in @a addr.
-  self_type &assign(in_addr_t addr);
+  self_type&assign(in_addr_t addr);
+
   /// Set to address in @a addr.
-  self_type &assign(in6_addr const &addr);
+  self_type&assign(in6_addr const&addr);
 
   /// Assign from end point.
-  self_type &operator=(IPEndpoint const &ip);
+  self_type&operator=(IPEndpoint const&ip);
+
   /// Assign from IPv4 raw address.
-  self_type &operator=(in_addr_t ip);
+  self_type&operator=(in_addr_t ip);
+
   /// Assign from IPv6 raw address.
-  self_type &operator=(in6_addr const &ip);
+  self_type&operator=(in6_addr const&ip);
+
   /// Assign from @c sockaddr
-  self_type &operator=(sockaddr const *addr);
+  self_type&operator=(sockaddr const *addr);
+
+  self_type&operator&=(IPMask const&mask);
 
-  self_type &operator&=(IPMask const& mask);
-  self_type &operator|=(IPMask const& mask);
+  self_type&operator|=(IPMask const&mask);
 
   /** Parse a string and load the result in @a this.
    *
    * @param text Text to parse.
    * @return  @c true on success, @c false otherwise.
    */
-  bool load(string_view const &text);
+  bool load(string_view const&text);
 
   /// Generic compare.
-  int cmp(self_type const &that) const;
+  int cmp(self_type const&that) const;
 
   /// Test for same address family.
   /// @c return @c true if @a that is the same address family as @a this.
-  bool isCompatibleWith(self_type const &that);
+  bool isCompatibleWith(self_type const&that);
 
   /// Get the address family.
   /// @return The address family.
   sa_family_t family() const;
+
   /// Test for IPv4.
   bool is_ip4() const;
+
   /// Test for IPv6.
   bool is_ip6() const;
 
   in_addr_t network_ip4() const;
+
   in6_addr network_ip6() const;
 
   explicit operator IP4Addr const&() const { return _addr._ip4; }
-  explicit operator IP4Addr &() { return _addr._ip4; }
+
+  explicit operator IP4Addr&() { return _addr._ip4; }
 
   explicit operator IP6Addr const&() const { return _addr._ip6; }
-  explicit operator IP6Addr &() { return _addr._ip6; }
+
+  explicit operator IP6Addr&() { return _addr._ip6; }
 
   /// Test for validity.
   bool is_valid() const;
 
   /// Make invalid.
-  self_type &invalidate();
+  self_type&invalidate();
 
   /// Test for multicast
   bool is_multicast() const;
@@ -562,7 +613,8 @@ public:
   static self_type const INVALID;
 
 protected:
-  friend bool operator==(self_type const &, self_type const &);
+  friend bool operator==(self_type const&, self_type const&);
+
   friend IP4Addr;
   friend IP6Addr;
 
@@ -574,11 +626,14 @@ protected:
     uint64_t _u64[IP6Addr::SIZE / sizeof(uint64_t)]; ///< As 64 bit chunks.
 
     constexpr raw_addr_type();
+
     raw_addr_type(in_addr_t addr) : _ip4(addr) {}
-    raw_addr_type(in6_addr const& addr) : _ip6(addr) {}
 
-    raw_addr_type(IP4Addr const& addr) : _ip4(addr) {}
-    raw_addr_type(IP6Addr const& addr) : _ip6(addr) {}
+    raw_addr_type(in6_addr const&addr) : _ip6(addr) {}
+
+    raw_addr_type(IP4Addr const&addr) : _ip4(addr) {}
+
+    raw_addr_type(IP6Addr const&addr) : _ip6(addr) {}
   } _addr;
 
   sa_family_t _family{AF_UNSPEC}; ///< Protocol family.
@@ -591,46 +646,59 @@ protected:
 class IPMask {
   using self_type = IPMask;  ///< Self reference type.
   friend class IP4Addr;
+
   friend class IP6Addr;
 
 public:
   using raw_type  = uint8_t; ///< Storage for mask width.
 
   IPMask() = default;
+
   explicit IPMask(raw_type count);
 
   /// @return @c true if the mask is valid, @c false if not.
   bool is_valid() const;
 
-  bool load(string_view const& text);
+  /** Parse mask from @a text.
+   *
+   * @param text A number in string format.
+   * @return @a true if a valid CIDR value, @c false if not.
+   */
+  bool load(string_view const&text);
 
   /** Copmute a mask for the network at @a addr.
    * @param addr Lower bound of network.
    * @return The width of the largest network starting at @a addr.
    */
-  static self_type mask_for(IPAddr const& addr);
+  static self_type mask_for(IPAddr const&addr);
 
   /** Copmute a mask for the network at @a addr.
    * @param addr Lower bound of network.
    * @return A mask with the width of the largest network starting at @a addr.
    */
-  static self_type mask_for(IP4Addr const& addr);
+  static self_type mask_for(IP4Addr const&addr);
 
   /** Copmute a mask for the network at @a addr.
    * @param addr Lower bound of network.
    * @return A mask with the width of the largest network starting at @a addr.
    */
-  static self_type mask_for(IP6Addr const& addr);
+  static self_type mask_for(IP6Addr const&addr);
+
+  /// Force @a this to an invalid state.
+  self_type&clear() {
+    _cidr = INVALID;
+    return *this;
+  }
 
   /// The width of the mask.
   raw_type width() const;
 
-  self_type & operator<<= (raw_type n) {
+  self_type&operator<<=(raw_type n) {
     _cidr -= n;
     return *this;
   }
 
-  self_type & operator>>= (raw_type n) {
+  self_type&operator>>=(raw_type n) {
     _cidr += n;
     return *this;
   }
@@ -676,11 +744,11 @@ public:
   IP4Range() = default;
 
   /// Construct from an network expressed as @a addr and @a mask.
-  IP4Range(IP4Addr const& addr, IPMask const& mask);
+  IP4Range(IP4Addr const&addr, IPMask const&mask);
 
   /// Construct from super type.
   /// @internal Why do I have to do this, even though the super type 
constructors are inherited?
-  IP4Range(super_type const& r) : super_type(r) {}
+  IP4Range(super_type const&r) : super_type(r) {}
 
   /** Construct range from @a text.
    *
@@ -690,7 +758,7 @@ public:
    * This results in a zero address if @a text is not a valid string. If this 
should be checked,
    * use @c load.
    */
-  IP4Range(string_view const& text);
+  IP4Range(string_view const&text);
 
   /** Set @a this range.
    *
@@ -698,7 +766,7 @@ public:
    * @param mask CIDR mask to compute maximum adddress from @a addr.
    * @return @a this
    */
-  self_type & assign(IP4Addr const& addr, IPMask const& mask);
+  self_type&assign(IP4Addr const&addr, IPMask const&mask);
 
   /** Assign to this range from text.
    *
@@ -741,9 +809,10 @@ public:
   using range_type = IP4Range; ///< Import base range type.
 
   /// Construct from @a range.
-  explicit NetSource(range_type const& range);
+  explicit NetSource(range_type const&range);
+
   /// Copy constructor.
-  NetSource(self_type const& that) = default;
+  NetSource(self_type const&that) = default;
 
   /// This class acts as a container and an iterator.
   using iterator = self_type;
@@ -754,27 +823,30 @@ public:
   iterator end() const; ///< Past last network.
 
   /// @return The current network.
-  IP4Net operator * () const;
+  IP4Net operator*() const;
+
   /// Access @a this as if it were an @c IP4Net.
-  self_type * operator -> ();
+  self_type *operator->();
 
   /// Iterator support.
   /// @areturn The current network address.
-  IP4Addr const& addr() const;
+  IP4Addr const&addr() const;
+
   /// Iterator support.
   /// @return The current network mask.
   IPMask mask() const;
 
   /// Move to next network.
-  self_type & operator++();
+  self_type&operator++();
+
   /// Move to next network.
   self_type operator++(int);
 
   /// Equality.
-  bool operator == (self_type const& that);
+  bool operator==(self_type const&that);
 
   /// Inequality.
-  bool operator != (self_type const& that);
+  bool operator!=(self_type const&that);
 
 protected:
   IP4Range _range; ///< Remaining range.
@@ -783,7 +855,9 @@ protected:
   IPMask::raw_type _cidr = IP4Addr::WIDTH; ///< Current CIDR value.
 
   void search_wider();
+
   void search_narrower();
+
   bool is_valid(IP4Addr mask);
 };
 
@@ -796,7 +870,7 @@ public:
 
   /// Construct from super type.
   /// @internal Why do I have to do this, even though the super type 
constructors are inherited?
-  IP6Range(super_type const& r) : super_type(r) {}
+  IP6Range(super_type const&r) : super_type(r) {}
 
   /** Construct range from @a text.
    *
@@ -806,7 +880,7 @@ public:
    * This results in a zero address if @a text is not a valid string. If this 
should be checked,
    * use @c load.
    */
-  IP6Range(string_view const& text);
+  IP6Range(string_view const&text);
 
   /** Set @a this range.
    *
@@ -814,7 +888,7 @@ public:
    * @param mask CIDR mask to compute maximum adddress from @a addr.
    * @return @a this
    */
-  self_type & assign(IP6Addr const& addr, IPMask const& mask);
+  self_type&assign(IP6Addr const&addr, IPMask const&mask);
 
   /** Assign to this range from text.
    *
@@ -857,9 +931,10 @@ public:
   using range_type = IP6Range; ///< Import base range type.
 
   /// Construct from @a range.
-  explicit NetSource(range_type const& range);
+  explicit NetSource(range_type const&range);
+
   /// Copy constructor.
-  NetSource(self_type const& that) = default;
+  NetSource(self_type const&that) = default;
 
   /// This class acts as a container and an iterator.
   using iterator = self_type;
@@ -870,35 +945,40 @@ public:
   iterator end() const; ///< Past last network.
 
   /// @return The current network.
-  IP6Net operator * () const;
+  IP6Net operator*() const;
+
   /// Access @a this as if it were an @c IP6Net.
-  self_type * operator -> ();
+  self_type *operator->();
 
   /// Iterator support.
   /// @areturn The current network address.
-  IP6Addr const& addr() const;
+  IP6Addr const&addr() const;
+
   /// Iterator support.
   /// @return The current network mask.
   IPMask mask() const;
 
   /// Move to next network.
-  self_type & operator++();
+  self_type&operator++();
+
   /// Move to next network.
   self_type operator++(int);
 
   /// Equality.
-  bool operator == (self_type const& that);
+  bool operator==(self_type const&that);
 
   /// Inequality.
-  bool operator != (self_type const& that);
+  bool operator!=(self_type const&that);
 
 protected:
   IP6Range _range; ///< Remaining range.
-  IPMask _mask { IP6Addr::WIDTH } ; ///< Current CIDR value.
+  IPMask _mask{IP6Addr::WIDTH}; ///< Current CIDR value.
 
   void search_wider();
+
   void search_narrower();
-  bool is_valid(IPMask const& mask);
+
+  bool is_valid(IPMask const&mask);
 };
 
 class IPRange {
@@ -906,24 +986,27 @@ class IPRange {
 public:
   /// Default constructor - construct invalid range.
   IPRange() = default;
+
   /// Construct from an IPv4 @a range.
-  IPRange(IP4Range const& range);
+  IPRange(IP4Range const&range);
+
   /// Construct from an IPv6 @a range.
-  IPRange(IP6Range const& range);
+  IPRange(IP6Range const&range);
+
   /** Construct from a string format.
    *
    * @param text Text form of range.
    *
    * The string can be a single address, two addresses separated by a dash '-' 
or a CIDR network.
    */
-  IPRange(string_view const& text);
+  IPRange(string_view const&text);
 
   /** Check if @a this range is the IP address @a family.
    *
    * @param family IP address family.
    * @return @c true if this is @a family, @c false if not.
    */
-  bool is(sa_family_t family) const ;
+  bool is(sa_family_t family) const;
 
   /** Load the range from @a text.
    *
@@ -933,19 +1016,23 @@ public:
    * A successful parse means @a this was loaded with the specified range. If 
not the range is
    * marked as invalid.
    */
-  bool load(std::string_view const& text);
+  bool load(std::string_view const&text);
 
   /// @return The minimum address in the range.
   IPAddr min() const;
+
   /// @return The maximum address in the range.
   IPAddr max() const;
 
   bool empty() const;
 
-  operator IP4Range & () { return _range._ip4; }
-  operator IP6Range & () { return _range._ip6; }
-  operator IP4Range const & () const { return _range._ip4; }
-  operator IP6Range const & () const { return _range._ip6; }
+  operator IP4Range&() { return _range._ip4; }
+
+  operator IP6Range&() { return _range._ip6; }
+
+  operator IP4Range const&() const { return _range._ip4; }
+
+  operator IP6Range const&() const { return _range._ip6; }
 
 protected:
   /** Range container.
@@ -961,9 +1048,9 @@ protected:
     std::monostate _nil; ///< Make constructor easier to implement.
     IP4Range _ip4; ///< IPv4 range.
     IP6Range _ip6; ///< IPv6 range.
-  } _range { std::monostate{} };
+  } _range{std::monostate{}};
   /// Family of @a _range.
-  sa_family_t _family { AF_UNSPEC };
+  sa_family_t _family{AF_UNSPEC};
 };
 
 /// An IPv4 network.
@@ -971,7 +1058,7 @@ class IP4Net {
   using self_type = IP4Net; ///< Self reference type.
 public:
   IP4Net() = default; ///< Construct invalid network.
-  IP4Net(self_type const& that) = default; ///< Copy constructor.
+  IP4Net(self_type const&that) = default; ///< Copy constructor.
 
   /** Construct from @a addr and @a mask.
    *
@@ -984,6 +1071,17 @@ public:
    */
   IP4Net(IP4Addr addr, IPMask mask);
 
+  IP4Net(swoc::TextView text) {
+    this->load(text);
+  }
+
+  /** Parse network as @a text.
+   *
+   * @param text String describing the network in CIDR format.
+   * @return @c true if a valid string, @c false if not.
+   */
+  bool load(swoc::TextView text);
+
   /// @return @c true if the network is valid, @c false if not.
   bool is_valid() const;
 
@@ -994,11 +1092,31 @@ public:
   IP4Addr upper_bound() const;
 
   /// @return The mask for the network.
-  IPMask const& mask() const;
+  IPMask const&mask() const;
 
   /// @return A range that exactly covers the network.
   IP4Range as_range() const;
 
+  /** Assign an @a addr and @a mask to @a this.
+   *
+   * @param addr Network addres.
+   * @param mask Network mask.
+   * @return @a this.
+   */
+  self_type&assign(IP4Addr const&addr, IPMask const&mask);
+
+  /// Reset network to invalid state.
+  self_type&clear() {
+    _mask.clear();
+    return *this;
+  }
+
+  /// Equality.
+  bool operator==(self_type const&that) const;
+
+  /// Inequality
+  bool operator!=(self_type const&that) const;
+
 protected:
   IP4Addr _addr; ///< Network address (also lower_bound).
   IPMask _mask; ///< Network mask.
@@ -1008,7 +1126,7 @@ class IP6Net {
   using self_type = IP6Net; ///< Self reference type.
 public:
   IP6Net() = default; ///< Construct invalid network.
-  IP6Net(self_type const& that) = default; ///< Copy constructor.
+  IP6Net(self_type const&that) = default; ///< Copy constructor.
 
   /** Construct from @a addr and @a mask.
    *
@@ -1021,6 +1139,13 @@ public:
    */
   IP6Net(IP6Addr addr, IPMask mask);
 
+  /** Parse network as @a text.
+   *
+   * @param text String describing the network in CIDR format.
+   * @return @c true if a valid string, @c false if not.
+   */
+  bool load(swoc::TextView text);
+
   /// @return @c true if the network is valid, @c false if not.
   bool is_valid() const;
 
@@ -1031,11 +1156,31 @@ public:
   IP6Addr upper_bound() const;
 
   /// @return The mask for the network.
-  IPMask const& mask() const;
+  IPMask const&mask() const;
 
   /// @return A range that exactly covers the network.
   IP6Range as_range() const;
 
+  /** Assign an @a addr and @a mask to @a this.
+   *
+   * @param addr Network addres.
+   * @param mask Network mask.
+   * @return @a this.
+   */
+  self_type&assign(IP6Addr const&addr, IPMask const&mask);
+
+  /// Reset network to invalid state.
+  self_type&clear() {
+    _mask.clear();
+    return *this;
+  }
+
+  /// Equality.
+  bool operator==(self_type const&that) const;
+
+  /// Inequality
+  bool operator!=(self_type const&that) const;
+
 protected:
   IP6Addr _addr; ///< Network address (also lower_bound).
   IPMask _mask; ///< Network mask.
@@ -1050,29 +1195,32 @@ public:
   static constexpr char SEPARATOR = '/'; // the character used between the 
address and mask
 
   IPNet() = default;
-  IPNet(const IPAddr &addr, const IPMask &mask);
 
-  operator IPAddr const &() const;
-  operator IPMask const &() const;
+  IPNet(const IPAddr&addr, const IPMask&mask);
 
-  IPAddr const &addr() const;
+  operator IPAddr const&() const;
 
-  IPMask const &mask() const;
+  operator IPMask const&() const;
+
+  IPAddr const&addr() const;
+
+  IPMask const&mask() const;
 
   IPAddr lower_bound() const;
+
   IPAddr upper_bound() const;
 
   IPRange as_range() const;
 
-  bool contains(IPAddr const &addr) const;
+  bool contains(IPAddr const&addr) const;
 
   // computes this is strict subset of other
-  bool is_subnet_of(self_type const &that);
+  bool is_subnet_of(self_type const&that);
 
   // Check if there are any addresses in both @a this and @a that.
-  bool intersects(self_type const &that);
+  bool intersects(self_type const&that);
 
-  self_type &assign(IPAddr const &addr, IPMask const &mask);
+  self_type&assign(IPAddr const&addr, IPMask const&mask);
 
 protected:
   IPAddr _addr;
@@ -1093,7 +1241,7 @@ protected:
  * - Cheap to copy.
  * - Comparable via the equality and inequality operators.
  */
-template <typename PAYLOAD> class IPSpace {
+template<typename PAYLOAD> class IPSpace {
   using self_type = IPSpace;
   using IP4Space  = DiscreteSpace<IP4Addr, PAYLOAD>;
   using IP6Space  = DiscreteSpace<IP6Addr, PAYLOAD>;
@@ -1112,7 +1260,7 @@ public:
    *
    * All addresses in @a r are set to have the @a payload.
    */
-  self_type & mark(IPRange const &range, PAYLOAD const &payload);
+  self_type&mark(IPRange const&range, PAYLOAD const&payload);
 
   /** Fill the @a range with @a payload.
    *
@@ -1122,7 +1270,7 @@ public:
    *
    * Addresses in @a range are set to have @a payload if the address does not 
already have a payload.
    */
-  self_type & fill(IPRange const& range, PAYLOAD const& payload);
+  self_type&fill(IPRange const&range, PAYLOAD const&payload);
 
   /** Blend @a color in to the @a range.
    *
@@ -1143,17 +1291,17 @@ public:
    * @c PAYLOAD @a p, @a p is updated by invoking <tt>blender(p, color)</tt>, 
with the expectation
    * that @a p will be updated in place.
    */
-  template < typename F , typename U = PAYLOAD >
-  self_type & blend(IPRange const& range, U const& color, F && blender);
+  template<typename F, typename U = PAYLOAD>
+  self_type&blend(IPRange const&range, U const&color, F&&blender);
 
-  template < typename F , typename U = PAYLOAD >
-  self_type & blend(IP4Range const& range, U const& color, F && blender) {
+  template<typename F, typename U = PAYLOAD>
+  self_type&blend(IP4Range const&range, U const&color, F&&blender) {
     _ip4.blend(range, color, blender);
     return *this;
   }
 
-  template < typename F , typename U = PAYLOAD >
-  self_type & blend(IP6Range const& range, U const& color, F && blender) {
+  template<typename F, typename U = PAYLOAD>
+  self_type&blend(IP6Range const&range, U const&color, F&&blender) {
     _ip6.blend(range, color, blender);
     return *this;
   }
@@ -1163,7 +1311,7 @@ public:
    * @param addr Address to find.
    * @return The payload if any, @c nullptr if the address is not in the space.
    */
-  PAYLOAD *find(IP4Addr const &addr) {
+  PAYLOAD *find(IP4Addr const&addr) {
     return _ip4.find(addr);
   }
 
@@ -1172,7 +1320,7 @@ public:
    * @param addr Address to find.
    * @return The payload if any, @c nullptr if the address is not in the space.
    */
-  PAYLOAD *find(IP6Addr const &addr) {
+  PAYLOAD *find(IP6Addr const&addr) {
     return _ip6.find(addr);
   }
 
@@ -1181,7 +1329,7 @@ public:
    * @param addr Address to find.
    * @return The payload if any, @c nullptr if the address is not in the space.
    */
-  PAYLOAD *find(IPAddr const &addr) {
+  PAYLOAD *find(IPAddr const&addr) {
     if (addr.is_ip4()) {
       return _ip4.find(IP4Addr{addr});
     } else if (addr.is_ip6()) {
@@ -1205,12 +1353,13 @@ public:
   class const_iterator {
     using self_type = const_iterator; ///< Self reference type.
     friend class IPSpace;
+
   public:
     using value_type = std::tuple<IPRange const, PAYLOAD const&>; /// Import 
for API compliance.
     // STL algorithm compliance.
     using iterator_category = std::bidirectional_iterator_tag;
     using pointer           = value_type *;
-    using reference         = value_type &;
+    using reference         = value_type&;
     using difference_type   = int;
 
     /// Default constructor.
@@ -1219,12 +1368,12 @@ public:
     /// Pre-increment.
     /// Move to the next element in the list.
     /// @return The iterator.
-    self_type &operator++();
+    self_type&operator++();
 
     /// Pre-decrement.
     /// Move to the previous element in the list.
     /// @return The iterator.
-    self_type &operator--();
+    self_type&operator--();
 
     /// Post-increment.
     /// Move to the next element in the list.
@@ -1238,17 +1387,17 @@ public:
 
     /// Dereference.
     /// @return A reference to the referent.
-    value_type const& operator*() const;
+    value_type const&operator*() const;
 
     /// Dereference.
     /// @return A pointer to the referent.
-    value_type const* operator->() const;
+    value_type const *operator->() const;
 
     /// Equality
-    bool operator==(self_type const &that) const;
+    bool operator==(self_type const&that) const;
 
     /// Inequality
-    bool operator!=(self_type const &that) const;
+    bool operator!=(self_type const&that) const;
 
   protected:
     // These are stored non-const to make implementing @c iterator easier. 
This class provides the
@@ -1259,11 +1408,11 @@ public:
     typename IP4Space::iterator _iter_4; ///< IPv4 sub-space iterator.
     typename IP6Space::iterator _iter_6; ///< IPv6 sub-space iterator.
     /// Current value.
-    value_type _value { IPRange{}, *null_payload };
+    value_type _value{IPRange{}, *null_payload};
 
     /// Dummy payload.
     /// @internal Used to initialize @c value_type for invalid iterators.
-    static constexpr PAYLOAD *  null_payload = nullptr;
+    static constexpr PAYLOAD *null_payload = nullptr;
 
     /** Internal constructor.
      *
@@ -1272,7 +1421,8 @@ public:
      *
      * In practice, both iterators should be either the beginning or ending 
iterator for the subspace.
      */
-    const_iterator(typename IP4Space::iterator const& iter4, typename 
IP6Space::iterator const& iter6);
+    const_iterator(typename IP4Space::iterator const&iter4
+                   , typename IP6Space::iterator const&iter6);
   };
 
   /** Iterator.
@@ -1284,13 +1434,15 @@ public:
   class iterator : public const_iterator {
     using self_type = iterator;
     using super_type = const_iterator;
+
     friend class IPSpace;
+
   public:
   public:
     /// Value type of iteration.
     using value_type = std::tuple<IPRange const, PAYLOAD&>;
     using pointer           = value_type *;
-    using reference         = value_type &;
+    using reference         = value_type&;
 
     /// Default constructor.
     iterator() = default;
@@ -1298,30 +1450,38 @@ public:
     /// Pre-increment.
     /// Move to the next element in the list.
     /// @return The iterator.
-    self_type &operator++();
+    self_type&operator++();
 
     /// Pre-decrement.
     /// Move to the previous element in the list.
     /// @return The iterator.
-    self_type &operator--();
+    self_type&operator--();
 
     /// Post-increment.
     /// Move to the next element in the list.
     /// @return The iterator value before the increment.
-    self_type operator++(int) { self_type zret{*this}; ++*this; return zret; }
+    self_type operator++(int) {
+      self_type zret{*this};
+      ++*this;
+      return zret;
+    }
 
     /// Post-decrement.
     /// Move to the previous element in the list.
     /// @return The iterator value before the decrement.
-    self_type operator--(int) { self_type zret{*this}; --*this; return zret; }
+    self_type operator--(int) {
+      self_type zret{*this};
+      --*this;
+      return zret;
+    }
 
     /// Dereference.
     /// @return A reference to the referent.
-    value_type const& operator*() const;
+    value_type const&operator*() const;
 
     /// Dereference.
     /// @return A pointer to the referent.
-    value_type const* operator->() const;
+    value_type const *operator->() const;
 
   protected:
     using super_type::super_type; /// Inherit supertype constructors.
@@ -1329,10 +1489,12 @@ public:
 
   /// @return A constant iterator to the first element.
   const_iterator begin() const;
+
   /// @return A constent iterator past the last element.
   const_iterator end() const;
 
   iterator begin() { return iterator{_ip4.begin(), _ip6.begin()}; }
+
   iterator end() { return iterator{_ip4.end(), _ip6.end()}; }
 
 protected:
@@ -1341,15 +1503,18 @@ protected:
 };
 
 template<typename PAYLOAD>
-IPSpace<PAYLOAD>::const_iterator::const_iterator(typename IP4Space::iterator 
const& iter4, typename IP6Space::iterator const& iter6) : _iter_4(iter4), 
_iter_6(iter6) {
+IPSpace<PAYLOAD>::const_iterator::const_iterator(typename IP4Space::iterator 
const&iter4
+                                                 , typename IP6Space::iterator 
const&iter6)
+    : _iter_4(iter4), _iter_6(iter6) {
   if (_iter_4.has_next()) {
     new(&_value) value_type{_iter_4->range(), _iter_4->payload()};
   } else if (_iter_6.has_next()) {
     new(&_value) value_type{_iter_6->range(), _iter_6->payload()};
   }
 }
+
 template<typename PAYLOAD>
-auto IPSpace<PAYLOAD>::const_iterator::operator++() -> self_type & {
+auto IPSpace<PAYLOAD>::const_iterator::operator++() -> self_type& {
   bool incr_p = false;
   if (_iter_4.has_next()) {
     ++_iter_4;
@@ -1366,7 +1531,7 @@ auto IPSpace<PAYLOAD>::const_iterator::operator++() -> 
self_type & {
       return *this;
     }
   }
-  new (&_value) value_type{IPRange{}, *null_payload};
+  new(&_value) value_type{IPRange{}, *null_payload};
   return *this;
 }
 
@@ -1378,10 +1543,10 @@ auto IPSpace<PAYLOAD>::const_iterator::operator++(int) 
-> self_type {
 }
 
 template<typename PAYLOAD>
-auto IPSpace<PAYLOAD>::const_iterator::operator--() -> self_type & {
+auto IPSpace<PAYLOAD>::const_iterator::operator--() -> self_type& {
   if (_iter_6.has_prev()) {
     --_iter_6;
-    new (&_value) value_type{_iter_6->range(), _iter_6->payload()};
+    new(&_value) value_type{_iter_6->range(), _iter_6->payload()};
     return *this;
   }
   if (_iter_4.has_prev()) {
@@ -1389,7 +1554,7 @@ auto IPSpace<PAYLOAD>::const_iterator::operator--() -> 
self_type & {
     new(&_value) value_type{_iter_4->range(), _iter_4->payload()};
     return *this;
   }
-  new (&_value) value_type{IPRange{}, *null_payload};
+  new(&_value) value_type{IPRange{}, *null_payload};
   return *this;
 }
 
@@ -1416,19 +1581,19 @@ auto IPSpace<PAYLOAD>::const_iterator::operator->() 
const -> value_type const *
 
 template<typename PAYLOAD>
 bool
-IPSpace<PAYLOAD>::const_iterator::operator==(self_type const& that) const {
+IPSpace<PAYLOAD>::const_iterator::operator==(self_type const&that) const {
   return _iter_4 == that._iter_4 && _iter_6 == that._iter_6;
 }
 
 template<typename PAYLOAD>
 bool
-IPSpace<PAYLOAD>::const_iterator::operator!=(self_type const& that) const {
+IPSpace<PAYLOAD>::const_iterator::operator!=(self_type const&that) const {
   return _iter_4 != that._iter_4 || _iter_6 != that._iter_6;
 }
 
 template<typename PAYLOAD>
-auto IPSpace<PAYLOAD>::iterator::operator->() const -> value_type const* {
-  return static_cast<value_type*>(&super_type::_value);
+auto IPSpace<PAYLOAD>::iterator::operator->() const -> value_type const * {
+  return static_cast<value_type *>(&super_type::_value);
 }
 
 template<typename PAYLOAD>
@@ -1437,13 +1602,13 @@ auto IPSpace<PAYLOAD>::iterator::operator*() const -> 
value_type const& {
 }
 
 template<typename PAYLOAD>
-auto IPSpace<PAYLOAD>::iterator::operator++() -> self_type & {
+auto IPSpace<PAYLOAD>::iterator::operator++() -> self_type& {
   this->super_type::operator++();
   return *this;
 }
 
 template<typename PAYLOAD>
-auto IPSpace<PAYLOAD>::iterator::operator--() -> self_type & {
+auto IPSpace<PAYLOAD>::iterator::operator--() -> self_type& {
   this->super_type::operator--();
   return *this;
 }
@@ -1455,40 +1620,40 @@ inline constexpr IPAddr::raw_addr_type::raw_addr_type() 
: _ip4(INADDR_ANY) {}
 
 inline IPAddr::IPAddr(in_addr_t addr) : _family(AF_INET), _addr(addr) {}
 
-inline IPAddr::IPAddr(in6_addr const &addr) : _family(AF_INET6), _addr(addr) {}
+inline IPAddr::IPAddr(in6_addr const&addr) : _family(AF_INET6), _addr(addr) {}
 
 inline IPAddr::IPAddr(sockaddr const *addr) {
   this->assign(addr);
 }
 
-inline IPAddr::IPAddr(IPEndpoint const &addr) {
+inline IPAddr::IPAddr(IPEndpoint const&addr) {
   this->assign(&addr.sa);
 }
 
-inline IPAddr::IPAddr(string_view const& text) {
+inline IPAddr::IPAddr(string_view const&text) {
   this->load(text);
 }
 
-inline IPAddr &
+inline IPAddr&
 IPAddr::operator=(in_addr_t addr) {
-  _family    = AF_INET;
+  _family = AF_INET;
   _addr._ip4 = addr;
   return *this;
 }
 
-inline IPAddr &
-IPAddr::operator=(in6_addr const &addr) {
-  _family    = AF_INET6;
+inline IPAddr&
+IPAddr::operator=(in6_addr const&addr) {
+  _family = AF_INET6;
   _addr._ip6 = addr;
   return *this;
 }
 
-inline IPAddr &
-IPAddr::operator=(IPEndpoint const &addr) {
+inline IPAddr&
+IPAddr::operator=(IPEndpoint const&addr) {
   return this->assign(&addr.sa);
 }
 
-inline IPAddr &
+inline IPAddr&
 IPAddr::operator=(sockaddr const *addr) {
   return this->assign(addr);
 }
@@ -1509,56 +1674,53 @@ IPAddr::is_ip6() const {
 }
 
 inline bool
-IPAddr::isCompatibleWith(self_type const &that) {
+IPAddr::isCompatibleWith(self_type const&that) {
   return this->is_valid() && _family == that._family;
 }
 
 inline bool
 IPAddr::is_loopback() const {
-  return (AF_INET == _family && 0x7F == _addr._octet[0]) || (AF_INET6 == 
_family && IN6_IS_ADDR_LOOPBACK(&_addr._ip6));
+  return (AF_INET == _family && 0x7F == _addr._octet[0]) ||
+         (AF_INET6 == _family && IN6_IS_ADDR_LOOPBACK(&_addr._ip6));
 }
 
 inline bool
-operator==(IPAddr const &lhs, IPAddr const &rhs) {
-  if (lhs._family != rhs._family)
+operator==(IPAddr const&lhs, IPAddr const&rhs) {
+  if (lhs._family != rhs._family) {
     return false;
-  switch (lhs._family)
-  {
-  case AF_INET:
-    return lhs._addr._ip4 == rhs._addr._ip4;
-  case AF_INET6:
-    return 0 == memcmp(&lhs._addr._ip6, &rhs._addr._ip6, IP6Addr::SIZE);
-  case AF_UNSPEC:
-    return true;
-  default:
-    break;
+  }
+  switch (lhs._family) {
+    case AF_INET:return lhs._addr._ip4 == rhs._addr._ip4;
+    case AF_INET6:return 0 == memcmp(&lhs._addr._ip6, &rhs._addr._ip6, 
IP6Addr::SIZE);
+    case AF_UNSPEC:return true;
+    default:break;
   }
   return false;
 }
 
 inline bool
-operator!=(IPAddr const &lhs, IPAddr const &rhs) {
+operator!=(IPAddr const&lhs, IPAddr const&rhs) {
   return !(lhs == rhs);
 }
 
-inline IPAddr &
+inline IPAddr&
 IPAddr::assign(in_addr_t addr) {
-  _family    = AF_INET;
+  _family = AF_INET;
   _addr._ip4 = addr;
   return *this;
 }
 
-inline IPAddr &
-IPAddr::assign(in6_addr const &addr) {
-  _family    = AF_INET6;
+inline IPAddr&
+IPAddr::assign(in6_addr const&addr) {
+  _family = AF_INET6;
   _addr._ip6 = addr;
   return *this;
 }
 
-inline IPAddr &
+inline IPAddr&
 IPAddr::assign(sockaddr_in const *addr) {
   if (addr) {
-    _family    = AF_INET;
+    _family = AF_INET;
     _addr._ip4 = addr;
   } else {
     _family = AF_UNSPEC;
@@ -1566,10 +1728,10 @@ IPAddr::assign(sockaddr_in const *addr) {
   return *this;
 }
 
-inline IPAddr &
+inline IPAddr&
 IPAddr::assign(sockaddr_in6 const *addr) {
   if (addr) {
-    _family    = AF_INET6;
+    _family = AF_INET6;
     _addr._ip6 = addr->sin6_addr;
   } else {
     _family = AF_UNSPEC;
@@ -1582,60 +1744,67 @@ IPAddr::is_valid() const {
   return _family == AF_INET || _family == AF_INET6;
 }
 
-inline IPAddr &
+inline IPAddr&
 IPAddr::invalidate() {
   _family = AF_UNSPEC;
   return *this;
 }
 
 // Associated operators.
-bool operator==(IPAddr const &lhs, sockaddr const *rhs);
+bool operator==(IPAddr const&lhs, sockaddr const *rhs);
+
 inline bool
-operator==(sockaddr const *lhs, IPAddr const &rhs) {
+operator==(sockaddr const *lhs, IPAddr const&rhs) {
   return rhs == lhs;
 }
+
 inline bool
-operator!=(IPAddr const &lhs, sockaddr const *rhs) {
+operator!=(IPAddr const&lhs, sockaddr const *rhs) {
   return !(lhs == rhs);
 }
+
 inline bool
-operator!=(sockaddr const *lhs, IPAddr const &rhs) {
+operator!=(sockaddr const *lhs, IPAddr const&rhs) {
   return !(rhs == lhs);
 }
+
 inline bool
-operator==(IPAddr const &lhs, IPEndpoint const &rhs) {
+operator==(IPAddr const&lhs, IPEndpoint const&rhs) {
   return lhs == &rhs.sa;
 }
+
 inline bool
-operator==(IPEndpoint const &lhs, IPAddr const &rhs) {
+operator==(IPEndpoint const&lhs, IPAddr const&rhs) {
   return &lhs.sa == rhs;
 }
+
 inline bool
-operator!=(IPAddr const &lhs, IPEndpoint const &rhs) {
+operator!=(IPAddr const&lhs, IPEndpoint const&rhs) {
   return !(lhs == &rhs.sa);
 }
+
 inline bool
-operator!=(IPEndpoint const &lhs, IPAddr const &rhs) {
+operator!=(IPEndpoint const&lhs, IPAddr const&rhs) {
   return !(rhs == &lhs.sa);
 }
 
 inline bool
-operator<(IPAddr const &lhs, IPAddr const &rhs) {
+operator<(IPAddr const&lhs, IPAddr const&rhs) {
   return -1 == lhs.cmp(rhs);
 }
 
 inline bool
-operator>=(IPAddr const &lhs, IPAddr const &rhs) {
+operator>=(IPAddr const&lhs, IPAddr const&rhs) {
   return lhs.cmp(rhs) >= 0;
 }
 
 inline bool
-operator>(IPAddr const &lhs, IPAddr const &rhs) {
+operator>(IPAddr const&lhs, IPAddr const&rhs) {
   return 1 == lhs.cmp(rhs);
 }
 
 inline bool
-operator<=(IPAddr const &lhs, IPAddr const &rhs) {
+operator<=(IPAddr const&lhs, IPAddr const&rhs) {
   return lhs.cmp(rhs) <= 0;
 }
 
@@ -1655,11 +1824,11 @@ inline IPEndpoint::IPEndpoint() {
   sa.sa_family = AF_UNSPEC;
 }
 
-inline IPEndpoint::IPEndpoint(IPAddr const &addr) {
+inline IPEndpoint::IPEndpoint(IPAddr const&addr) {
   this->assign(addr);
 }
 
-inline IPEndpoint &
+inline IPEndpoint&
 IPEndpoint::invalidate() {
   sa.sa_family = AF_UNSPEC;
   return *this;
@@ -1675,19 +1844,19 @@ IPEndpoint::is_valid() const {
   return sa.sa_family == AF_INET || sa.sa_family == AF_INET6;
 }
 
-inline IPEndpoint &
-IPEndpoint::operator=(self_type const &that) {
+inline IPEndpoint&
+IPEndpoint::operator=(self_type const&that) {
   self_type::assign(&sa, &that.sa);
   return *this;
 }
 
-inline IPEndpoint &
+inline IPEndpoint&
 IPEndpoint::assign(sockaddr const *src) {
   self_type::assign(&sa, src);
   return *this;
 }
 
-inline IPEndpoint const &
+inline IPEndpoint const&
 IPEndpoint::fill(sockaddr *addr) const {
   self_type::assign(addr, &sa);
   return *this;
@@ -1708,7 +1877,7 @@ IPEndpoint::family() const {
   return sa.sa_family;
 }
 
-inline in_port_t &
+inline in_port_t&
 IPEndpoint::port() {
   return self_type::port(&sa);
 }
@@ -1723,14 +1892,11 @@ IPEndpoint::host_order_port() const {
   return ntohs(this->port());
 }
 
-inline in_port_t &
+inline in_port_t&
 IPEndpoint::port(sockaddr *sa) {
-  switch (sa->sa_family)
-  {
-  case AF_INET:
-    return reinterpret_cast<sockaddr_in *>(sa)->sin_port;
-  case AF_INET6:
-    return reinterpret_cast<sockaddr_in6 *>(sa)->sin6_port;
+  switch (sa->sa_family) {
+    case AF_INET:return reinterpret_cast<sockaddr_in *>(sa)->sin_port;
+    case AF_INET6:return reinterpret_cast<sockaddr_in6 *>(sa)->sin6_port;
   }
   // Force a failure upstream by returning a null reference.
   return *static_cast<in_port_t *>(nullptr);
@@ -1750,41 +1916,42 @@ IPEndpoint::host_order_port(sockaddr const *sa) {
 
 inline constexpr IP4Addr::IP4Addr(in_addr_t addr) : _addr(addr) {}
 
-inline IP4Addr::IP4Addr(std::string_view const& text) {
-  if (! this->load(text)) {
+inline IP4Addr::IP4Addr(std::string_view const&text) {
+  if (!this->load(text)) {
     _addr = INADDR_ANY;
   }
 }
 
-inline IP4Addr::IP4Addr(IPAddr const& addr) : _addr(addr._family == AF_INET ? 
addr._addr._ip4._addr : INADDR_ANY) {}
+inline IP4Addr::IP4Addr(IPAddr const&addr) : _addr(
+    addr._family == AF_INET ? addr._addr._ip4._addr : INADDR_ANY) {}
 
-inline IP4Addr& IP4Addr::operator<<=(unsigned n) {
+inline IP4Addr&IP4Addr::operator<<=(unsigned n) {
   _addr <<= n;
   return *this;
 }
 
-inline IP4Addr& IP4Addr::operator>>=(unsigned n) {
+inline IP4Addr&IP4Addr::operator>>=(unsigned n) {
   _addr >>= n;
   return *this;
 }
 
-inline IP4Addr& IP4Addr::operator&=(self_type const& that) {
+inline IP4Addr&IP4Addr::operator&=(self_type const&that) {
   _addr &= that._addr;
   return *this;
 }
 
-inline IP4Addr& IP4Addr::operator|=(self_type const& that) {
+inline IP4Addr&IP4Addr::operator|=(self_type const&that) {
   _addr |= that._addr;
   return *this;
 }
 
-inline IP4Addr &
+inline IP4Addr&
 IP4Addr::operator++() {
   ++_addr;
   return *this;
 }
 
-inline IP4Addr &
+inline IP4Addr&
 IP4Addr::operator--() {
   --_addr;
   return *this;
@@ -1799,64 +1966,65 @@ inline in_addr_t IP4Addr::host_order() const {
 }
 
 inline auto
-IP4Addr::operator=(in_addr_t ip) -> self_type & {
+IP4Addr::operator=(in_addr_t ip) -> self_type& {
   _addr = ntohl(ip);
   return *this;
 }
 
-inline bool operator == (IP4Addr const& lhs, IP4Addr const& rhs) {
+inline bool operator==(IP4Addr const&lhs, IP4Addr const&rhs) {
   return lhs._addr == rhs._addr;
 }
 
-inline bool operator != (IP4Addr const& lhs, IP4Addr const& rhs) {
+inline bool operator!=(IP4Addr const&lhs, IP4Addr const&rhs) {
   return lhs._addr != rhs._addr;
 }
 
-inline bool operator < (IP4Addr const& lhs, IP4Addr const& rhs) {
+inline bool operator<(IP4Addr const&lhs, IP4Addr const&rhs) {
   return lhs._addr < rhs._addr;
 }
 
-inline bool operator <= (IP4Addr const& lhs, IP4Addr const& rhs) {
+inline bool operator<=(IP4Addr const&lhs, IP4Addr const&rhs) {
   return lhs._addr <= rhs._addr;
 }
 
-inline bool operator > (IP4Addr const& lhs, IP4Addr const& rhs) {
+inline bool operator>(IP4Addr const&lhs, IP4Addr const&rhs) {
   return rhs < lhs;
 }
 
-inline bool operator >= (IP4Addr const& lhs, IP4Addr const& rhs) {
+inline bool operator>=(IP4Addr const&lhs, IP4Addr const&rhs) {
   return rhs <= lhs;
 }
 
-inline IP4Addr & IP4Addr::operator&=(IPMask const& mask) {
+inline IP4Addr&IP4Addr::operator&=(IPMask const&mask) {
   _addr &= mask.as_ip4()._addr;
   return *this;
 }
 
-inline IP4Addr & IP4Addr::operator|=(IPMask const& mask) {
+inline IP4Addr&IP4Addr::operator|=(IPMask const&mask) {
   _addr |= ~(mask.as_ip4()._addr);
   return *this;
 }
 
 constexpr in_addr_t IP4Addr::reorder(in_addr_t src) {
-  return ((src & 0xFF) << 24) | (((src >> 8) & 0xFF) << 16) | (((src >> 16) & 
0xFF) << 8) | ((src >> 24) & 0xFF);
+  return ((src & 0xFF) << 24) | (((src >> 8) & 0xFF) << 16) | (((src >> 16) & 
0xFF) << 8) |
+         ((src >> 24) & 0xFF);
 }
 
 // ---
 
-inline IP6Addr::IP6Addr(in6_addr const& addr) {
+inline IP6Addr::IP6Addr(in6_addr const&addr) {
   *this = addr;
 }
 
-inline IP6Addr::IP6Addr(std::string_view const& text) {
-  if (! this->load(text)) {
+inline IP6Addr::IP6Addr(std::string_view const&text) {
+  if (!this->load(text)) {
     this->clear();
   }
 }
 
-inline IP6Addr::IP6Addr(IPAddr const& addr) : _addr{addr._addr._ip6._addr} {}
+inline IP6Addr::IP6Addr(IPAddr const&addr) : _addr{addr._addr._ip6._addr} {}
 
-inline in6_addr& IP6Addr::copy_to(in6_addr & addr) const {
+inline in6_addr&IP6Addr::copy_to(in6_addr&addr) const {
   self_type::reorder(addr, _addr._raw);
   return addr;
 }
@@ -1866,19 +2034,19 @@ inline in6_addr IP6Addr::network_order() const {
   return this->copy_to(zret);
 }
 
-inline auto IP6Addr::operator = (in6_addr const& addr) -> self_type & {
+inline auto IP6Addr::operator=(in6_addr const&addr) -> self_type& {
   self_type::reorder(_addr._raw, addr);
   return *this;
 }
 
-inline auto IP6Addr::operator = (sockaddr_in6 const* addr) -> self_type & {
+inline auto IP6Addr::operator=(sockaddr_in6 const *addr) -> self_type& {
   if (addr) {
     return *this = addr->sin6_addr;
   }
   this->clear();
 }
 
-inline IP6Addr &
+inline IP6Addr&
 IP6Addr::operator++() {
   if (++(_addr._store[1]) == 0) {
     ++(_addr._store[0]);
@@ -1886,7 +2054,7 @@ IP6Addr::operator++() {
   return *this;
 }
 
-inline IP6Addr &
+inline IP6Addr&
 IP6Addr::operator--() {
   if (--(_addr._store[1]) == ~static_cast<uint64_t >(0)) {
     --(_addr._store[0]);
@@ -1895,48 +2063,50 @@ IP6Addr::operator--() {
 }
 
 inline void IP6Addr::reorder(unsigned char dst[WORD_SIZE], unsigned char const 
src[WORD_SIZE]) {
-  for (size_t idx = 0 ; idx < WORD_SIZE ; ++idx ) {
+  for (size_t idx = 0; idx < WORD_SIZE; ++idx) {
     dst[idx] = src[WORD_SIZE - (idx + 1)];
   }
 }
 
-inline bool operator == (IP6Addr const& lhs, IP6Addr const& rhs) {
+inline bool operator==(IP6Addr const&lhs, IP6Addr const&rhs) {
   return lhs._addr._store[0] == rhs._addr._store[0] &&
          lhs._addr._store[1] == rhs._addr._store[1];
 }
 
-inline bool operator != (IP6Addr const& lhs, IP6Addr const& rhs) {
+inline bool operator!=(IP6Addr const&lhs, IP6Addr const&rhs) {
   return lhs._addr._store[0] != rhs._addr._store[0] ||
          lhs._addr._store[1] != rhs._addr._store[1];
 }
 
-inline bool operator < (IP6Addr const& lhs, IP6Addr const& rhs) {
-  return lhs._addr._store[0] < rhs._addr._store[0] || (lhs._addr._store[0] == 
rhs._addr._store[0] && lhs._addr._store[1] < rhs._addr._store[1]);
+inline bool operator<(IP6Addr const&lhs, IP6Addr const&rhs) {
+  return lhs._addr._store[0] < rhs._addr._store[0] ||
+         (lhs._addr._store[0] == rhs._addr._store[0] && lhs._addr._store[1] < 
rhs._addr._store[1]);
 }
 
-inline bool operator > (IP6Addr const& lhs, IP6Addr const& rhs) {
+inline bool operator>(IP6Addr const&lhs, IP6Addr const&rhs) {
   return rhs < lhs;
 }
 
-inline bool operator <= (IP6Addr const& lhs, IP6Addr const& rhs) {
-  return lhs._addr._store[0] < rhs._addr._store[0] || (lhs._addr._store[0] == 
rhs._addr._store[0] && lhs._addr._store[1] <= rhs._addr._store[1]);
+inline bool operator<=(IP6Addr const&lhs, IP6Addr const&rhs) {
+  return lhs._addr._store[0] < rhs._addr._store[0] ||
+         (lhs._addr._store[0] == rhs._addr._store[0] && lhs._addr._store[1] <= 
rhs._addr._store[1]);
 }
 
-inline bool operator >= (IP6Addr const& lhs, IP6Addr const& rhs) {
+inline bool operator>=(IP6Addr const&lhs, IP6Addr const&rhs) {
   return rhs <= lhs;
 }
 
-inline IP6Addr& IP6Addr::operator &= (IPMask const& mask) {
+inline IP6Addr&IP6Addr::operator&=(IPMask const&mask) {
   if (mask._cidr < WORD_WIDTH) {
     _addr._store[MSW] &= (~word_type{0} << (WORD_WIDTH - mask._cidr));
     _addr._store[LSW] = 0;
-  } else if (mask._cidr < WIDTH){
+  } else if (mask._cidr < WIDTH) {
     _addr._store[LSW] &= (~word_type{0} << (2 * WORD_WIDTH - mask._cidr));
   }
   return *this;
 }
 
-inline IP6Addr& IP6Addr::operator |= (IPMask const& mask) {
+inline IP6Addr&IP6Addr::operator|=(IPMask const&mask) {
   if (mask._cidr < WORD_WIDTH) {
     _addr._store[MSW] |= (~word_type{0} >> mask._cidr);
     _addr._store[LSW] = ~word_type{0};
@@ -1948,65 +2118,65 @@ inline IP6Addr& IP6Addr::operator |= (IPMask const& 
mask) {
 
 // Disambiguating comparisons.
 
-inline bool operator == (IPAddr const& lhs, IP4Addr const& rhs) {
+inline bool operator==(IPAddr const&lhs, IP4Addr const&rhs) {
   return lhs.is_ip4() && static_cast<IP4Addr const&>(lhs) == rhs;
 }
 
-inline bool operator != (IPAddr const& lhs, IP4Addr const& rhs) {
-  return ! lhs.is_ip4() || static_cast<IP4Addr const&>(lhs) != rhs;
+inline bool operator!=(IPAddr const&lhs, IP4Addr const&rhs) {
+  return !lhs.is_ip4() || static_cast<IP4Addr const&>(lhs) != rhs;
 }
 
-inline bool operator == (IP4Addr const& lhs, IPAddr const& rhs) {
+inline bool operator==(IP4Addr const&lhs, IPAddr const&rhs) {
   return rhs.is_ip4() && lhs == static_cast<IP4Addr const&>(rhs);
 }
 
-inline bool operator != (IP4Addr const& lhs, IPAddr const& rhs) {
-  return ! rhs.is_ip4() || lhs != static_cast<IP4Addr const&>(rhs);
+inline bool operator!=(IP4Addr const&lhs, IPAddr const&rhs) {
+  return !rhs.is_ip4() || lhs != static_cast<IP4Addr const&>(rhs);
 }
 
-inline bool operator == (IPAddr const& lhs, IP6Addr const& rhs) {
+inline bool operator==(IPAddr const&lhs, IP6Addr const&rhs) {
   return lhs.is_ip6() && static_cast<IP6Addr const&>(lhs) == rhs;
 }
 
-inline bool operator != (IPAddr const& lhs, IP6Addr const& rhs) {
-  return ! lhs.is_ip6() || static_cast<IP6Addr const&>(lhs) != rhs;
+inline bool operator!=(IPAddr const&lhs, IP6Addr const&rhs) {
+  return !lhs.is_ip6() || static_cast<IP6Addr const&>(lhs) != rhs;
 }
 
-inline bool operator == (IP6Addr const& lhs, IPAddr const& rhs) {
+inline bool operator==(IP6Addr const&lhs, IPAddr const&rhs) {
   return rhs.is_ip6() && lhs == static_cast<IP6Addr const&>(rhs);
 }
 
-inline bool operator != (IP6Addr const& lhs, IPAddr const& rhs) {
-  return ! rhs.is_ip6() || lhs != static_cast<IP6Addr const&>(rhs);
+inline bool operator!=(IP6Addr const&lhs, IPAddr const&rhs) {
+  return !rhs.is_ip6() || lhs != static_cast<IP6Addr const&>(rhs);
 }
 
 // +++ IPRange +++
 
-inline IP4Range::IP4Range(string_view const& text) {
+inline IP4Range::IP4Range(string_view const&text) {
   this->load(text);
 }
 
-inline auto  IP4Range::networks() const -> NetSource {
-  return { NetSource{*this} };
+inline auto IP4Range::networks() const -> NetSource {
+  return {NetSource{*this}};
 }
 
-inline IP6Range::IP6Range(string_view const& text) {
+inline IP6Range::IP6Range(string_view const&text) {
   this->load(text);
 }
 
-inline auto  IP6Range::networks() const -> NetSource {
-  return { NetSource{*this} };
+inline auto IP6Range::networks() const -> NetSource {
+  return {NetSource{*this}};
 }
 
-inline IPRange::IPRange(IP4Range const& range) : _family(AF_INET) {
+inline IPRange::IPRange(IP4Range const&range) : _family(AF_INET) {
   _range._ip4 = range;
 }
 
-inline IPRange::IPRange(IP6Range const& range) : _family(AF_INET6) {
+inline IPRange::IPRange(IP6Range const&range) : _family(AF_INET6) {
   _range._ip6 = range;
 }
 
-inline IPRange::IPRange(string_view const& text) {
+inline IPRange::IPRange(string_view const&text) {
   this->load(text);
 }
 
@@ -2023,17 +2193,17 @@ inline auto IPMask::width() const -> raw_type {
 }
 
 inline bool
-operator==(IPMask const &lhs, IPMask const &rhs) {
+operator==(IPMask const&lhs, IPMask const&rhs) {
   return lhs.width() == rhs.width();
 }
 
 inline bool
-operator!=(IPMask const &lhs, IPMask const &rhs) {
+operator!=(IPMask const&lhs, IPMask const&rhs) {
   return lhs.width() != rhs.width();
 }
 
 inline bool
-operator<(IPMask const &lhs, IPMask const &rhs) {
+operator<(IPMask const&lhs, IPMask const&rhs) {
   return lhs.width() < rhs.width();
 }
 
@@ -2041,69 +2211,107 @@ inline IP4Addr IPMask::as_ip4() const {
   static constexpr auto MASK = ~in_addr_t{0};
   in_addr_t addr = MASK;
   if (_cidr < IP4Addr::WIDTH) {
-    addr <<=IP4Addr::WIDTH - _cidr;
+    addr <<= IP4Addr::WIDTH - _cidr;
   }
-  return IP4Addr{ addr };
+  return IP4Addr{addr};
 }
 
 // +++ mixed operators +++
 
-inline IP4Addr operator & (IP4Addr const& addr, IPMask const& mask) {
+inline IP4Addr operator&(IP4Addr const&addr, IPMask const&mask) {
   return IP4Addr{addr} &= mask;
 }
 
-inline IP4Addr operator | (IP4Addr const& addr, IPMask const& mask) {
-  return IP4Addr {addr} |= mask;
+inline IP4Addr operator|(IP4Addr const&addr, IPMask const&mask) {
+  return IP4Addr{addr} |= mask;
 }
 
-inline IP6Addr operator & (IP6Addr const& addr, IPMask const& mask) {
+inline IP6Addr operator&(IP6Addr const&addr, IPMask const&mask) {
   return IP6Addr{addr} &= mask;
 }
 
-inline IP6Addr operator | (IP6Addr const& addr, IPMask const& mask) {
+inline IP6Addr operator|(IP6Addr const&addr, IPMask const&mask) {
   return IP6Addr{addr} |= mask;
 }
 
-inline IPAddr operator & (IPAddr const& addr, IPMask const& mask) {
+inline IPAddr operator&(IPAddr const&addr, IPMask const&mask) {
   return IPAddr{addr} &= mask;
 }
 
-inline IPAddr operator | (IPAddr const& addr, IPMask const& mask) {
-  return IPAddr {addr} |= mask;
+inline IPAddr operator|(IPAddr const&addr, IPMask const&mask) {
+  return IPAddr{addr} |= mask;
 }
 
 // +++ IPNet +++
 
 inline IP4Net::IP4Net(swoc::IP4Addr addr, swoc::IPMask mask) : _addr(addr & 
mask), _mask(mask) {}
-inline IPMask const& IP4Net::mask() const { return _mask; }
+
+inline IPMask const&IP4Net::mask() const { return _mask; }
+
 inline bool IP4Net::is_valid() const { return _mask.is_valid(); }
+
 inline IP4Addr IP4Net::lower_bound() const { return _addr; }
+
 inline IP4Addr IP4Net::upper_bound() const { return _addr | _mask; }
-inline IP4Range IP4Net::as_range() const { return { this->lower_bound(), 
this->upper_bound()}; }
+
+inline IP4Range IP4Net::as_range() const { return {this->lower_bound(), 
this->upper_bound()}; }
+
+inline bool IP4Net::operator==(self_type const&that) const {
+  return _mask == that._mask && _addr == that._addr;
+}
+
+inline bool IP4Net::operator!=(self_type const&that) const {
+  return _mask != that._mask || _addr != that._addr;
+}
+
+inline IP4Net::self_type&IP4Net::assign(IP4Addr const&addr, IPMask const&mask) 
{
+  _addr = addr & mask;
+  _mask = mask;
+  return *this;
+}
 
 inline IP6Net::IP6Net(swoc::IP6Addr addr, swoc::IPMask mask) : _addr(addr & 
mask), _mask(mask) {}
-inline IPMask const& IP6Net::mask() const { return _mask; }
+
+inline IPMask const&IP6Net::mask() const { return _mask; }
+
 inline bool IP6Net::is_valid() const { return _mask.is_valid(); }
+
 inline IP6Addr IP6Net::lower_bound() const { return _addr; }
+
 inline IP6Addr IP6Net::upper_bound() const { return _addr | _mask; }
-inline IP6Range IP6Net::as_range() const { return { this->lower_bound(), 
this->upper_bound()}; }
 
-inline IPNet::IPNet(IPAddr const &addr, IPMask const &mask) : _addr(addr & 
mask), _mask(mask) {}
+inline IP6Range IP6Net::as_range() const { return {this->lower_bound(), 
this->upper_bound()}; }
 
-inline IPNet::operator IPAddr const &() const {
+inline bool IP6Net::operator==(self_type const&that) const {
+  return _mask == that._mask && _addr == that._addr;
+}
+
+inline bool IP6Net::operator!=(self_type const&that) const {
+  return _mask != that._mask || _addr != that._addr;
+}
+
+inline IP6Net::self_type&IP6Net::assign(IP6Addr const&addr, IPMask const&mask) 
{
+  _addr = addr & mask;
+  _mask = mask;
+  return *this;
+}
+
+inline IPNet::IPNet(IPAddr const&addr, IPMask const&mask) : _addr(addr & 
mask), _mask(mask) {}
+
+inline IPNet::operator IPAddr const&() const {
   return _addr;
 }
 
-inline IPNet::operator IPMask const &() const {
+inline IPNet::operator IPMask const&() const {
   return _mask;
 }
 
-inline IPAddr const &
+inline IPAddr const&
 IPNet::addr() const {
   return _addr;
 }
 
-inline IPMask const &
+inline IPMask const&
 IPNet::mask() const {
   return _mask;
 }
@@ -2131,18 +2339,19 @@ inline IP4Range::NetSource::iterator 
IP4Range::NetSource::end() const {
   return self_type{range_type{}};
 }
 
-inline IPMask IP4Range::NetSource::mask() const { return IPMask{ _cidr }; }
+inline IPMask IP4Range::NetSource::mask() const { return IPMask{_cidr}; }
 
 inline auto IP4Range::NetSource::operator->() -> self_type * { return this; }
 
-inline IP4Addr const& IP4Range::NetSource::addr() const { return _range.min(); 
}
+inline IP4Addr const&IP4Range::NetSource::addr() const { return _range.min(); }
 
-inline bool IP4Range::NetSource::operator==(IP4Range::NetSource::self_type 
const& that) {
-  return ((_cidr == that._cidr) && (_range == that._range)) || (_range.empty() 
&& that._range.empty());
+inline bool IP4Range::NetSource::operator==(IP4Range::NetSource::self_type 
const&that) {
+  return ((_cidr == that._cidr) && (_range == that._range)) ||
+         (_range.empty() && that._range.empty());
 }
 
 inline bool IP4Range::NetSource::operator!=(IP4Range::NetSource::self_type 
const&that) {
-  return ! (*this == that);
+  return !(*this == that);
 }
 
 inline IP6Range::NetSource::iterator IP6Range::NetSource::begin() const {
@@ -2159,22 +2368,24 @@ inline IP6Net IP6Range::NetSource::operator*() const {
 
 inline auto IP6Range::NetSource::operator->() -> self_type * { return this; }
 
-inline bool IP6Range::NetSource::is_valid(IPMask const& mask) {
+inline bool IP6Range::NetSource::is_valid(IPMask const&mask) {
   return ((_range.min() & mask) == _range.min()) &&
          ((_range.min() | mask) <= _range.max());
 }
 
-inline bool IP6Range::NetSource::operator==(IP6Range::NetSource::self_type 
const& that) {
-  return ((_mask == that._mask) && (_range == that._range)) || (_range.empty() 
&& that._range.empty());
+inline bool IP6Range::NetSource::operator==(IP6Range::NetSource::self_type 
const&that) {
+  return ((_mask == that._mask) && (_range == that._range)) ||
+         (_range.empty() && that._range.empty());
 }
 
 inline bool IP6Range::NetSource::operator!=(IP6Range::NetSource::self_type 
const&that) {
-  return ! (*this == that);
+  return !(*this == that);
 }
 
 // --- IPSpace
 
-template < typename PAYLOAD > auto IPSpace<PAYLOAD>::mark(IPRange const 
&range, PAYLOAD const &payload) -> self_type & {
+template<typename PAYLOAD>
+auto IPSpace<PAYLOAD>::mark(IPRange const&range, PAYLOAD const&payload) -> 
self_type& {
   if (range.is(AF_INET)) {
     _ip4.mark(range, payload);
   } else if (range.is(AF_INET6)) {
@@ -2183,7 +2394,8 @@ template < typename PAYLOAD > auto 
IPSpace<PAYLOAD>::mark(IPRange const &range,
   return *this;
 }
 
-template < typename PAYLOAD > auto IPSpace<PAYLOAD>::fill(IPRange const 
&range, PAYLOAD const &payload) -> self_type & {
+template<typename PAYLOAD>
+auto IPSpace<PAYLOAD>::fill(IPRange const&range, PAYLOAD const&payload) -> 
self_type& {
   if (range.is(AF_INET6)) {
     _ip6.fill(range, payload);
   } else if (range.is(AF_INET)) {
@@ -2193,8 +2405,8 @@ template < typename PAYLOAD > auto 
IPSpace<PAYLOAD>::fill(IPRange const &range,
 }
 
 template<typename PAYLOAD>
-template<typename F, typename U >
-auto IPSpace<PAYLOAD>::blend(IPRange const&range, U const&color, F&&blender) 
-> self_type & {
+template<typename F, typename U>
+auto IPSpace<PAYLOAD>::blend(IPRange const&range, U const&color, F&&blender) 
-> self_type& {
   if (range.is(AF_INET)) {
     _ip4.blend(range, color, blender);
   } else if (range.is(AF_INET6)) {
@@ -2211,13 +2423,13 @@ void IPSpace<PAYLOAD>::clear() {
 
 template<typename PAYLOAD>
 auto IPSpace<PAYLOAD>::begin() const -> const_iterator {
-  auto nc_this = const_cast<self_type*>(this);
+  auto nc_this = const_cast<self_type *>(this);
   return const_iterator(nc_this->_ip4.begin(), nc_this->_ip6.begin());
 }
 
 template<typename PAYLOAD>
 auto IPSpace<PAYLOAD>::end() const -> const_iterator {
-  auto nc_this = const_cast<self_type*>(this);
+  auto nc_this = const_cast<self_type *>(this);
   return const_iterator(nc_this->_ip4.end(), nc_this->_ip6.end());
 }
 
@@ -2225,34 +2437,36 @@ auto IPSpace<PAYLOAD>::end() const -> const_iterator {
 
 namespace std {
 
-template <> class tuple_size<swoc::IP4Net> : public 
std::integral_constant<size_t, 2> {};
+template<> class tuple_size<swoc::IP4Net> : public 
std::integral_constant<size_t, 2> {
+};
 
-template < size_t IDX > class tuple_element<IDX, swoc::IP4Net> {
+template<size_t IDX> class tuple_element<IDX, swoc::IP4Net> {
   static_assert("swoc::IP4Net tuple index out of range");
 };
 
-template <> class tuple_element<0, swoc::IP4Net> {
+template<> class tuple_element<0, swoc::IP4Net> {
 public:
   using type = swoc::IP4Addr;
 };
 
-template <> class tuple_element<1, swoc::IP4Net> {
+template<> class tuple_element<1, swoc::IP4Net> {
 public:
   using type = swoc::IPMask;
 };
 
-template <> class tuple_size<swoc::IP6Net> : public 
std::integral_constant<size_t, 2> {};
+template<> class tuple_size<swoc::IP6Net> : public 
std::integral_constant<size_t, 2> {
+};
 
-template < size_t IDX > class tuple_element<IDX, swoc::IP6Net> {
+template<size_t IDX> class tuple_element<IDX, swoc::IP6Net> {
   static_assert("swoc::IP6Net tuple index out of range");
 };
 
-template <> class tuple_element<0, swoc::IP6Net> {
+template<> class tuple_element<0, swoc::IP6Net> {
 public:
   using type = swoc::IP6Addr;
 };
 
-template <> class tuple_element<1, swoc::IP6Net> {
+template<> class tuple_element<1, swoc::IP6Net> {
 public:
   using type = swoc::IPMask;
 };
@@ -2261,8 +2475,8 @@ public:
 
 namespace swoc {
 
-template < size_t IDX > typename std::tuple_element<IDX, IP4Net>::type
-get(swoc::IP4Net const& net) {
+template<size_t IDX> typename std::tuple_element<IDX, IP4Net>::type
+get(swoc::IP4Net const&net) {
   if constexpr (IDX == 0) {
     return net.lower_bound();
   } else if constexpr (IDX == 1) {
@@ -2270,8 +2484,8 @@ get(swoc::IP4Net const& net) {
   }
 }
 
-template < size_t IDX > typename std::tuple_element<IDX, IP6Net>::type
-get(swoc::IP6Net const& net) {
+template<size_t IDX> typename std::tuple_element<IDX, IP6Net>::type
+get(swoc::IP6Net const&net) {
   if constexpr (IDX == 0) {
     return net.lower_bound();
   } else if constexpr (IDX == 1) {
diff --git a/swoc++/src/swoc_ip.cc b/swoc++/src/swoc_ip.cc
index 283b557..c53a0b0 100644
--- a/swoc++/src/swoc_ip.cc
+++ b/swoc++/src/swoc_ip.cc
@@ -618,6 +618,48 @@ IP6Addr IPMask::as_ip6() const {
   return { MASK, MASK };
 }
 
+// ++ IPNet ++
+
+bool IP4Net::load(TextView text) {
+  auto idx = text.find('/');
+  if (idx != text.npos) {
+    if (idx + 1 < text.size()) { // must have something past the separator or 
it's bogus.
+      IP4Addr addr;
+      if (addr.load(text.substr(0, idx))) { // load the address
+        IPMask mask;
+        text.remove_prefix(idx + 1); // drop address and separator.
+        if (mask.load(text)) {
+          this->assign(addr, mask);
+          return true;
+        }
+      }
+    }
+  }
+
+  this->clear();
+  return false;
+}
+
+bool IP6Net::load(TextView text) {
+  auto idx = text.find('/');
+  if (idx != text.npos) {
+    if (idx + 1 < text.size()) { // must have something past the separator or 
it's bogus.
+      IP6Addr addr;
+      if (addr.load(text.substr(0, idx))) { // load the address
+        IPMask mask;
+        text.remove_prefix(idx + 1); // drop address and separator.
+        if (mask.load(text)) {
+          this->assign(addr, mask);
+          return true;
+        }
+      }
+    }
+  }
+
+  this->clear();
+  return false;
+}
+
 // +++ IP4Range +++
 
 IP4Range::IP4Range(swoc::IP4Addr const&addr, swoc::IPMask const&mask) {
diff --git a/unit_tests/test_ip.cc b/unit_tests/test_ip.cc
index 711282b..286d590 100644
--- a/unit_tests/test_ip.cc
+++ b/unit_tests/test_ip.cc
@@ -28,6 +28,9 @@ using swoc::IP6Range;
 
 using swoc::IPAddr;
 using swoc::IPRange;
+
+using swoc::IPMask;
+
 using W = swoc::LocalBufferWriter<256>;
 
 TEST_CASE("Basic IP", "[libswoc][ip]") {
@@ -63,7 +66,7 @@ TEST_CASE("Basic IP", "[libswoc][ip]") {
     REQUIRE(s.rest == rest);
   }
 
-  IP4Addr alpha { "172.96.12.134"};
+  IP4Addr alpha{"172.96.12.134"};
   CHECK(alpha == IP4Addr{"172.96.12.134"});
   CHECK(alpha == IP4Addr{IPAddr{"172.96.12.134"}});
   CHECK(alpha == IPAddr{IPEndpoint{"172.96.12.134:80"}});
@@ -275,7 +278,8 @@ TEST_CASE("IP ranges and networks", 
"[libswoc][ip][net][range]") {
   swoc::IP4Range r_2{"1.1.2.0-1.1.2.97"};
   swoc::IP4Range r_3{"1.1.0.0-1.2.0.0"};
   swoc::IP4Range r_4{"10.33.45.19-10.33.45.76"};
-  swoc::IP6Range 
r_5{"2001:1f2d:c587:24c3:9128:3349:3cee:143-ffee:1f2d:c587:24c3:9128:3349:3cFF:FFFF"_tv};
+  swoc::IP6Range r_5{
+      
"2001:1f2d:c587:24c3:9128:3349:3cee:143-ffee:1f2d:c587:24c3:9128:3349:3cFF:FFFF"_tv};
 
   CHECK(true == r_0.empty());
   CHECK(false == r_1.empty());
@@ -288,11 +292,218 @@ TEST_CASE("IP ranges and networks", 
"[libswoc][ip][net][range]") {
   swoc::IP6Addr a_1{"2001:1f2d:c587:24c4::"};
   CHECK(a_1 == (a_1 & swoc::IPMask{62}));
 
-  for ( auto const& [ addr, mask ] : r_4.networks()) {
-    std::cout << W().print("{}/{}\n", addr, mask.width());
+  std::array<swoc::IP4Net, 7> r_4_nets =
+      {{
+           "10.33.45.19/32"_tv
+           , "10.33.45.20/30"_tv
+           , "10.33.45.24/29"_tv
+           , "10.33.45.32/27"_tv
+           , "10.33.45.64/29"_tv
+           , "10.33.45.72/30"_tv
+           , "10.33.45.76/32"_tv
+       }};
+  auto r4_net = r_4_nets.begin();
+  for (auto const&net : r_4.networks()) {
+    REQUIRE(r4_net != r_4_nets.end());
+    CHECK(*r4_net == net);
+    ++r4_net;
   }
-  for ( auto const& [ addr, mask ] : r_5.networks()) {
-    std::cout << W().print("{}/{}\n", addr, mask.width());
+
+  std::array<swoc::IP6Net, 130> r_5_nets =
+      {{
+           {IP6Addr{
+               "2001:1f2d:c587:24c3:9128:3349:3cee:143"}, IPMask{
+               128}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:3cee:144"}, IPMask{126}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:3cee:148"}, IPMask{125}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:3cee:150"}, IPMask{124}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:3cee:160"}, IPMask{123}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:3cee:180"}, IPMask{121}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:3cee:200"}, IPMask{119}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:3cee:400"}, IPMask{118}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:3cee:800"}, IPMask{117}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:3cee:1000"}, IPMask{116}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:3cee:2000"}, IPMask{115}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:3cee:4000"}, IPMask{114}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:3cee:8000"}, IPMask{113}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:3cef:0"}, IPMask{112}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:3cf0:0"}, IPMask{108}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:3d00:0"}, IPMask{104}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:3e00:0"}, IPMask{103}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:4000:0"}, IPMask{98}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3349:8000:0"}, IPMask{97}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:334a::"}, IPMask{95}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:334c::"}, IPMask{94}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3350::"}, IPMask{92}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3360::"}, IPMask{91}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3380::"}, IPMask{89}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3400::"}, IPMask{86}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:3800::"}, IPMask{85}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:4000::"}, IPMask{82}}
+           , {IP6Addr{
+              "2001:1f2d:c587:24c3:9128:8000::"}, IPMask{81}}
+           , {IP6Addr{"2001:1f2d:c587:24c3:9129::"}, IPMask{
+              80}}
+           , {IP6Addr{"2001:1f2d:c587:24c3:912a::"}, IPMask{
+              79}}
+           , {IP6Addr{"2001:1f2d:c587:24c3:912c::"}, IPMask{
+              78}}
+           , {IP6Addr{"2001:1f2d:c587:24c3:9130::"}, IPMask{
+              76}}
+           , {IP6Addr{"2001:1f2d:c587:24c3:9140::"}, IPMask{
+              74}}
+           , {IP6Addr{"2001:1f2d:c587:24c3:9180::"}, IPMask{
+              73}}
+           , {IP6Addr{"2001:1f2d:c587:24c3:9200::"}, IPMask{
+              71}}
+           , {IP6Addr{"2001:1f2d:c587:24c3:9400::"}, IPMask{
+              70}}
+           , {IP6Addr{"2001:1f2d:c587:24c3:9800::"}, IPMask{
+              69}}
+           , {IP6Addr{"2001:1f2d:c587:24c3:a000::"}, IPMask{
+              67}}
+           , {IP6Addr{"2001:1f2d:c587:24c3:c000::"}, IPMask{
+              66}}
+           , {IP6Addr{"2001:1f2d:c587:24c4::"}, IPMask{62}}
+           , {IP6Addr{"2001:1f2d:c587:24c8::"}, IPMask{61}}
+           , {IP6Addr{"2001:1f2d:c587:24d0::"}, IPMask{60}}
+           , {IP6Addr{"2001:1f2d:c587:24e0::"}, IPMask{59}}
+           , {IP6Addr{"2001:1f2d:c587:2500::"}, IPMask{56}}
+           , {IP6Addr{"2001:1f2d:c587:2600::"}, IPMask{55}}
+           , {IP6Addr{"2001:1f2d:c587:2800::"}, IPMask{53}}
+           , {IP6Addr{"2001:1f2d:c587:3000::"}, IPMask{52}}
+           , {IP6Addr{"2001:1f2d:c587:4000::"}, IPMask{50}}
+           , {IP6Addr{"2001:1f2d:c587:8000::"}, IPMask{49}}
+           , {IP6Addr{"2001:1f2d:c588::"}, IPMask{45}}
+           , {IP6Addr{"2001:1f2d:c590::"}, IPMask{44}}
+           , {IP6Addr{"2001:1f2d:c5a0::"}, IPMask{43}}
+           , {IP6Addr{"2001:1f2d:c5c0::"}, IPMask{42}}
+           , {IP6Addr{"2001:1f2d:c600::"}, IPMask{39}}
+           , {IP6Addr{"2001:1f2d:c800::"}, IPMask{37}}
+           , {IP6Addr{"2001:1f2d:d000::"}, IPMask{36}}
+           , {IP6Addr{"2001:1f2d:e000::"}, IPMask{35}}
+           , {IP6Addr{"2001:1f2e::"}, IPMask{31}}
+           , {IP6Addr{"2001:1f30::"}, IPMask{28}}
+           , {IP6Addr{"2001:1f40::"}, IPMask{26}}
+           , {IP6Addr{"2001:1f80::"}, IPMask{25}}
+           , {IP6Addr{"2001:2000::"}, IPMask{19}}
+           , {IP6Addr{"2001:4000::"}, IPMask{18}}
+           , {IP6Addr{"2001:8000::"}, IPMask{17}}
+           , {IP6Addr{"2002::"}, IPMask{15}}
+           , {IP6Addr{"2004::"}, IPMask{14}}
+           , {IP6Addr{"2008::"}, IPMask{13}}
+           , {IP6Addr{"2010::"}, IPMask{12}}
+           , {IP6Addr{"2020::"}, IPMask{11}}
+           , {IP6Addr{"2040::"}, IPMask{10}}
+           , {IP6Addr{"2080::"}, IPMask{9}}
+           , {IP6Addr{"2100::"}, IPMask{8}}
+           , {IP6Addr{"2200::"}, IPMask{7}}
+           , {IP6Addr{"2400::"}, IPMask{6}}
+           , {IP6Addr{"2800::"}, IPMask{5}}
+           , {IP6Addr{"3000::"}, IPMask{4}}
+           , {IP6Addr{"4000::"}, IPMask{2}}
+           , {IP6Addr{"8000::"}, IPMask{2}}
+           , {IP6Addr{"c000::"}, IPMask{3}}
+           , {IP6Addr{"e000::"}, IPMask{4}}
+           , {IP6Addr{"f000::"}, IPMask{5}}
+           , {IP6Addr{"f800::"}, IPMask{6}}
+           , {IP6Addr{"fc00::"}, IPMask{7}}
+           , {IP6Addr{"fe00::"}, IPMask{8}}
+           , {IP6Addr{"ff00::"}, IPMask{9}}
+           , {IP6Addr{"ff80::"}, IPMask{10}}
+           , {IP6Addr{"ffc0::"}, IPMask{11}}
+           , {IP6Addr{"ffe0::"}, IPMask{13}}
+           , {IP6Addr{"ffe8::"}, IPMask{14}}
+           , {IP6Addr{"ffec::"}, IPMask{15}}
+           , {IP6Addr{"ffee::"}, IPMask{20}}
+           , {IP6Addr{"ffee:1000::"}, IPMask{21}}
+           , {IP6Addr{"ffee:1800::"}, IPMask{22}}
+           , {IP6Addr{"ffee:1c00::"}, IPMask{23}}
+           , {IP6Addr{"ffee:1e00::"}, IPMask{24}}
+           , {IP6Addr{"ffee:1f00::"}, IPMask{27}}
+           , {IP6Addr{"ffee:1f20::"}, IPMask{29}}
+           , {IP6Addr{"ffee:1f28::"}, IPMask{30}}
+           , {IP6Addr{"ffee:1f2c::"}, IPMask{32}}
+           , {IP6Addr{"ffee:1f2d::"}, IPMask{33}}
+           , {IP6Addr{"ffee:1f2d:8000::"}, IPMask{34}}
+           , {IP6Addr{"ffee:1f2d:c000::"}, IPMask{38}}
+           , {IP6Addr{"ffee:1f2d:c400::"}, IPMask{40}}
+           , {IP6Addr{"ffee:1f2d:c500::"}, IPMask{41}}
+           , {IP6Addr{"ffee:1f2d:c580::"}, IPMask{46}}
+           , {IP6Addr{"ffee:1f2d:c584::"}, IPMask{47}}
+           , {IP6Addr{"ffee:1f2d:c586::"}, IPMask{48}}
+           , {IP6Addr{"ffee:1f2d:c587::"}, IPMask{51}}
+           , {IP6Addr{"ffee:1f2d:c587:2000::"}, IPMask{54}}
+           , {IP6Addr{"ffee:1f2d:c587:2400::"}, IPMask{57}}
+           , {IP6Addr{"ffee:1f2d:c587:2480::"}, IPMask{58}}
+           , {IP6Addr{"ffee:1f2d:c587:24c0::"}, IPMask{63}}
+           , {IP6Addr{"ffee:1f2d:c587:24c2::"}, IPMask{64}}
+           , {IP6Addr{"ffee:1f2d:c587:24c3::"}, IPMask{65}}
+           , {IP6Addr{"ffee:1f2d:c587:24c3:8000::"}, IPMask{
+              68}}
+           , {IP6Addr{"ffee:1f2d:c587:24c3:9000::"}, IPMask{
+              72}}
+           , {IP6Addr{"ffee:1f2d:c587:24c3:9100::"}, IPMask{
+              75}}
+           , {IP6Addr{"ffee:1f2d:c587:24c3:9120::"}, IPMask{
+              77}}
+           , {IP6Addr{"ffee:1f2d:c587:24c3:9128::"}, IPMask{
+              83}}
+           , {IP6Addr{
+              "ffee:1f2d:c587:24c3:9128:2000::"}, IPMask{84}}
+           , {IP6Addr{
+              "ffee:1f2d:c587:24c3:9128:3000::"}, IPMask{87}}
+           , {IP6Addr{
+              "ffee:1f2d:c587:24c3:9128:3200::"}, IPMask{88}}
+           , {IP6Addr{
+              "ffee:1f2d:c587:24c3:9128:3300::"}, IPMask{90}}
+           , {IP6Addr{
+              "ffee:1f2d:c587:24c3:9128:3340::"}, IPMask{93}}
+           , {IP6Addr{
+              "ffee:1f2d:c587:24c3:9128:3348::"}, IPMask{96}}
+           , {IP6Addr{
+              "ffee:1f2d:c587:24c3:9128:3349::"}, IPMask{99}}
+           , {IP6Addr{
+              "ffee:1f2d:c587:24c3:9128:3349:2000:0"}, IPMask{100}}
+           , {IP6Addr{
+              "ffee:1f2d:c587:24c3:9128:3349:3000:0"}, IPMask{101}}
+           , {IP6Addr{
+              "ffee:1f2d:c587:24c3:9128:3349:3800:0"}, IPMask{102}}
+           , {IP6Addr{
+              "ffee:1f2d:c587:24c3:9128:3349:3c00:0"}, IPMask{104}}
+       }};
+
+  auto r5_net = r_5_nets.begin();
+  for (auto const&[addr, mask] : r_5.networks()) {
+    REQUIRE(r5_net != r_5_nets.end());
+    CHECK(*r5_net == swoc::IP6Net{addr, mask});
+    ++r5_net;
   }
 }
 
@@ -368,15 +579,15 @@ TEST_CASE("IP Space Int", "[libswoc][ip][ipspace]") {
 
   std::array<std::tuple<TextView, int>, 9> ranges = {
       {
-          { "100.0.0.0-100.0.0.255",  0 }
-          , { "100.0.1.0-100.0.1.255",  1 }
-          , { "100.0.2.0-100.0.2.255",  2 }
-          , { "100.0.3.0-100.0.3.255",  3 }
-          , { "100.0.4.0-100.0.4.255",  4 }
-          , { "100.0.5.0-100.0.5.255",  5 }
-          , { "100.0.6.0-100.0.6.255",  6 }
-          , { "100.0.0.0-100.0.0.255",  31 }
-          , { "100.0.1.0-100.0.1.255",  30 }
+          {"100.0.0.0-100.0.0.255", 0}
+          , {"100.0.1.0-100.0.1.255", 1}
+          , {"100.0.2.0-100.0.2.255", 2}
+          , {"100.0.3.0-100.0.3.255", 3}
+          , {"100.0.4.0-100.0.4.255", 4}
+          , {"100.0.5.0-100.0.5.255", 5}
+          , {"100.0.6.0-100.0.6.255", 6}
+          , {"100.0.0.0-100.0.0.255", 31}
+          , {"100.0.1.0-100.0.1.255", 30}
       }};
 
   space.clear();
@@ -420,7 +631,7 @@ TEST_CASE("IPSpace bitset", "[libswoc][ipspace][bitset]") {
 TEST_CASE("IPSpace docJJ", "[libswoc][ipspace][docJJ]") {
   using PAYLOAD = std::bitset<32>;
   using Space = swoc::IPSpace<PAYLOAD>;
-  auto blender = [](PAYLOAD& lhs, PAYLOAD const& rhs) -> bool {
+  auto blender = [](PAYLOAD&lhs, PAYLOAD const&rhs) -> bool {
     lhs |= rhs;
     return true;
   };
@@ -434,26 +645,26 @@ TEST_CASE("IPSpace docJJ", "[libswoc][ipspace][docJJ]") {
 
   std::array<std::tuple<TextView, std::initializer_list<unsigned>>, 9> ranges 
= {
       {
-            { "100.0.0.0-100.0.0.255", { 0 } }
-          , { "100.0.1.0-100.0.1.255", { 1 } }
-          , { "100.0.2.0-100.0.2.255", { 2 } }
-          , { "100.0.3.0-100.0.3.255", { 3 } }
-          , { "100.0.4.0-100.0.4.255", { 4 } }
-          , { "100.0.5.0-100.0.5.255", { 5 } }
-          , { "100.0.6.0-100.0.6.255", { 6 } }
-          , { "100.0.0.0-100.0.0.255", { 31 } }
-          , { "100.0.1.0-100.0.1.255", { 30 } }
+          {"100.0.0.0-100.0.0.255", {0}}
+          , {"100.0.1.0-100.0.1.255", {1}}
+          , {"100.0.2.0-100.0.2.255", {2}}
+          , {"100.0.3.0-100.0.3.255", {3}}
+          , {"100.0.4.0-100.0.4.255", {4}}
+          , {"100.0.5.0-100.0.5.255", {5}}
+          , {"100.0.6.0-100.0.6.255", {6}}
+          , {"100.0.0.0-100.0.0.255", {31}}
+          , {"100.0.1.0-100.0.1.255", {30}}
       }};
 
   std::array<std::initializer_list<unsigned>, 7> results = {{
-        { 0, 31 }
-      , { 1, 30 }
-      , { 2 }
-      , { 3 }
-      , { 4 }
-      , { 5 }
-      , { 6 }
-  }};
+                                                                {0, 31}
+                                                                , {1, 30}
+                                                                , {2}
+                                                                , {3}
+                                                                , {4}
+                                                                , {5}
+                                                                , {6}
+                                                            }};
 
   Space space;
 
@@ -467,15 +678,15 @@ TEST_CASE("IPSpace docJJ", "[libswoc][ipspace][docJJ]") {
   unsigned idx;
 
   idx = 0;
-  for ( auto const& [ range, bits ] : space) {
+  for (auto const&[range, bits] : space) {
     REQUIRE(idx < results.size());
     CHECK(bits == make_bits(results[idx]));
     ++idx;
   }
 
   idx = results.size();
-  for ( auto spot = space.end() ; spot != space.begin() ; ) {
-    auto const& [ range, bits ] { *--spot };
+  for (auto spot = space.end(); spot != space.begin();) {
+    auto const&[range, bits]{*--spot};
     REQUIRE(idx > 0);
     --idx;
     CHECK(bits == make_bits(results[idx]));


Reply via email to