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 <[email protected]>
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 ¬e : 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());
}
}