Skip to content

Commit

Permalink
Pattern: reduce code duplication for writing strings
Browse files Browse the repository at this point in the history
Signed-off-by: Pavel Artsishevsky <polter.rnd@gmail.com>
  • Loading branch information
polter-rnd committed Dec 17, 2024
1 parent fb9b0d1 commit 3657efb
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 30 deletions.
35 changes: 16 additions & 19 deletions include/slimlog/pattern-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,10 @@ auto Pattern<Char>::format(auto& out, Record<Char, StringType>& record) -> void
Util::Types::Overloaded{
[&out, &value = item.value](std::reference_wrapper<StringType> arg) {
if constexpr (Detail::HasConvertString<Char, StringType>) {
format_string(out, value, ConvertString<Char, StringType>{}(arg.get()));
format_string(
out,
value,
RecordStringView{ConvertString<Char, StringType>{}(arg.get())});
} else {
(void)out;
(void)value;
Expand Down Expand Up @@ -255,22 +258,16 @@ void Pattern<Char>::compile(StringViewType pattern)

template<typename Char>
template<typename StringView>
requires(
std::same_as<std::remove_cvref_t<StringView>, RecordStringView<Char>>
|| std::same_as<std::remove_cvref_t<StringView>, RecordStringView<char>>)
void Pattern<Char>::format_string(auto& out, const auto& item, StringView&& data)
{
constexpr auto CountCodepoints = [](StringView& src) {
if constexpr (std::is_same_v<StringView, StringViewType>) {
return Util::Unicode::count_codepoints(src.data(), src.size());
} else {
return src.codepoints();
}
};
const auto codepoints = CountCodepoints(data);

if (auto& specs = std::get<typename Placeholder::StringSpecs>(item); specs.width > 0)
[[unlikely]] {
write_string_padded(out, std::forward<StringView>(data), specs, codepoints);
write_string_padded(out, std::forward<StringView>(data), specs);
} else {
write_string(out, std::forward<StringView>(data), codepoints);
write_string(out, std::forward<StringView>(data));
}
}

Expand Down Expand Up @@ -429,15 +426,14 @@ auto Pattern<Char>::get_string_specs(StringViewType value) -> Placeholder::Strin

template<typename Char>
template<typename StringView>
constexpr void Pattern<Char>::write_string(auto& dst, StringView&& src, std::size_t codepoints)
constexpr void Pattern<Char>::write_string(auto& dst, StringView&& src)
{
using DataChar = typename std::remove_cvref_t<StringView>::value_type;
if constexpr (std::is_same_v<DataChar, char> && !std::is_same_v<Char, char>) {
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<StringView>(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<StringView>(src));
Expand All @@ -447,9 +443,10 @@ constexpr void Pattern<Char>::write_string(auto& dst, StringView&& src, std::siz
template<typename Char>
template<typename StringView>
constexpr void Pattern<Char>::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
Expand Down Expand Up @@ -497,7 +494,7 @@ constexpr void Pattern<Char>::write_string_padded(
}

// Fill data
write_string(dst, std::forward<StringView>(src), codepoints);
write_string(dst, std::forward<StringView>(src));

// Fill right padding
if (right_padding != 0) {
Expand Down
13 changes: 8 additions & 5 deletions include/slimlog/pattern.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@

#include <array>
#include <chrono>
#include <concepts>
#include <cstddef>
#include <cstdint>
#include <initializer_list>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include <variant>
#include <vector>
Expand Down Expand Up @@ -265,6 +267,9 @@ class Pattern {
* @param data Source string to be formatted.
*/
template<typename StringView>
requires(
std::same_as<std::remove_cvref_t<StringView>, RecordStringView<Char>>
|| std::same_as<std::remove_cvref_t<StringView>, RecordStringView<char>>)
static void format_string(auto& out, const auto& item, StringView&& data);

/**
Expand Down Expand Up @@ -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<typename StringView>
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.
Expand All @@ -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<typename StringView>
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<Char> m_pattern;
std::vector<Placeholder> m_placeholders;
Expand Down
11 changes: 5 additions & 6 deletions include/slimlog/util/unicode.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include <iterator>
#include <limits>
#include <stdexcept>
#include <string_view>

namespace SlimLog::Util::Unicode {

Expand Down Expand Up @@ -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<typename Char>
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<Char, wchar_t>) {
std::mbstate_t state = {};
#if defined(_WIN32) and defined(__STDC_WANT_SECURE_LIB__)
Expand All @@ -296,7 +295,7 @@ constexpr auto from_multibyte(Char* dest, std::string_view data, std::size_t cod
#endif
} else {
Detail::FromMultibyte<Char> 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) {
Expand Down

0 comments on commit 3657efb

Please sign in to comment.