This is an automated email from the ASF dual-hosted git repository. bneradt pushed a commit to branch charset in repository https://gitbox.apache.org/repos/asf/trafficserver-libswoc.git
commit 3632bbcbcfd146fc6480a7226872e8e5b00a49f5 Author: Alan M. Carroll <[email protected]> AuthorDate: Tue Nov 21 16:37:06 2023 -0600 Errata: Enable auto generated annotations. --- code/include/swoc/Errata.h | 87 +++++++++++++++++++++++++++++++++++++++----- code/include/swoc/TextView.h | 86 ++++++++++++++++++++++++++++++++----------- code/src/bw_format.cc | 4 +- unit_tests/test_Errata.cc | 46 +++++++++++++++++++++++ 4 files changed, 190 insertions(+), 33 deletions(-) diff --git a/code/include/swoc/Errata.h b/code/include/swoc/Errata.h index 59ec0d4..8d3c129 100644 --- a/code/include/swoc/Errata.h +++ b/code/include/swoc/Errata.h @@ -47,6 +47,7 @@ #include "swoc/MemSpan.h" #include "swoc/MemArena.h" #include "swoc/bwf_base.h" +#include "swoc/bwf_std.h" #include "swoc/IntrusiveDList.h" namespace swoc { inline namespace SWOC_VERSION_NS { @@ -85,6 +86,10 @@ public: /// This defaults to zero and no filtering is done unless it is overwritten. static Severity FILTER_SEVERITY; + static inline TextView AUTOTEXT_SEVERITY = "{}"; ///< Format for auto generated annotation with severity. + static inline TextView AUTOTEXT_CODE = "{}"; ///< Format for auto generated annotation with error code. + static inline TextView AUTOTEXT_SEVERITY_CODE = "{}: {}"; ///< Format for auto generate annotation with error code and severity. + /// Mapping of severity to string. /// Values larger than the span size will be rendered as numbers. /// Defaults to an empty span, meaning all severities will be printed as integers. @@ -196,28 +201,77 @@ protected: 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 + code_type _code{DEFAULT_CODE}; ///< Message code / ID Container _notes; ///< The message stack. swoc::MemArena _arena; ///< Annotation text storage. }; public: + /// Used to indicate automatically generated annotation text. + static constexpr struct AutoText {} AUTO {}; + /// Default constructor - empty errata, very fast. Errata() = default; - Errata(self_type const &that) = delete; ///< No constant copy construction. + Errata(self_type const &that) = delete; ///< No copy construction. Errata(self_type &&that) noexcept; ///< Move constructor. - self_type &operator=(self_type const &that) = delete; // no copy assignemnt. + self_type &operator=(self_type const &that) = delete; // no copy assignment. self_type &operator=(self_type &&that); ///< Move assignment. ~Errata(); ///< Destructor. + /** Construct with an error code. + * + * @param ec Error code + * + * No annotation is created. + */ + explicit Errata(code_type const& ec); + + /** Construct with an error code and generated annotation. + * + * @param ec Error code + * + * An annotation is created using the format @c AUTOTEXT_CODE with @a ec as the argument. + * @see AUTOTEXT_CODE + */ + explicit Errata(code_type const& ec, AutoText); + /** Construct with a severity. * * @param severity Severity. * - * No annotations are created. + * No annotation is created. */ explicit Errata(Severity severity); + /** Construct with a severity. + * + * @param severity Severity. + * + * An annotation is created using the format @c AUTO_TEXT_SEVERITY with @a severity as the argument. + * @see AUTOTEXT_SEVERITY + */ + explicit Errata(Severity severity, AutoText); + + /** Construct with error code and severity. + * + * @param ec Error code. + * @param severity Severity. + * + * No annotation is created. + */ + Errata(code_type const &ec, Severity severity); + + /** Construct with a severity and error code. + * + * @param severity Severity. + * @param ec Error code. + * @param auto_text If present, generate an annotation. + * + * The annotation uses the format @c AUTOTEXT_SEVERITY_CODE with arguments @a severity , @a ec + * @see AUTOTEXT_SEVERITY_CODE + */ + explicit Errata(code_type const& ec, Severity severity, AutoText auto_text); + /** Constructor. * * @param code Error code. @@ -613,9 +667,6 @@ public: std::ostream &write(std::ostream &out) const; protected: - /// Construct with code and severity, but no annotations. - Errata(code_type const &code, Severity severity); - /// Implementation instance. /// @internal Because this is used with a self-containing @c MemArena standard smart pointers do not /// work correctly. Instead the @c clear method must be used to release the memory. @@ -979,14 +1030,32 @@ inline Errata::Errata(self_type &&that) noexcept { std::swap(_data, that._data); } +inline Errata::Errata(code_type const& ec) { + this->data()->_code = ec; +} + inline Errata::Errata(Severity severity) { this->data()->_severity = severity; } -inline Errata::Errata(const code_type &code, Severity severity) { +inline Errata::Errata(const code_type &ec, Severity severity) { auto d = this->data(); d->_severity = severity; - d->_code = code; + d->_code = ec; +} + +inline Errata::Errata(code_type const& ec, AutoText) { + this->data()->_code = ec; + this->note(AUTOTEXT_CODE, ec); +} + +inline Errata::Errata(Severity severity, AutoText) { + this->data()->_severity = severity; + this->note(AUTOTEXT_SEVERITY, severity); +} + +inline Errata::Errata(const code_type &ec, Severity severity, AutoText) : Errata(ec, severity) { + this->note(AUTOTEXT_SEVERITY_CODE, severity, ec); } inline Errata::Errata(const code_type &code, Severity severity, const std::string_view &text) : Errata(code, severity) { diff --git a/code/include/swoc/TextView.h b/code/include/swoc/TextView.h index b665f54..ed342ee 100644 --- a/code/include/swoc/TextView.h +++ b/code/include/swoc/TextView.h @@ -36,6 +36,18 @@ namespace swoc { inline namespace SWOC_VERSION_NS { class TextView; +/** A set of characters. + * + */ +class CharSet { + using self_type = CharSet; +public: + constexpr CharSet(TextView const& chars); + bool operator () (u_char idx) const { return _chars[idx]; } +protected: + std::bitset<256> _chars; +}; + /** A read only view of a contiguous piece of memory. A @c TextView does not own the memory to which it refers, it is simply a view of part of some @@ -324,6 +336,12 @@ public: */ self_type <rim(char c); + /** Remove bytes from the start of the view that are in @a delimiters. + * + * @return @a this + */ + self_type <rim(CharSet const &delimiters); + /** Remove bytes from the start of the view that are in @a delimiters. * * @return @a this @@ -350,6 +368,12 @@ public: */ self_type &rtrim(char c); + /** Remove bytes from the end of the view that are in @a delimiters. + * + * @return @a this + */ + self_type &rtrim(CharSet const &delimiters); + /** Remove bytes from the end of the view that are in @a delimiters. * @return @a this */ @@ -369,6 +393,11 @@ public: */ self_type &trim(char c); + /** Remove bytes from the start and end of the view that are in @a delimiters. + * @return @a this + */ + self_type &trim(CharSet const &delimiters); + /** Remove bytes from the start and end of the view that are in @a delimiters. * @return @a this */ @@ -1052,6 +1081,12 @@ double svtod(TextView text, TextView *parsed = nullptr); // simpler plain @c TextView ? Because otherwise Doxygen can't match up the declaration and // definition and the reference documentation is messed up. Sigh. +inline constexpr CharSet::CharSet(TextView const & chars) { + for ( auto c : chars) { + _chars[u_char(c)] = true; + } +} + // === TextView Implementation === /// @cond TextView_INTERNAL // Doxygen doesn't match these up well due to various type and template issues. @@ -1474,62 +1509,71 @@ TextView::trim(char c) { } inline TextView & -TextView::ltrim(std::string_view const &delimiters) { - std::bitset<256> valid; - this->init_delimiter_set(delimiters, valid); - const char *spot; - const char *limit; +TextView::ltrim(CharSet const &delimiters) { + const char *spot = this->data(); + const char *limit = this->data_end(); - for (spot = this->data(), limit = this->data_end(); spot < limit && valid[static_cast<uint8_t>(*spot)]; ++spot) - ; + while (spot < limit && delimiters(*spot)) { + ++spot; + } this->remove_prefix(spot - this->data()); return *this; } +inline TextView & +TextView::ltrim(std::string_view const &delimiters) { + return this->ltrim(CharSet(delimiters)); +} + inline TextView & TextView::ltrim(const char *delimiters) { - return this->ltrim(std::string_view(delimiters)); + return this->ltrim(CharSet(delimiters)); } inline TextView & -TextView::rtrim(std::string_view const &delimiters) { - std::bitset<256> valid; - this->init_delimiter_set(delimiters, valid); +TextView::rtrim(CharSet const &delimiters) { const char *spot = this->data_end(); const char *limit = this->data(); - - while (limit < spot-- && valid[static_cast<uint8_t>(*spot)]) - ; + while (limit < spot-- && delimiters(*spot)) { + } this->remove_suffix(this->data_end() - (spot + 1)); return *this; } inline TextView & -TextView::trim(std::string_view const &delimiters) { - std::bitset<256> valid; - this->init_delimiter_set(delimiters, valid); +TextView::rtrim(std::string_view const &delimiters) { + return this->rtrim(CharSet(delimiters)); +} + +inline TextView & +TextView::trim(CharSet const &delimiters) { const char *spot; const char *limit; // Do this explicitly, so we don't have to initialize the character set twice. - for (spot = this->data(), limit = this->data_end(); spot < limit && valid[static_cast<uint8_t>(*spot)]; ++spot) + for (spot = this->data(), limit = this->data_end(); spot < limit && delimiters(*spot); ++spot) ; this->remove_prefix(spot - this->data()); spot = this->data_end(); limit = this->data(); - while (limit < spot-- && valid[static_cast<uint8_t>(*spot)]) - ; + while (limit < spot-- && delimiters(*spot)) { + } this->remove_suffix(this->data_end() - (spot + 1)); return *this; } +inline TextView & +TextView::trim(std::string_view const &delimiters) { + return this->trim(CharSet(delimiters)); +} + inline TextView & TextView::trim(const char *delimiters) { - return this->trim(std::string_view(delimiters)); + return this->trim(CharSet(delimiters)); } template <typename F> diff --git a/code/src/bw_format.cc b/code/src/bw_format.cc index de62200..83f1689 100644 --- a/code/src/bw_format.cc +++ b/code/src/bw_format.cc @@ -905,8 +905,7 @@ bwformat(BufferWriter &w, bwf::Spec const &spec, std::error_code const &ec) { // This provides convenient safe access to the errno short name array. static const swoc::bwf::Format number_fmt{"[{}]"_sv}; // numeric value format. - if (spec.has_numeric_type()) { - // if numeric type, print just the numeric part. + if (spec.has_numeric_type()) { // if numeric type, print just the numeric part. bwformat(w, spec, ec.value()); } else { if ((&ec.category() == G_CAT || &ec.category() == S_CAT) && swoc::ERRNO_RANGE.contains(ec.value())) { @@ -915,7 +914,6 @@ bwformat(BufferWriter &w, bwf::Spec const &spec, std::error_code const &ec) { w.write(ec.message()); } if (spec._type != 's' && spec._type != 'S') { - bwformat(w, spec, ec.value()); w.write(' ').write('[').format(spec, ec.value()).write(']'); } } diff --git a/unit_tests/test_Errata.cc b/unit_tests/test_Errata.cc index acb41a0..da766ca 100644 --- a/unit_tests/test_Errata.cc +++ b/unit_tests/test_Errata.cc @@ -10,6 +10,7 @@ #include "swoc/bwf_std.h" #include "swoc/bwf_ex.h" #include "swoc/swoc_file.h" +#include "swoc/Lexicon.h" #include "catch.hpp" using swoc::Errata; @@ -29,6 +30,42 @@ std::array<swoc::TextView, 5> Severity_Names{ {"Debug", "Diag", "Info", "Warn", "Error"} }; +enum class ECode { + ALPHA = 1, + BRAVO, + CHARLIE +}; + +struct e_category : std::error_category { + const char *name() const noexcept override; + std::string message(int ev) const override; +}; + +e_category e_cat; + +const char * +e_category::name() const noexcept +{ + return "libswoc"; +} + +std::string +e_category::message(int ev) const +{ + static swoc::Lexicon<ECode> lexicon { + { + { ECode::ALPHA , "Alpha" }, + { ECode::BRAVO, "Bravo"}, + { ECode::CHARLIE, "Charlie"} + } + , "Code out of range" + }; + + return std::string(lexicon[ECode(ev)]); +} + +inline std::error_code ecode(ECode c) { return { int(c) , e_cat }; } + std::string ErrataSinkText; // Call from unit test main before starting tests. @@ -376,3 +413,12 @@ TEST_CASE("Errata Wrapper", "[libswoc][errata]") { REQUIRE(errata.front().text().starts_with("ni itchi - EINVAL")); } } + +TEST_CASE("Errata Autotext", "[libswoc][errata]") { + Errata a{ERRATA_WARN, Errata::AUTO}; + REQUIRE(a.front().text() == "Warn"); + Errata b{ecode(ECode::BRAVO), Errata::AUTO}; + REQUIRE(b.front().text() == "Bravo [2]"); + Errata c{ecode(ECode::ALPHA), ERRATA_ERROR, Errata::AUTO}; + REQUIRE(c.front().text() == "Error: Alpha [1]"); +}
