Add utils::RangeToWrapper

This commit is contained in:
sha512sum 2024-10-29 12:17:08 +00:00
parent 15d4fd00d0
commit 405a3100e1
2 changed files with 43 additions and 21 deletions

View file

@ -1,7 +1,7 @@
#pragma once
#include <libxml++/libxml++.h>
#include <algorithm>
#include <larra/utils.hpp>
#include <nameof.hpp>
#include <ranges>
#include <variant>
@ -23,20 +23,18 @@ constexpr auto ToKebabCaseName() -> std::string_view {
static constexpr auto rawStr = nameof::nameof_short_type<T>();
constexpr auto str = [] {
return rawStr | std::views::transform([](auto ch) {
return impl::IsUpper(ch) ? std::array<char, 2>{'-', impl::ToLower(ch)} : std::array<char, 2>{ch, '\0'};
}) |
std::views::join | std::views::filter([](char ch) {
return ch != '\0';
});
return rawStr //
| std::views::transform([](auto ch) {
return impl::IsUpper(ch) ? std::array<char, 2>{'-', impl::ToLower(ch)} : std::array<char, 2>{ch, '\0'};
}) //
| std::views::join //
| std::views::filter([](char ch) {
return ch != '\0';
}) //
| std::views::drop(1);
};
constexpr auto size = std::ranges::distance(str()) - 1;
static constexpr auto arr = [&] {
std::array<char, size> response; // NOLINT
std::ranges::copy(str() | std::views::drop(1), response.begin());
return response;
}();
return {arr.data(), size};
static constexpr auto arr = str() | std::ranges::to<utils::RangeToWrapper<std::array<char, std::ranges::distance(str())>>>();
return {arr.data(), arr.size()};
}
} // namespace impl
@ -53,15 +51,11 @@ struct ErrorImpl : BaseError {
static inline const auto kKebabCaseName = static_cast<std::string>(impl::ToKebabCaseName<T>());
static constexpr auto kErrorMessage = [] -> std::string_view {
static constexpr auto name = nameof::nameof_short_type<T>();
static constexpr auto str = [] {
return std::array{std::string_view{"Stream Error: "}, nameof::nameof_short_type<T>(), std::string_view{"\0", 1}} | std::views::join;
return std::array{std::string_view{"Stream Error: "}, std::string_view{name}, std::string_view{"\0", 1}} | std::views::join;
};
constexpr auto size = std::ranges::distance(str());
static constexpr auto array = [&] {
std::array<char, size> response; // NOLINT
std::ranges::copy(str(), response.begin());
return response;
}();
static constexpr auto array = str() | std::ranges::to<utils::RangeToWrapper<std::array<char, std::ranges::distance(str())>>>();
return {array.data(), array.size() - 1};
}();
static constexpr auto TryParse(xmlpp::Element* element) -> std::optional<T> {

View file

@ -267,4 +267,32 @@ inline auto StartLifetimeAs(const void* ptr) -> const T* {
#endif
// Example: "Hello" | std::ranges::to<RangeToWrapper<std::array<char, 6>>>()
template <typename T>
struct RangeToWrapper : T {
[[nodiscard]] constexpr auto Base() & -> decltype(auto) {
return static_cast<T&>(*this);
}
[[nodiscard]] constexpr auto Base() const& -> decltype(auto) {
return static_cast<const T&>(*this);
}
[[nodiscard]] constexpr auto Base() && -> decltype(auto) {
return static_cast<T&&>(*this);
}
[[nodiscard]] constexpr auto Base() const&& -> decltype(auto) {
return static_cast<const T&&>(*this);
}
template <typename Range> // NOLINTNEXTLINE
constexpr RangeToWrapper(std::from_range_t, Range&& range) {
auto result = std::ranges::copy(range, this->begin());
if(result.in != std::ranges::end(range) || result.out != std::ranges::end(*this)) {
throw std::invalid_argument{"Invalid range size"};
}
}
template <typename... Args> // NOLINTNEXTLINE
constexpr RangeToWrapper(Args&&... args)
requires requires { T{std::forward<Args>(args)...}; }
: T{std::forward<Args>(args)...} {};
};
} // namespace larra::xmpp::utils