This commit is contained in:
Timur A. Fatkhullin 2024-01-23 23:30:48 +03:00
parent fa0cfea8fe
commit 969429d2f6
2 changed files with 78 additions and 15 deletions

View File

@ -1,9 +1,9 @@
#pragma once
#include <format>
#include <ranges>
#include <tuple>
#include <type_traits>
#include <format>
/*
@ -17,16 +17,28 @@ namespace adc::traits
{
// check if type can be used with std::format_to
// (from https://stackoverflow.com/questions/72430369/how-to-check-that-a-type-is-formattable-using-type-traits-concepts)
template<typename T>
concept formattable = requires (T& v, std::format_context ctx) {
std::formatter<std::remove_cvref_t<T>>().format(v, ctx);
};
// (from
// https://stackoverflow.com/questions/72430369/how-to-check-that-a-type-is-formattable-using-type-traits-concepts)
template <typename T>
concept formattable =
requires(T& v, std::format_context ctx) { std::formatter<std::remove_cvref_t<T>>().format(v, ctx); };
// range of char/const char
template <typename R, typename CharT = char>
concept adc_char_range = std::ranges::range<R> && std::is_same_v<std::remove_cv_t<std::ranges::range_value_t<R>>, CharT>;
concept adc_char_range =
std::ranges::range<R> && std::is_same_v<std::remove_cv_t<std::ranges::range_value_t<R>>, CharT>;
// output range of char/const char
template <typename R, typename CharT = char>
concept adc_output_char_range = std::ranges::output_range<R, CharT>;
// range of char/const char
template <typename R, typename CharT = char>
concept adc_input_char_range = std::ranges::input_range<CharT>;
// deduce returned type of callable
template <typename T>

View File

@ -63,7 +63,8 @@ static ValueT AdcFromChars(R&& range)
} else if (std::is_constructible_v<ValueT, std::ranges::iterator_t<R>, std::ranges::iterator_t<R>>) {
return ValueT(range.begin(), range.end());
} else {
static_assert(false, "AdcFromChars: CANNOT CONVERT CHAR-RANGE TO USER-TYPE VALUE (UNSUPPORTED USER-VALUE TYPE)");
static_assert(false,
"AdcFromChars: CANNOT CONVERT CHAR-RANGE TO USER-TYPE VALUE (UNSUPPORTED USER-VALUE TYPE)");
// throw std::invalid_argument(
// "AdcFromChars: cannot convert char-range to user-type value (unsupported user-value type)");
}
@ -82,7 +83,7 @@ static SerializedT AdcTrivialSerializer(VT&& value)
if constexpr (std::is_convertible_v<v_t, SerializedT>) {
return static_cast<SerializedT>(std::forward<VT>(value));
} else if (traits::adc_char_range<SerializedT>) {
} else if (traits::adc_output_char_range<SerializedT>) {
SerializedT s_val;
std::format_to(std::back_inserter(s_val), "{}", std::forward<VT>(value));
return s_val;
@ -96,33 +97,83 @@ static SerializedT AdcTrivialSerializer(VT&& value)
template <typename VT, typename SerializedT = std::string>
static VT AdcTrivialDeserializer(SerializedT&& s_value)
{
return AdcFromChars<VT>(std::forward<SerializedT>(s_value));
if constexpr (std::is_convertible_v<SerializedT, VT>) {
return static_cast<VT>(std::forward<SerializedT>(s_value));
} else if (traits::adc_input_char_range<SerializedT>) {
return AdcFromChars<VT>(std::forward<SerializedT>(s_value));
} else {
static_assert(false, "TRIVIAL DESERIALIZER: UNSUPPORTED SERIALIZING TYPE!!!");
}
}
template <std::ranges::range OutputR, traits::adc_char_range InputR, traits::adc_char_range DelimR>
OutputR AdcRangeFromCharRange(InputR&& input_r, DelimR&& delim, size_t max_len = std::numeric_limits<size_t>::max())
template <std::ranges::range OutputR, traits::adc_input_char_range InputR, traits::adc_input_char_range DelimR>
OutputR AdcValueRangeFromCharRange(InputR&& input_r,
DelimR&& delim,
size_t max_len = std::numeric_limits<size_t>::max())
{
OutputR res;
if (max_len == 0)
if (max_len == 0) {
return res;
}
using value_t = std::ranges::range_value_t<OutputR>;
if constexpr (std::is_array_v<std::remove_cvref_t<DelimR>>) {
std::ranges::copy(std::views::split(std::forward<InputR>(input_r), std::string_view(delim)) |
std::views::filter([](const auto& r) { return !std::ranges::empty(r); }) |
std::views::transform([](auto vl) { return convFunc<value_t>(vl); }) | std::views::take(max_len),
std::views::transform([](auto vl) { return AdcTrivialDeserializer<value_t>(vl); }) |
std::views::take(max_len),
std::back_inserter(res));
} else {
std::ranges::copy(std::views::split(std::forward<InputR>(input_r), std::forward<DelimR>(delim)) |
std::views::filter([](const auto& r) { return !std::ranges::empty(r); }) |
std::views::transform([](auto vl) { return convFunc<value_t>(vl); }) | std::views::take(max_len),
std::views::transform([](auto vl) { return AdcTrivialDeserializer<value_t>(vl); }) |
std::views::take(max_len),
std::back_inserter(res));
}
return res;
}
template <traits::adc_output_char_range OutputR, std::ranges::range InputR, traits::adc_input_char_range DelimR>
OutputR AdcCharRangeFromValueRange(InputR&& input_r,
DelimR&& delim,
size_t max_len = std::numeric_limits<size_t>::max())
{
OutputR res;
max_len = max_len < std::ranges::size(input_r) ? max_len : std::ranges::size(input_r);
if (max_len == 0) {
return res;
}
--max_len;
if (max_len) {
auto view = input_r | std::views::take(max_len) | std::views::transform([&delim](auto v) {
auto r = AdcTrivialSerializer<OutputR>(v);
std::ranges::copy(delim, std::back_inserter(r));
return r;
}) |
std::views::join;
std::ranges::copy(view, std::back_inserter(res));
auto view1 = input_r | std::views::drop(max_len) | std::views::take(1) | std::views::transform([](auto v) {
auto r = AdcTrivialSerializer<OutputR>(v);
return r;
}) |
std::views::join;
std::ranges::copy(view1, std::back_inserter(res));
} else {
res = AdcTrivialSerializer<OutputR>(*std::forward<InputR>(input_r).begin());
}
return res;
}
} // namespace adc::utils