From 3657efb004a4f54aee4dad2caa98feb8f87e1ef7 Mon Sep 17 00:00:00 2001 From: Pavel Artsishevsky Date: Tue, 17 Dec 2024 21:04:41 +0100 Subject: [PATCH] Pattern: reduce code duplication for writing strings Signed-off-by: Pavel Artsishevsky --- include/slimlog/pattern-inl.h | 35 ++++++++++++++++------------------ include/slimlog/pattern.h | 13 ++++++++----- include/slimlog/util/unicode.h | 11 +++++------ 3 files changed, 29 insertions(+), 30 deletions(-) diff --git a/include/slimlog/pattern-inl.h b/include/slimlog/pattern-inl.h index 09e72ea..e8e27e5 100644 --- a/include/slimlog/pattern-inl.h +++ b/include/slimlog/pattern-inl.h @@ -146,7 +146,10 @@ auto Pattern::format(auto& out, Record& record) -> void Util::Types::Overloaded{ [&out, &value = item.value](std::reference_wrapper arg) { if constexpr (Detail::HasConvertString) { - format_string(out, value, ConvertString{}(arg.get())); + format_string( + out, + value, + RecordStringView{ConvertString{}(arg.get())}); } else { (void)out; (void)value; @@ -255,22 +258,16 @@ void Pattern::compile(StringViewType pattern) template template + requires( + std::same_as, RecordStringView> + || std::same_as, RecordStringView>) void Pattern::format_string(auto& out, const auto& item, StringView&& data) { - constexpr auto CountCodepoints = [](StringView& src) { - if constexpr (std::is_same_v) { - return Util::Unicode::count_codepoints(src.data(), src.size()); - } else { - return src.codepoints(); - } - }; - const auto codepoints = CountCodepoints(data); - if (auto& specs = std::get(item); specs.width > 0) [[unlikely]] { - write_string_padded(out, std::forward(data), specs, codepoints); + write_string_padded(out, std::forward(data), specs); } else { - write_string(out, std::forward(data), codepoints); + write_string(out, std::forward(data)); } } @@ -429,15 +426,14 @@ auto Pattern::get_string_specs(StringViewType value) -> Placeholder::Strin template template -constexpr void Pattern::write_string(auto& dst, StringView&& src, std::size_t codepoints) +constexpr void Pattern::write_string(auto& dst, StringView&& src) { using DataChar = typename std::remove_cvref_t::value_type; if constexpr (std::is_same_v && !std::is_same_v) { + const auto codepoints = src.codepoints(); dst.reserve(dst.size() + codepoints + 1); // Take into account null terminator - const std::size_t written = Util::Unicode::from_multibyte( - dst.end(), - std::forward(src), // NOLINT(cppcoreguidelines-slicing) - codepoints + 1); + const std::size_t written + = Util::Unicode::from_multibyte(dst.end(), codepoints + 1, src.data(), src.size()); dst.resize(dst.size() + written - 1); // Trim null terminator } else { dst.append(std::forward(src)); @@ -447,9 +443,10 @@ constexpr void Pattern::write_string(auto& dst, StringView&& src, std::siz template template constexpr void Pattern::write_string_padded( - auto& dst, StringView&& src, const Placeholder::StringSpecs& specs, std::size_t codepoints) + auto& dst, StringView&& src, const Placeholder::StringSpecs& specs) { const auto spec_width = Util::Types::to_unsigned(specs.width); + const auto codepoints = src.codepoints(); const auto padding = spec_width > codepoints ? spec_width - codepoints : 0; // Shifts are encoded as string literals because constexpr is not @@ -497,7 +494,7 @@ constexpr void Pattern::write_string_padded( } // Fill data - write_string(dst, std::forward(src), codepoints); + write_string(dst, std::forward(src)); // Fill right padding if (right_padding != 0) { diff --git a/include/slimlog/pattern.h b/include/slimlog/pattern.h index 86621d1..84acc42 100644 --- a/include/slimlog/pattern.h +++ b/include/slimlog/pattern.h @@ -11,11 +11,13 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -265,6 +267,9 @@ class Pattern { * @param data Source string to be formatted. */ template + requires( + std::same_as, RecordStringView> + || std::same_as, RecordStringView>) static void format_string(auto& out, const auto& item, StringView&& data); /** @@ -339,10 +344,9 @@ class Pattern { * @tparam StringView String view type, convertible to `std::basic_string_view`. * @param dst Destination buffer where the string will be written. * @param src Source string view to be written. - * @param codepoints Number of codepoints the source string contains. */ template - constexpr static void write_string(auto& dst, StringView&& src, std::size_t codepoints); + constexpr static void write_string(auto& dst, StringView&& src); /** * @brief Writes the source string to the destination buffer with specific alignment. @@ -354,11 +358,10 @@ class Pattern { * @param dst Destination buffer where the string will be written. * @param src Source string view to be written. * @param specs String specifications, including alignment and fill character. - * @param codepoints Number of codepoints the source string contains. */ template - constexpr static void write_string_padded( - auto& dst, StringView&& src, const Placeholder::StringSpecs& specs, std::size_t codepoints); + constexpr static void + write_string_padded(auto& dst, StringView&& src, const Placeholder::StringSpecs& specs); std::basic_string m_pattern; std::vector m_placeholders; diff --git a/include/slimlog/util/unicode.h b/include/slimlog/util/unicode.h index a2a5c75..e2d3b5a 100644 --- a/include/slimlog/util/unicode.h +++ b/include/slimlog/util/unicode.h @@ -18,7 +18,6 @@ #include #include #include -#include namespace SlimLog::Util::Unicode { @@ -270,16 +269,16 @@ constexpr auto to_ascii(Char chr) -> char * * @tparam Char Character type of the destination string. * @param dest Pointer to destination buffer for the converted string. - * @param data Source multi-byte string to be converted. * @param codepoints Number of codepoints to be written to the destination string. + * @param source Pointer to multi-byte string to be converted. + * @param source_size Source string length. * @return Number of characters written including null terminator. */ template -constexpr auto from_multibyte(Char* dest, std::string_view data, std::size_t codepoints) +constexpr auto +from_multibyte(Char* dest, std::size_t codepoints, const char* source, std::size_t source_size) { - const char* source = data.data(); std::size_t written = 0; - if constexpr (std::is_same_v) { std::mbstate_t state = {}; #if defined(_WIN32) and defined(__STDC_WANT_SECURE_LIB__) @@ -296,7 +295,7 @@ constexpr auto from_multibyte(Char* dest, std::string_view data, std::size_t cod #endif } else { Detail::FromMultibyte dispatcher; - for (auto source_size = data.size(); source_size > 0;) { + while (source_size > 0) { Char wchr; const int next = dispatcher.get(&wchr, source, source_size); switch (next) {