This commit is contained in:
Timur A. Fatkhullin
2025-10-28 01:11:34 +03:00
parent bdfc5dbc1c
commit 85dfa2e9a5
5 changed files with 337 additions and 200 deletions

View File

@@ -173,6 +173,15 @@ using mcc_func_argN_t = std::conditional_t<N >= mcc_func_traits<T>::arity,
void>;
// std::array
template <typename T>
concept mcc_array_c = requires(T t) {
[]<typename VT, size_t N>(std::array<VT, N>) {
}(t);
};
// non-const lvalue reference, constructible from CtorArgTs (an output argument of function)
template <typename T, typename... CtorArgTs>
concept mcc_output_arg_c = !std::is_const_v<std::remove_reference_t<T>> && std::is_lvalue_reference_v<T> &&

View File

@@ -158,7 +158,7 @@ static std::optional<double> parsAngleString(R&& r, bool hms = false)
return std::nullopt;
}
static std::optional<double> parsAngleString(const char* s, bool hms = false)
[[maybe_unused]] static std::optional<double> parsAngleString(const char* s, bool hms = false)
{
return parsAngleString(std::span{s, std::strlen(s)}, hms);
}
@@ -455,7 +455,21 @@ public:
value = v.value();
} else if constexpr (mcc::traits::mcc_output_char_range<VT>) {
VT r;
std::ranges::copy(bytes, std::back_inserter(r));
if constexpr (traits::mcc_array_c<VT>) {
size_t N =
std::ranges::size(r) <= std::ranges::size(bytes) ? std::ranges::size(r) : std::ranges::size(bytes);
for (size_t i = 0; i < N; ++i) {
r[i] = bytes[i];
}
if (std::ranges::size(r) > N) {
for (size_t i = N; i < std::ranges::size(r); ++i) {
r[i] = '\0';
}
}
} else {
std::ranges::copy(bytes, std::back_inserter(r));
}
value = r;
} else if constexpr (std::ranges::range<VT>) {
using el_t = std::ranges::range_value_t<VT>;
@@ -466,13 +480,21 @@ public:
VT r;
el_t elem;
size_t i = 0;
auto els = std::views::split(bytes, _rangeDelim);
for (auto const& el : els) {
ret = (*this)(std::string_view(el), elem);
if (!ret) {
std::back_inserter(r) = elem;
if constexpr (traits::mcc_array_c<VT>) {
if (i < std::ranges::size(r)) {
r[i] = elem;
}
++i;
} else {
std::back_inserter(r) = elem;
}
} else {
return std::make_error_code(std::errc::invalid_argument);
}
@@ -582,7 +604,7 @@ public:
}
template <typename T>
std::expected<T, std::error_code> getValue(std::string_view key)
std::expected<T, std::error_code> getValue(std::string_view key) const
{
T v;
auto err = forKey(key, [&v]<typename VT>(const VT& val) {
@@ -686,20 +708,27 @@ protected:
std::array<size_t, std::tuple_size_v<DESCR_T>> _hashes;
std::error_code forKey(std::string_view key, auto&& func)
//
// NOTE: deduced this is needed here to use "forKey" method in getter and setter (const and non-const contexts)!!!
//
std::error_code forKey(this auto&& self, std::string_view key, auto&& func)
{
return forHash<0>(FNV1aHash(key), std::forward<decltype(func)>(func));
return std::forward<decltype(self)>(self).template forHash<0>(FNV1aHash(key),
std::forward<decltype(func)>(func));
}
template <size_t I = 0>
std::error_code forHash(size_t hash, auto&& func)
std::error_code forHash(this auto&& self, size_t hash, auto&& func)
{
if constexpr (I < std::tuple_size_v<DESCR_T>) {
if (hash == _hashes[I]) {
return std::forward<decltype(func)>(func)(std::get<I>(_keyValue).value);
if (hash == std::forward<decltype(self)>(self)._hashes[I]) {
return std::forward<decltype(func)>(func)(
std::get<I>(std::forward<decltype(self)>(self)._keyValue).value);
} else {
return forHash<I + 1>(hash, std::forward<decltype(func)>(func));
return std::forward<decltype(self)>(self).template forHash<I + 1>(hash,
std::forward<decltype(func)>(func));
}
}