#pragma once #include #include #include #include #include #include "../common/adc_traits.h" namespace adc::utils { static bool AdcIsSpace(char in) noexcept { static constexpr auto ws = {' ', '\t', '\n', '\v', '\r', '\f'}; return std::ranges::any_of(ws, [in](auto p) { return p == in; }); }; template static auto AdcTrimSpaces(R&& r) { return r | std::views::drop_while(AdcIsSpace) | std::views::reverse | std::views::drop_while(AdcIsSpace) | std::views::reverse; } template static ValueT AdcFromChars(R&& range) { if constexpr (std::is_arithmetic_v) { ValueT v; std::from_chars_result res; const char* end_ptr; // std::from_chars needs random-access container!!! if constexpr (std::ranges::random_access_range) { res = std::from_chars(&*range.begin(), &*range.end(), v); end_ptr = &*range.end(); } else { std::string s(range.begin(), range.end()); end_ptr = s.data() + s.size(); res = std::from_chars(s.data(), s.data() + s.size(), v); } if (res.ec == std::errc()) { if (res.ptr != end_ptr) { throw std::invalid_argument( "AdcFromChars: cannot convert char-range to user-type value (invalid argument)"); } return v; } else if (res.ec == std::errc::invalid_argument) { throw std::invalid_argument( "AdcFromChars: cannot convert char-range to user-type value (invalid argument)"); } else if (res.ec == std::errc::result_out_of_range) { throw std::invalid_argument( "AdcFromChars: cannot convert char-range to user-type value (result out of 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)"); // throw std::invalid_argument( // "AdcFromChars: cannot convert char-range to user-type value (unsupported user-value type)"); } } /* TRIVIAL SERIALIZER/DESERIALIZER */ static const std::regex AdcIntegerRegex("^ *[+-]?\\d+\\d* *$", std::regex::ECMAScript); static const std::regex AdcRealRegex("^ *[-+]?\\d+\\d*\\.?\\d*([Ee][-+]?\\d+)? *$", std::regex::ECMAScript); template static SerializedT AdcTrivialSerializer(VT&& value) { using v_t = std::decay_t; if constexpr (std::is_convertible_v) { return static_cast(std::forward(value)); } else if (traits::adc_char_range) { SerializedT s_val; std::format_to(std::back_inserter(s_val), "{}", std::forward(value)); return s_val; } else { // throw std::invalid_argument("trivial serializer: cannot serialize value"); static_assert(false, "TRIVIAL SERIALIZER: UNSUPPORTED SERIALIZING TYPE!!!"); } } template static VT AdcTrivialDeserializer(SerializedT&& s_value) { return AdcFromChars(std::forward(s_value)); } template OutputR AdcRangeFromCharRange(InputR&& input_r, DelimR&& delim, size_t max_len = std::numeric_limits::max()) { OutputR res; 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::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::back_inserter(res)); } return res; } } // namespace adc::utils