diff --git a/common/adc_traits.h b/common/adc_traits.h index a79b91b..f7f47ba 100644 --- a/common/adc_traits.h +++ b/common/adc_traits.h @@ -1,9 +1,9 @@ #pragma once +#include #include #include #include -#include /* @@ -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 -concept formattable = requires (T& v, std::format_context ctx) { - std::formatter>().format(v, ctx); -}; +// (from +// https://stackoverflow.com/questions/72430369/how-to-check-that-a-type-is-formattable-using-type-traits-concepts) +template +concept formattable = + requires(T& v, std::format_context ctx) { std::formatter>().format(v, ctx); }; // range of char/const char template -concept adc_char_range = std::ranges::range && std::is_same_v>, CharT>; +concept adc_char_range = + std::ranges::range && std::is_same_v>, CharT>; + + +// output range of char/const char +template +concept adc_output_char_range = std::ranges::output_range; + + +// range of char/const char +template +concept adc_input_char_range = std::ranges::input_range; + // deduce returned type of callable template diff --git a/common/adc_utils.h b/common/adc_utils.h index f46b239..e2c068e 100644 --- a/common/adc_utils.h +++ b/common/adc_utils.h @@ -63,7 +63,8 @@ static ValueT AdcFromChars(R&& range) } else if (std::is_constructible_v, std::ranges::iterator_t>) { 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) { return static_cast(std::forward(value)); - } else if (traits::adc_char_range) { + } else if (traits::adc_output_char_range) { SerializedT s_val; std::format_to(std::back_inserter(s_val), "{}", std::forward(value)); return s_val; @@ -96,33 +97,83 @@ static SerializedT AdcTrivialSerializer(VT&& value) template static VT AdcTrivialDeserializer(SerializedT&& s_value) { - return AdcFromChars(std::forward(s_value)); + if constexpr (std::is_convertible_v) { + return static_cast(std::forward(s_value)); + } else if (traits::adc_input_char_range) { + return AdcFromChars(std::forward(s_value)); + } else { + static_assert(false, "TRIVIAL DESERIALIZER: UNSUPPORTED SERIALIZING TYPE!!!"); + } } -template -OutputR AdcRangeFromCharRange(InputR&& input_r, DelimR&& delim, size_t max_len = std::numeric_limits::max()) +template +OutputR AdcValueRangeFromCharRange(InputR&& input_r, + DelimR&& delim, + size_t max_len = std::numeric_limits::max()) { OutputR res; - if (max_len == 0) + if (max_len == 0) { return res; + } using value_t = std::ranges::range_value_t; if constexpr (std::is_array_v>) { std::ranges::copy(std::views::split(std::forward(input_r), std::string_view(delim)) | std::views::filter([](const auto& r) { return !std::ranges::empty(r); }) | - std::views::transform([](auto vl) { return convFunc(vl); }) | std::views::take(max_len), + std::views::transform([](auto vl) { return AdcTrivialDeserializer(vl); }) | + std::views::take(max_len), std::back_inserter(res)); } else { std::ranges::copy(std::views::split(std::forward(input_r), std::forward(delim)) | std::views::filter([](const auto& r) { return !std::ranges::empty(r); }) | - std::views::transform([](auto vl) { return convFunc(vl); }) | std::views::take(max_len), + std::views::transform([](auto vl) { return AdcTrivialDeserializer(vl); }) | + std::views::take(max_len), std::back_inserter(res)); } return res; } + +template +OutputR AdcCharRangeFromValueRange(InputR&& input_r, + DelimR&& delim, + size_t max_len = std::numeric_limits::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(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(v); + return r; + }) | + std::views::join; + std::ranges::copy(view1, std::back_inserter(res)); + } else { + res = AdcTrivialSerializer(*std::forward(input_r).begin()); + } + + return res; +} + } // namespace adc::utils