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

amc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 7433988c8 libswoc: Update to 1.4.6 (#9530)
7433988c8 is described below

commit 7433988c86a100093535bb913fb223cb689c9d72
Author: Alan M. Carroll <a...@apache.org>
AuthorDate: Sat Mar 18 09:23:31 2023 -0500

    libswoc: Update to 1.4.6 (#9530)
---
 lib/swoc/CMakeLists.txt               |   2 +-
 lib/swoc/Makefile.am                  |   2 +-
 lib/swoc/include/swoc/DiscreteRange.h |   9 ++
 lib/swoc/include/swoc/Errata.h        | 128 ++++++++++++++--
 lib/swoc/include/swoc/IPAddr.h        |   2 +
 lib/swoc/include/swoc/IPRange.h       | 273 +++++++++++++++++++++++++++++++---
 lib/swoc/include/swoc/swoc_version.h  |   4 +-
 lib/swoc/src/Errata.cc                |  32 +++-
 lib/swoc/src/bw_format.cc             |  12 +-
 lib/swoc/src/swoc_ip.cc               |   6 +-
 10 files changed, 414 insertions(+), 56 deletions(-)

diff --git a/lib/swoc/CMakeLists.txt b/lib/swoc/CMakeLists.txt
index 420da122e..f0a7755f5 100644
--- a/lib/swoc/CMakeLists.txt
+++ b/lib/swoc/CMakeLists.txt
@@ -1,7 +1,7 @@
 cmake_minimum_required(VERSION 3.11)
 
 project(Lib-SWOC CXX)
-set(LIBSWOC_VERSION "1.4.5")
+set(LIBSWOC_VERSION "1.4.6")
 set(CMAKE_CXX_STANDARD 17)
 cmake_policy(SET CMP0087 NEW)
 # override "lib64" to be "lib" unless the user explicitly sets it.
diff --git a/lib/swoc/Makefile.am b/lib/swoc/Makefile.am
index bd1c51dea..210d7c6b4 100644
--- a/lib/swoc/Makefile.am
+++ b/lib/swoc/Makefile.am
@@ -22,7 +22,7 @@ library_includedir=$(includedir)/swoc
 
 AM_CPPFLAGS += @SWOC_INCLUDES@
 
-libtsswoc_la_LDFLAGS = @AM_LDFLAGS@ -no-undefined -release 1.4.5
+libtsswoc_la_LDFLAGS = @AM_LDFLAGS@ -no-undefined -release 1.4.6
 libtsswoc_la_SOURCES = \
        src/ArenaWriter.cc  src/bw_format.cc  src/bw_ip_format.cc  
src/Errata.cc  src/MemArena.cc  src/RBTree.cc  src/swoc_file.cc  src/swoc_ip.cc 
 src/TextView.cc src/string_view_util.cc
 
diff --git a/lib/swoc/include/swoc/DiscreteRange.h 
b/lib/swoc/include/swoc/DiscreteRange.h
index cfefbf510..a04a3e7d2 100644
--- a/lib/swoc/include/swoc/DiscreteRange.h
+++ b/lib/swoc/include/swoc/DiscreteRange.h
@@ -850,6 +850,9 @@ public:
   /// @return The number of distinct ranges.
   size_t count() const;
 
+  /// @return @c true if there are no ranges in the container, @c false 
otherwise.
+  bool empty() const;
+
   /// @return Iterator for the first range.
   iterator begin() { return _list.begin(); }
   /// @return Iterator past the last node.
@@ -977,6 +980,12 @@ DiscreteSpace<METRIC, PAYLOAD>::count() const {
   return _list.count();
 }
 
+template <typename METRIC, typename PAYLOAD>
+bool
+DiscreteSpace<METRIC, PAYLOAD>::empty() const {
+  return _list.empty();
+}
+
 template <typename METRIC, typename PAYLOAD>
 auto
 DiscreteSpace<METRIC, PAYLOAD>::head() -> Node * {
diff --git a/lib/swoc/include/swoc/Errata.h b/lib/swoc/include/swoc/Errata.h
index 94c9b9a2c..3995e279c 100644
--- a/lib/swoc/include/swoc/Errata.h
+++ b/lib/swoc/include/swoc/Errata.h
@@ -76,7 +76,7 @@ public:
 
   /// Code used if not specified.
   static inline const code_type DEFAULT_CODE;
-  /// Severity used if not specified.
+  /// Severity reported if severity not set.
   static Severity DEFAULT_SEVERITY;
   /// Severity level at which the instance is a failure of some sort.
   static Severity FAILURE_SEVERITY;
@@ -189,7 +189,13 @@ protected:
     /// Allocate from the arena.
     swoc::MemSpan<char> alloc(size_t n);
 
-    Severity _severity{Errata::DEFAULT_SEVERITY}; ///< Severity.
+    TextView _annotation_glue_text = DEFAULT_ANNOTATION_GLUE_TEXT;
+    TextView _annotation_severity_glue_text = DEFAULT_SEVERITY_GLUE_TEXT;
+    TextView _severity_glue_text = DEFAULT_SEVERITY_GLUE_TEXT;
+    TextView _indent_text = DEFAULT_INDENT_TEXT;
+    bool _glue_final_p = true; ///< Add glue after the last annotation?
+
+    std::optional<Severity> _severity; ///< Severity.
     code_type _code{Errata::DEFAULT_CODE};        ///< Message code / ID
     Container _notes;                             ///< The message stack.
     swoc::MemArena _arena;                        ///< Annotation text storage.
@@ -360,7 +366,11 @@ public:
   friend std::ostream &operator<<(std::ostream &, self_type const &);
 
   /// Default glue value (a newline) for text rendering.
-  static std::string_view DEFAULT_GLUE;
+  static inline TextView DEFAULT_ANNOTATION_GLUE_TEXT = "\n";
+  /// Default glue text for use after the severity name.
+  static inline TextView DEFAULT_SEVERITY_GLUE_TEXT = ": ";
+  // Text used for each level of indent.
+  static inline TextView DEFAULT_INDENT_TEXT = "  ";
 
   /** Test status.
 
@@ -391,6 +401,8 @@ public:
    */
   bool is_ok() const;
 
+  bool has_severity() const { return _data && _data->_severity.has_value(); }
+
   /** Get the maximum severity of the messages in the erratum.
    *
    * @return Max severity for all messages.
@@ -442,12 +454,65 @@ public:
   //! Reference one past bottom item on the stack.
   const_iterator end() const;
 
+  /** First annotation.
+   *
+   * @return The first annotation.
+   *
+   * It is an error to call this on an empty instance.
+   */
   const Annotation &front() const;
 
+  /** lask annotation.
+   *
+   * @return The last annotation.
+   *
+   * It is an error to call this on an empty instance.
+   */
   const Annotation &back() const;
 
   // Logging support.
 
+  /// @return The annotation glue text for @a this.
+  TextView annotation_glue_text() const;
+
+  /** Assign text to use between annotations while printing.
+   *
+   * @param text Glue text.
+   * @param final_glue_p Add glue after last annotation?
+   * @return @a this
+   */
+  self_type & assign_annotation_glue_text(TextView text, bool final_glue_p = 
false);
+
+  /// @return Glue text for the annotation severity.
+  TextView annotation_severity_glue_text() const;
+
+  /** Assign text to use after the severity for an annoation while printing.
+   *
+   * @param text Glue text.
+   * @return @a this
+   */
+  self_type & assign_annotation_severity_glue_text(TextView text);
+
+  /// @return The severity glue text for @a this.
+  TextView severity_glue_text() const;
+
+  /** Assign text to use after the severity while printing.
+   *
+   * @param text Glue text.
+   * @return @a this
+   */
+  self_type & assign_severity_glue_text(TextView text);
+
+  /// @return The text used for each level of indentation.
+  TextView indent_text() const;
+
+  /** Assign the text used for indentation.
+   *
+   * @param text Text for each level of indentation.
+   * @return @a this.
+   */
+  self_type & assign_indent_text(TextView text);
+
   /** Base class for erratum sink.
 
       When an errata is abandoned, this will be called on it to perform any 
client specific logging.
@@ -528,6 +593,7 @@ protected:
 
   friend struct Data;
   friend class Item;
+  friend BufferWriter &bwformat(BufferWriter &bw, bwf::Spec const &, Errata 
const &errata);
 };
 
 extern std::ostream &operator<<(std::ostream &os, Errata const &stat);
@@ -941,7 +1007,7 @@ inline auto Errata::assign(code_type code) -> self_type & {
 
 inline auto
 Errata::severity() const -> Severity {
-  return _data ? _data->_severity : DEFAULT_SEVERITY;
+  return _data ? _data->_severity.value() : DEFAULT_SEVERITY;
 }
 
 inline auto Errata::assign(Severity severity) -> self_type & {
@@ -949,15 +1015,6 @@ inline auto Errata::assign(Severity severity) -> 
self_type & {
   return *this;
 }
 
-inline auto Errata::update(Severity severity) -> self_type & {
-  if (_data) {
-    _data->_severity = std::max(_data->_severity, severity);
-  } else {
-    this->assign(severity);
-  }
-  return *this;
-}
-
 inline size_t
 Errata::length() const {
   return _data ? _data->_notes.count() : 0;
@@ -1063,6 +1120,51 @@ Errata::end() const {
   return _data ? _data->_notes.end() : const_iterator();
 }
 
+inline TextView
+Errata::annotation_glue_text() const {
+  return _data ? _data->_annotation_glue_text : DEFAULT_ANNOTATION_GLUE_TEXT;
+}
+
+inline auto
+Errata::assign_annotation_glue_text(TextView text, bool final_glue_p) -> 
self_type & {
+  this->data()->_annotation_glue_text = this->data()->localize(text);
+  this->data()->_glue_final_p = final_glue_p;
+  return *this;
+}
+
+inline TextView
+Errata::annotation_severity_glue_text() const {
+  return _data ? _data->_annotation_severity_glue_text : 
DEFAULT_SEVERITY_GLUE_TEXT;
+}
+
+inline auto
+Errata::assign_annotation_severity_glue_text(TextView text) -> self_type & {
+  this->data()->_annotation_severity_glue_text = this->data()->localize(text);
+  return *this;
+}
+
+inline TextView
+Errata::severity_glue_text() const {
+  return _data ? _data->_severity_glue_text : DEFAULT_SEVERITY_GLUE_TEXT;
+}
+
+inline auto
+Errata::assign_severity_glue_text(TextView text) -> self_type & {
+  this->data()->_severity_glue_text = this->data()->localize(text);
+  return *this;
+}
+
+inline TextView
+Errata::indent_text() const {
+  return _data ? _data->_indent_text : DEFAULT_INDENT_TEXT;
+}
+
+inline auto
+Errata::assign_indent_text(TextView text) -> self_type & {
+  this->data()->_indent_text = this->data()->localize(text);
+  return *this;
+}
+
 inline void
 Errata::SinkWrapper::operator()(Errata const &e) const {
   _f(e);
diff --git a/lib/swoc/include/swoc/IPAddr.h b/lib/swoc/include/swoc/IPAddr.h
index 44198f3df..ac359c4c9 100644
--- a/lib/swoc/include/swoc/IPAddr.h
+++ b/lib/swoc/include/swoc/IPAddr.h
@@ -9,6 +9,8 @@
 #include <netinet/in.h>
 #include <sys/socket.h>
 
+#include <cstddef>
+
 #include "swoc/swoc_version.h"
 #include "swoc/swoc_meta.h"
 #include "swoc/MemSpan.h"
diff --git a/lib/swoc/include/swoc/IPRange.h b/lib/swoc/include/swoc/IPRange.h
index 89b69cd71..9f05c5a5e 100644
--- a/lib/swoc/include/swoc/IPRange.h
+++ b/lib/swoc/include/swoc/IPRange.h
@@ -322,14 +322,51 @@ public:
   /// Default constructor - construct invalid range.
   IPRange() = default;
 
+  /** Construct an inclusive range.
+   *
+   * @param min Minimum range value.
+   * @param max Maximum range value.
+   */
   IPRange(IPAddr const &min, IPAddr const &max);
 
+  /** Construct an inclusive range.
+   *
+   * @param min Minimum range value.
+   * @param max Maximum range value.
+   */
+  IPRange(IP4Addr const &min, IP4Addr const &max);
+  /** Construct an inclusive range.
+   *
+   * @param min Minimum range value.
+   * @param max Maximum range value.
+   */
+  IPRange(IP6Addr const &min, IP6Addr const &max);
+
+  /** Construct a singleton range.
+   *
+   * @param addr Address of range.
+   */
+
+  IPRange(IPAddr const& addr) : IPRange(addr, addr) {}
+  /** Construct a singleton range.
+   *
+   * @param addr Address of range.
+   */
+  IPRange(IP4Addr addr) : IPRange(addr, addr) {}
+
+  /** Construct a singleton range.
+   *
+   * @param addr Address of range.
+   */
+  IPRange(IP6Addr const & addr) : IPRange(addr, addr) {}
+
   /// Construct from an IPv4 @a range.
   IPRange(IP4Range const &range);
 
   /// Construct from an IPv6 @a range.
   IPRange(IP6Range const &range);
 
+
   /** Construct from a string format.
    *
    * @param text Text form of range.
@@ -338,6 +375,9 @@ public:
    */
   IPRange(string_view const &text);
 
+  self_type & assign(IP4Addr const& min, IP4Addr const& max);
+  self_type & assign(IP6Addr const& min, IP6Addr const& max);
+
   /// Equality
   bool operator==(self_type const &that) const;
   /// Inequality
@@ -796,22 +836,24 @@ public:
     blend(IP6Range const &range, U const &color, F &&blender);
 
   /// @return The number of distinct ranges.
-  size_t
-  count() const {
-    return _ip4.count() + _ip6.count();
-  }
+  size_t count() const;
 
-  size_t
-  count_ip4() const {
-    return _ip4.count();
-  }
-  size_t
-  count_ip6() const {
-    return _ip6.count();
-  }
+  /// @return The number of IPv4 ranges.
+  size_t count_ip4() const;
 
+  /// @return The number of IPv6 ranges.
+  size_t count_ip6() const;
+
+  /** Number of rnages for a specific address family.
+   *
+   * @param f Address family.
+   * @return The number of ranges of @a family.
+   */
   size_t count(sa_family_t f) const;
 
+  /// @return @c true if there are no ranges in the space, @c false otherwise.
+  bool empty() const;
+
   /// Remove all ranges.
   void clear();
 
@@ -882,6 +924,8 @@ public:
     /// @return A pointer to the referent.
     value_type const *operator->() const;
 
+    IPRange const& range() const;
+
     /// Equality
     bool operator==(self_type const &that) const;
 
@@ -978,6 +1022,7 @@ public:
     /// Dereference.
     /// @return A pointer to the referent.
     value_type const *operator->() const;
+
   };
 
   /** Find the payload for an @a addr.
@@ -1103,6 +1148,8 @@ protected:
   iterator iterator_at(typename IP6Space::iterator const& spot) {
     return iterator(_ip4.end(), spot);
   }
+
+  friend class IPRangeSet;
 };
 
 /** An IPSpace that contains only addresses.
@@ -1117,6 +1164,20 @@ class IPRangeSet
 {
   using self_type = IPRangeSet;
 
+  /// Empty struct to use for payload.
+  /// This declares the struct and defines the singleton instance used.
+  /// @internal For some reason @c std::monostate didn't work, but I don't 
remember why.
+  static inline constexpr struct Mark {
+    using self_type = Mark;
+    /// @internal @c IPSpace requires equality / inequality operators.
+    /// These make all instance equal to each other.
+    bool operator==(self_type const &that);
+    bool operator!=(self_type const &that);
+  } MARK{};
+
+  /// Range set type.
+  using Space = swoc::IPSpace<Mark>;
+
 public:
   /// Default construct empty set.
   IPRangeSet() = default;
@@ -1145,22 +1206,85 @@ public:
   /// @return Number of ranges in the set.
   size_t count() const;
 
+  bool empty() const;
+
   /// Remove all addresses in the set.
   void clear();
 
-protected:
-  /// Empty struct to use for payload.
-  /// This declares the struct and defines the singleton instance used.
-  static inline constexpr struct Mark {
-    using self_type = Mark;
-    /// @internal @c IPSpace requires equality / inequality operators.
-    /// These make all instance equal to each other.
-    bool operator==(self_type const &that);
-    bool operator!=(self_type const &that);
-  } MARK{};
+  /// Constant iterator for iteration over ranges.
+  class const_iterator {
+    using self_type = const_iterator; ///< Self reference type.
+    using super_type = Space::const_iterator;
+    friend class IPRangeSet;
+
+  public:
+    using value_type = IPRange const;
+    // STL algorithm compliance.
+    using iterator_category = std::bidirectional_iterator_tag;
+    using pointer           = value_type *;
+    using reference         = value_type &;
+    using const_reference   = value_type const &;
+    using difference_type   = int;
+
+    /// Default constructor.
+    const_iterator() = default;
 
+    /// Copy constructor.
+    const_iterator(self_type const &that) = default;
+
+    /// Assignment.
+    self_type &operator=(self_type const &that) = default;
+
+    /// Pre-increment.
+    /// Move to the next element in the list.
+    /// @return The iterator.
+    self_type &operator++();
+
+    /// Pre-decrement.
+    /// Move to the previous element in the list.
+    /// @return The iterator.
+    self_type &operator--();
+
+    /// Post-increment.
+    /// Move to the next element in the list.
+    /// @return The iterator value before the increment.
+    self_type operator++(int);
+
+    /// Post-decrement.
+    /// Move to the previous element in the list.
+    /// @return The iterator value before the decrement.
+    self_type operator--(int);
+
+    /// Dereference.
+    /// @return A reference to the referent.
+    value_type const& operator*() const;
+
+    /// Dereference.
+    /// @return A pointer to the referent.
+    value_type const *operator->() const;
+
+    /// Equality
+    bool operator==(self_type const &that) const;
+
+    /// Inequality
+    bool operator!=(self_type const &that) const;
+
+  protected:
+    const_iterator(super_type const& spot) : _iter(spot) {}
+
+    super_type _iter; ///< Underlying iterator.
+  };
+
+  using iterator = const_iterator;
+
+  /// @return Iterator to first range.
+  const_iterator begin() const { return _addrs.begin(); }
+  /// @return Iterator past last range.
+  const_iterator end() const { return _addrs.end(); }
+
+protected:
   /// The address set.
-  swoc::IPSpace<Mark> _addrs;
+  Space _addrs;
 };
 
 inline auto
@@ -1189,6 +1313,11 @@ IPRangeSet::count() const
   return _addrs.count();
 }
 
+inline bool
+IPRangeSet::empty() const {
+  return _addrs.empty();
+}
+
 inline void
 IPRangeSet::clear()
 {
@@ -1294,9 +1423,13 @@ IPSpace<PAYLOAD>::const_iterator::operator->() const -> 
value_type const * {
   return &_value;
 }
 
+template <typename PAYLOAD>
+IPRange const &
+IPSpace<PAYLOAD>::const_iterator::range() const { return std::get<0>(_value); }
+
 /* Bit of subtlety with equality - although it seems that if @a _iter_4 is 
valid, it doesn't matter
  * where @a _iter6 is (because it is really the iterator location that's being 
checked), it's
- * neccesary to do the @a _iter_4 validity on both iterators to avoid the case 
of a false positive
+ * necessary to do the @a _iter_4 validity on both iterators to avoid the case 
of a false positive
  * where different internal iterators are valid. However, in practice the 
other (non-active)
  * iterator won't have an arbitrary value, it will be either @c begin or @c 
end in step with the
  * active iterator therefore it's effective and cheaper to just check both 
values.
@@ -1378,10 +1511,32 @@ inline IPRange::IPRange(IP6Range const &range) : 
_family(AF_INET6) {
   _range._ip6 = range;
 }
 
+inline IPRange::IPRange(IP4Addr const &min, IP4Addr const &max) {
+  this->assign(min, max);
+}
+
+inline IPRange::IPRange(IP6Addr const &min, IP6Addr const &max) {
+  this->assign(min, max);
+}
+
 inline IPRange::IPRange(string_view const &text) {
   this->load(text);
 }
 
+inline auto
+IPRange::assign(IP4Addr const &min, IP4Addr const &max) -> self_type & {
+  _range._ip4.assign(min, max);
+  _family = AF_INET;
+  return *this;
+}
+
+inline auto
+IPRange::assign(IP6Addr const &min, IP6Addr const &max) -> self_type & {
+  _range._ip6.assign(min, max);
+  _family = AF_INET6;
+  return *this;
+}
+
 inline auto
 IPRange::networks() const -> NetSource {
   return {NetSource{*this}};
@@ -1911,12 +2066,82 @@ IPSpace<PAYLOAD>::end(sa_family_t family) const -> 
const_iterator {
   return this->end();
 }
 
+template <typename PAYLOAD>
+size_t
+IPSpace<PAYLOAD>::count_ip4() const {
+  return _ip4.count();
+}
+
+template <typename PAYLOAD>
+size_t
+IPSpace<PAYLOAD>::count_ip6() const {
+  return _ip6.count();
+}
+
+template <typename PAYLOAD>
+size_t
+IPSpace<PAYLOAD>::count() const {
+  return _ip4.count() + _ip6.count();
+}
+
 template <typename PAYLOAD>
 size_t
 IPSpace<PAYLOAD>::count(sa_family_t f) const {
   return IP4Addr::AF_value == f ? _ip4.count() : IP6Addr::AF_value == f ? 
_ip6.count() : 0;
 }
 
+template <typename PAYLOAD>
+bool
+IPSpace<PAYLOAD>::empty() const {
+  return _ip4.empty() && _ip6.empty();
+}
+
+inline auto
+IPRangeSet::const_iterator::operator++() -> self_type & {
+  ++_iter;
+  return *this;
+}
+
+inline auto
+IPRangeSet::const_iterator::operator--() -> self_type & {
+  --_iter;
+  return *this;
+}
+
+inline auto
+IPRangeSet::const_iterator::operator++(int) -> self_type {
+  self_type zret{*this};
+  ++_iter;
+  return zret;
+}
+
+inline auto
+IPRangeSet::const_iterator::operator--(int) -> self_type {
+  self_type zret{*this};
+  --_iter;
+  return zret;
+}
+
+inline auto
+IPRangeSet::const_iterator::operator*() const -> value_type const& {
+  return _iter.range();
+}
+
+inline auto
+IPRangeSet::const_iterator::operator->() const -> value_type const * {
+  return &(_iter.range());
+}
+
+inline bool
+IPRangeSet::const_iterator::operator==(IPRangeSet::const_iterator::self_type 
const &that) const {
+  return _iter == that._iter;
+}
+
+inline bool
+IPRangeSet::const_iterator::operator!=(IPRangeSet::const_iterator::self_type 
const &that) const {
+  return _iter != that._iter;
+}
+
 }} // namespace swoc::SWOC_VERSION_NS
 
 /// @cond NOT_DOCUMENTED
diff --git a/lib/swoc/include/swoc/swoc_version.h 
b/lib/swoc/include/swoc/swoc_version.h
index 636eae0b3..9c7d2748c 100644
--- a/lib/swoc/include/swoc/swoc_version.h
+++ b/lib/swoc/include/swoc/swoc_version.h
@@ -23,11 +23,11 @@
 #pragma once
 
 #if !defined(SWOC_VERSION_NS)
-#define SWOC_VERSION_NS _1_4_5
+#define SWOC_VERSION_NS _1_4_6
 #endif
 
 namespace swoc { inline namespace SWOC_VERSION_NS {
 static constexpr unsigned MAJOR_VERSION = 1;
 static constexpr unsigned MINOR_VERSION = 4;
-static constexpr unsigned POINT_VERSION = 5;
+static constexpr unsigned POINT_VERSION = 6;
 }} // namespace swoc::SWOC_VERSION_NS
diff --git a/lib/swoc/src/Errata.cc b/lib/swoc/src/Errata.cc
index c354f0a9e..80e6bea91 100644
--- a/lib/swoc/src/Errata.cc
+++ b/lib/swoc/src/Errata.cc
@@ -25,8 +25,6 @@ namespace {
 std::vector<Errata::Sink::Handle> Sink_List;
 }
 
-std::string_view Errata::DEFAULT_GLUE{"\n", 1};
-
 string_view
 Errata::Data::localize(string_view src) {
   auto span = _arena.alloc(src.size()).rebind<char>();
@@ -110,7 +108,9 @@ Errata &
 Errata::note(const self_type &that) {
   if (that._data) {
     auto d       = this->data();
-    d->_severity = std::max<Severity>(d->_severity, that._data->_severity);
+    if (that.has_severity()) {
+      this->update(that.severity());
+    }
     for (auto const &annotation : that) {
       
d->_notes.append(d->_arena.make<Annotation>(d->localize(annotation._text), 
annotation._severity, annotation._level + 1));
     }
@@ -118,6 +118,13 @@ Errata::note(const self_type &that) {
   return *this;
 }
 
+auto Errata::update(Severity severity) -> self_type & {
+  if (! _data || ! _data->_severity.has_value() || _data->_severity.value() < 
severity) {
+    this->assign(severity);
+  }
+  return *this;
+}
+
 void
 Errata::register_sink(Sink::Handle const &s) {
   Sink_List.push_back(s);
@@ -135,18 +142,31 @@ bwformat(BufferWriter &bw, bwf::Spec const &spec, 
Errata::Severity level) {
 
 BufferWriter &
 bwformat(BufferWriter &bw, bwf::Spec const &, Errata const &errata) {
-  bw.print("{}: ", errata.severity());
+  if (errata.has_severity()) {
+    bw.print("{}{}", errata.severity(), errata.severity_glue_text());
+  }
 
   if (errata.code()) {
     bw.print("[{0:s} {0:d}] ", errata.code());
   }
 
+  bool trailing_p = false;
+  auto glue = errata.annotation_glue_text();
+  auto a_s_glue = errata.annotation_severity_glue_text();
+  auto id_txt = errata.indent_text();
   for (auto &note : errata) {
     if (note.text()) {
-      bw.print("{}{}{}\n", swoc::bwf::Pattern{int(note.level()), "  "}, 
swoc::bwf::If(note.has_severity(), "{}: ", note.severity()),
-               note.text());
+      bw.print("{}{}{}{}"
+               , swoc::bwf::If(trailing_p, "{}", glue)
+               , swoc::bwf::Pattern{int(note.level()), id_txt}
+               , swoc::bwf::If(note.has_severity(), "{}{}", note.severity(), 
a_s_glue)
+               , note.text());
+      trailing_p = true;
     }
   }
+  if (trailing_p && errata._data->_glue_final_p) {
+    bw.print("{}", glue);
+  }
   return bw;
 }
 
diff --git a/lib/swoc/src/bw_format.cc b/lib/swoc/src/bw_format.cc
index 4d4432e8e..0aa735986 100644
--- a/lib/swoc/src/bw_format.cc
+++ b/lib/swoc/src/bw_format.cc
@@ -936,11 +936,13 @@ bwformat(BufferWriter &w, bwf::Spec const &spec, 
bwf::Date const &date) {
 
 BufferWriter &
 bwformat(BufferWriter &w, bwf::Spec const &spec, bwf::Pattern const &pattern) {
-  auto limit        = std::min<size_t>(spec._max, pattern._text.size() * 
pattern._n);
-  decltype(limit) n = 0;
-  while (n < limit) {
-    w.write(pattern._text);
-    n += pattern._text.size();
+  if (! pattern._text.empty()) { // If there's no text, no point in looping.
+    auto limit        = std::min<size_t>(spec._max, pattern._text.size() * 
pattern._n);
+    decltype(limit) n = 0;
+    while (n < limit) {
+      w.write(pattern._text);
+      n += pattern._text.size();
+    }
   }
   return w;
 }
diff --git a/lib/swoc/src/swoc_ip.cc b/lib/swoc/src/swoc_ip.cc
index c9a5564d2..469d90f6e 100644
--- a/lib/swoc/src/swoc_ip.cc
+++ b/lib/swoc/src/swoc_ip.cc
@@ -1055,11 +1055,9 @@ IP6Range::load(std::string_view text) {
 
 IPRange::IPRange(IPAddr const &min, IPAddr const &max) {
   if (min.is_ip4() && max.is_ip4()) {
-    _range._ip4.assign(min.ip4(), max.ip4());
-    _family = AF_INET;
+    this->assign(min.ip4(), max.ip4());
   } else if (min.is_ip6() && max.is_ip6()) {
-    _range._ip6.assign(min.ip6(), max.ip6());
-    _family = AF_INET6;
+    this->assign(min.ip6(), max.ip6());
   }
 }
 

Reply via email to