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

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

commit 3f35e4b8be14306d4e858b720aeed075e79c92d0
Author: Alan M. Carroll <[email protected]>
AuthorDate: Wed Dec 4 13:20:08 2019 -0600

    Documentation update for IP Networking.
---
 doc/Makefile                  |   4 +-
 doc/code/BW_Format.en.rst     |   4 +-
 doc/code/IPSpace.en.rst       | 127 ++++++++++++++++++++++++++++++++++++++++--
 doc/index.rst                 |   1 +
 swoc++/include/swoc/swoc_ip.h |  36 ++++++++++--
 5 files changed, 160 insertions(+), 12 deletions(-)

diff --git a/doc/Makefile b/doc/Makefile
index cde5d25..047a4dc 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -22,7 +22,8 @@ $(IMAGEDIR)/%.svg : $(UMLDIR)/%.uml
 
 help:
        @echo "Please use \`make <target>' where <target> is one of"
-       @echo "  html       to make standalone HTML files"
+       @echo "  html       to make standalone HTML files."
+       @echo "  publish    to build the documentation clean, ready to publish."
 
 uml:
        @if [ ! -d uml ] ; then mkdir uml; fi
@@ -38,6 +39,7 @@ html: static uml ext/local-config.py reference
 clean:
        -rm -rf html warn.log
        -rm -rf $(BUILDDIR)/doctrees $(BUILDDIR)/html $(BUILDDIR)/dirhtml 
$(BUILDDIR)/singlehtml
+       -rm -rf doxygen
 
 publish: clean doxygen html
 
diff --git a/doc/code/BW_Format.en.rst b/doc/code/BW_Format.en.rst
index 1d8ec08..712da59 100644
--- a/doc/code/BW_Format.en.rst
+++ b/doc/code/BW_Format.en.rst
@@ -489,8 +489,8 @@ Specific types
    :code:`#include <swoc/bwf_ip.h>`
 
    The IP address is printed. Fill is used to fill in address segments if 
provided, not to the
-   minimum width if specified. :class:`IpEndpoint` and :class:`IpAddr` are 
supported with the same
-   formatting. The formatting support in this case is extensive because of the 
commonality and
+   minimum width if specified. :libswoc:`IPEndpoint` and :libswoc:`IPAddr` are 
supported with the
+   same formatting. The formatting support in this case is extensive because 
of the commonality and
    importance of IP address data.
 
    Type overrides
diff --git a/doc/code/IPSpace.en.rst b/doc/code/IPSpace.en.rst
index 353a171..832d799 100644
--- a/doc/code/IPSpace.en.rst
+++ b/doc/code/IPSpace.en.rst
@@ -16,15 +16,18 @@
 .. default-domain:: cpp
 .. highlight:: cpp
 
-********
-IP Space
-********
+*************
+IP Networking
+*************
 
 Synopsis
 ********
 
 :code:`#include <swoc/swoc_ip.h>`
 
+Usage
+*****
+
 .. class:: IPEndpoint
 
    :libswoc:`Reference documentation <swoc::IPEndpoint>`.
@@ -32,8 +35,122 @@ Synopsis
 This library is for storing and manipulating IP addresses as data. It has no 
support for actual
 network operations.
 
-Usage
-*****
+IPAddr
+======
+
+The classes :libswoc:`swoc::IPAddr`, :libswoc:`swoc::IP4Addr`, and 
:libswoc:`swoc::IP6Addr` are used
+to hold IP addresses. :code:`IP4Addr` and :code:`IP6Addr` are family specific 
and hold
+(respectively) IPv4 and IPv6 addresses. :code:`IPAddr` acts as a union of 
these two types along with
+an IP family specifier that indicates the type of address contained. The type 
specific classes
+provide performance and storage benefits when the type of the address is known 
or forced, while
+:code:`IPAddr` provides a generic type useful for interfaces.
+
+These classes provide support for parsing and formatting IP addresses. The 
constructor can take
+a string and, if a valid address, will initialize the instance to that 
address. The downside is
+there is no indication of failure other than the instance initializing to the 
zero or "any"
+address. This can be reasonable in situations where those addresses are not 
valid either. However
+in general the :libswoc:`swoc::IPAddr::load` method should be used, which both 
initializes the
+instance and provides an indication of whether the input was valid.
+
+IPRange
+=======
+
+The classes :libswoc:`swoc::IPRange`, :libswoc:`swoc::IP4Range`, and 
:libswoc:`swoc::IP6Range` are
+used to hold ranges of IP addresses. :code:`IP4Range` and :code:`IP6Range` are 
family specific and
+hold (respectively) IPv4 and IPv6 addresses. :code:`IPAddr` acts as a union of 
these two types along
+with an IP family specifier that indicates the type of address contained. The 
type specific classes
+provide performance and storage benefits when the type of the address is known 
or forced, while
+:code:`IPRange` provides a generic type useful for interfaces. Note that an 
:code:`IPRange` holds a
+range of addresses of a single family, it can never hold a range that is of 
mixed families.
+
+These classes provide support for parsing and formatting ranges of IP 
adddresses. The parsing logic
+accepts three forms of a range. In all cases the lower and upper limits of the 
range must be the
+same IP address family.
+
+Range
+   Two addresses, separated by a dash ("-") character. E.g.
+
+      172.26.13.4-172.27.12.9
+
+Network
+   An address and a CIDR based mask, separated by a slash ("/") character. E.g.
+
+      1337:0:0:ded:BEEF::/48
+
+Singleton
+   A single IP address, which is interpreted as a range of size 1.
+
+Such a string can be passed to the constructor, which will initialize to the 
corresponding range if
+properly formatted, otherwise the range will be default constructed to an 
invalid range. There is
+also the :libswoc:`swoc::IPRange::load` method which returns a :code:`bool` to 
indicate if the
+parsing was successful.
+
+IPSpace
+=======
+
+The :libswoc:`swoc::IPSpace` class is designed as a container for ranges of IP 
addresses. Lookup is
+done by single addresses. Conceptually, for each possible IP address there is 
a *payload*. Populating
+the container is done by applying a specific payload to a range of addresses. 
After populating an
+IP address can be looked up to find the corresponding payload.
+
+The payload is a template argument to the class, as with standard containers. 
There is no template
+argument for the key, as that is always an IP address.
+
+Applying payloads to the space is analogized to painting, each distinct 
payload considered a different
+"color" for an address. There are several methods used to paint the space, 
depending on the desired
+effect on existing payloads.
+
+mark
+   :libswoc:`swoc::IPSpace::mark` applies the :arg:`payload` to the range, 
replacing any existing
+   payload present. This is modeled on the "painter's algorithm" where the 
most recent coloring
+   replaces any prior colors in the region.
+
+fill
+   :libswoc:`swoc::IPSpace::fill` applies the :arg:`payload` to the range but 
only where there is not
+   already a payload. This is modeled on "backfilling" a background. This is 
useful for "first match"
+   logic, as which ever payload is first put in to the container will remain.
+
+blend
+   :libswoc:`swoc::IPSpace::blend` applies the :arg:`payload` to the range by 
combining ("blending")
+   the payloads. The result of blending can be "uncolored" which results in 
those addresses being
+   removed from the space. This is useful for applying different properties in 
sequence, where the
+   result is a combination of the properties.
+
+Blend
++++++
+
+The :libswoc:`swoc::IPSpace::blend` method requires a range and a "blender", 
which is a functor
+that combines two :code:`PAYLOAD` instances. The signature is ::
+
+  bool blender(PAYLOAD & lhs, PAYLOAD const& rhs)
+
+The method is modeled on C++ `compound assignment operators
+<https://en.cppreference.com/w/cpp/language/operator_assignment#Builtin_compound_assignment>`__.
 If
+the blend operation is thought of as the "@" operator, then the blend functor 
performs :code:`lhs @=
+rhs`. That is, :arg:`lhs` is modified to be the combination of :arg:`lhs` and 
:arg`rhs`. :arg:`lhs`
+is always the previous payload already in the space, and :arg:`rhs` is the 
:arg:`payload` argument
+to the :code:`blend` method. The internal logic handles copying the payload 
instances as needed.
+
+The return value indicates whether the combined result in :arg:`lhs` is a 
valid payload or not. If
+it is the method should return :code:`true`. In general most implementations 
will :code:`return
+true;` in all cases. If the method returns :code:`false` then the address(es) 
for the combined
+payload are removed from the container. This allows payloads to be 
"unblended", for one payload to
+cancel out another, or to do selective erasing of ranges.
+
+As an example, consider the case where the payload is a bitmask. It might be 
reasonable to keep
+empty bitmasks in the container, but it would be reasonble to decide the empty 
bitmask and any
+address mapped to it should removed entirely from the container. In such a 
case, a blender that
+clears bits in the payloads should return :code:`false` when the result is the 
empty bitmask.
+
+Similarly, if the goal is to remove ranges that have a specific payload, then 
a blender that returns
+:code:`false` if :arg:`lhs` matches that specific payload and :code:`true` if 
not, should be used.
+
+There is a small implementation wrinkle, however. Because the blending logic 
cannot assume the
+result of blending a payload with an equal payload results in the same 
payload, it must do a test to
+determine the result. I.e. if :arg:`lhs == rhs` for the arguments, it cannot 
be assumed that after
+the blend :arg:`lhs` remains unchanged (consider the bitmask unsetting blender 
earlier). The blender
+may want to return something special in this case, which can be detected by 
comparing :code:`&lhs ==
+&rhs`. If true then this is the test case, otherwise it is not.
 
 History
 *******
diff --git a/doc/index.rst b/doc/index.rst
index ffe0eb6..415634d 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -26,6 +26,7 @@ unrelated projects. Hence this library. I hope you find it as 
useful as I have.
    :maxdepth: 1
 
    preface.en
+   building.en
    code/BufferWriter.en
    code/BW_Format.en
    code/meta.en
diff --git a/swoc++/include/swoc/swoc_ip.h b/swoc++/include/swoc/swoc_ip.h
index 2ba59dd..e504e15 100644
--- a/swoc++/include/swoc/swoc_ip.h
+++ b/swoc++/include/swoc/swoc_ip.h
@@ -525,6 +525,14 @@ public:
     return f == _family;
   }
 
+  /** Load the range from @a text.
+   *
+   * @param text Range specifier in text format.
+   * @return @c true if @a text was successfully parsed, @c false if not.
+   *
+   * 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);
 
   IPAddr min() const;
@@ -633,6 +641,16 @@ public:
    */
   self_type & mark(IP4Range const &r, PAYLOAD const &payload);
 
+  /** Fill the @a range with @a payload.
+   *
+   * @param range Destination range.
+   * @param payload Payload for range.
+   * @return this
+   *
+   * 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);
+
   /** Blend @a payload in to the @a range.
    *
    * @tparam F Blending functor type (deduced).
@@ -1192,10 +1210,13 @@ template < typename PAYLOAD > auto 
IPSpace<PAYLOAD>::mark(swoc::IP4Range const &
   return *this;
 }
 
-template<typename PAYLOAD>
-void IPSpace<PAYLOAD>::clear() {
-  _ip4.clear();
-  _ip6.clear();
+template < typename PAYLOAD > auto IPSpace<PAYLOAD>::fill(swoc::IPRange const 
&range, PAYLOAD const &payload) -> self_type & {
+  if (range.is(AF_INET6)) {
+    _ip6.fill(range, payload);
+  } else if (range.is(AF_INET)) {
+    _ip4.fill(range, payload);
+  }
+  return *this;
 }
 
 template<typename PAYLOAD>
@@ -1209,4 +1230,11 @@ auto IPSpace<PAYLOAD>::blend(IPRange const&range, 
PAYLOAD const&payload, F&&blen
   return *this;
 }
 
+template<typename PAYLOAD>
+void IPSpace<PAYLOAD>::clear() {
+  _ip4.clear();
+  _ip6.clear();
+}
+
+
 } // namespace swoc

Reply via email to