From 5d964cd61c864be84fb6b102fb5b7a21a576b7fb Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Thu, 6 Aug 2026 13:27:13 +0300 Subject: [PATCH] ... --- examples/str_exam.cpp | 12 +++ include/snipplib/concepts/snplib_traits.h | 37 ++++++++ include/snipplib/utils/snplib_keyvalue_expr.h | 85 ++++++++++++++++--- 3 files changed, 124 insertions(+), 10 deletions(-) diff --git a/examples/str_exam.cpp b/examples/str_exam.cpp index 82d41db..0b84659 100644 --- a/examples/str_exam.cpp +++ b/examples/str_exam.cpp @@ -88,8 +88,20 @@ int main() snplib_keyvalue_expr_t kv1; kv1.setKeyValue("KEY", 7.7); + kv1.appendValue(std::string{"dekjlwe"}); + kv1.appendValue(100); + std::println("key = '{}'", kv1.key()); std::println("value = '{}'", kv1.value()); + std::println("valueSeq = '{}'\n", kv1.valueSeq()); + + si = std::string{"dekjlwe"}; + kv1.setValue(7.7, snplib_serialization_params_t{}, si, snplib_serialization_params_t{}, 100, + snplib_serialization_params_t{}); + + std::println("key = '{}'", kv1.key()); + std::println("value = '{}'", kv1.value()); + std::println("valueSeq = '{}'\n", kv1.valueSeq()); snplib_random_string_generator_t<> rstr_gen; diff --git a/include/snipplib/concepts/snplib_traits.h b/include/snipplib/concepts/snplib_traits.h index 1791b89..6b975db 100644 --- a/include/snipplib/concepts/snplib_traits.h +++ b/include/snipplib/concepts/snplib_traits.h @@ -82,4 +82,41 @@ template using snplib_func_arg1_t = typename snplib_func_traits_t::arg1_t; +/* create a std::tuple from the input types except the last one*/ +template +struct snplib_tuple_except_last_helper_t; + +template +struct snplib_tuple_except_last_helper_t { + using tuple_t = std::tuple<>; +}; + +template +struct snplib_tuple_except_last_helper_t { + using tuple_t = + decltype(std::tuple_cat(std::declval>(), + std::declval::tuple_t>())); +}; + + +template +using snplib_tuple_except_last_t = typename snplib_tuple_except_last_helper_t::tuple_t; + + +template +struct snplib_last_in_pack_helper_t; + +template +struct snplib_last_in_pack_helper_t { + using type = T; +}; + +template +struct snplib_last_in_pack_helper_t { + using type = typename snplib_last_in_pack_helper_t::type; +}; + +template +using snplib_last_in_pack_t = typename snplib_last_in_pack_helper_t::type; + } // namespace snplib \ No newline at end of file diff --git a/include/snipplib/utils/snplib_keyvalue_expr.h b/include/snipplib/utils/snplib_keyvalue_expr.h index 1f8d445..1c5b497 100644 --- a/include/snipplib/utils/snplib_keyvalue_expr.h +++ b/include/snipplib/utils/snplib_keyvalue_expr.h @@ -2,6 +2,7 @@ #include "../concepts/snplib_concepts.h" #include "../serialization/snplib_serialization.h" +#include "snipplib/concepts/snplib_traits.h" namespace snplib { @@ -239,27 +240,91 @@ public: return snplib_deduced_error(err, std::make_error_code(std::errc::invalid_argument)); } - // it can be a reallocation of the byte sequence so one needs to reinit _key and _value + // a reallocation of the byte sequence may occur so one needs to reinit _key and _value auto it = _byteSeq.begin(); std::advance(it, key_sz); _key = {_byteSeq.begin(), it}; std::advance(it, _config.keyval_delim.size()); _value = {it, _byteSeq.end()}; - // _valueSeq = snplib_split_char_range(_value, _config.valseq_delim); + _valueSeq.resize(1); _valueSeq[0] = _value; return {}; } - // template - // requires mutableContent - // error_t appendValue(ValueT&& value, SParT sparams = snplib_serialization_params_t{}) - // { - // if (_valueSeq.empty()) { - // return setValue(std::forward(value), std::move(sparams)); - // } - // } + // value1, ser-pars1, value2, ser-pars2, ..., valueN, ser-parsN + template + requires(mutableContent && sizeof...(ValSerParPairTs) >= 4 && (sizeof...(ValSerParPairTs) % 2 == 0)) + error_t setValue(ValSerParPairTs&&... pairs) + { + constexpr auto f = [](std::index_sequence) { + using args_t = std::tuple; + + return ((snplib_serializable_c> && + snplib_serialization_params_c>) && + ...); + }(std::make_index_sequence{}); + + _valueSeq.clear(); // to trigger the first call to setValue + return [this](this auto&& self, auto&& v1, auto&& sp1, auto&&... prs) -> error_t { + auto err = appendValue(std::forward(v1), std::forward(sp1)); + if (err) { + return snplib_deduced_error(err, std::make_error_code(std::errc::invalid_argument)); + } + + if constexpr (sizeof...(prs)) { + return std::forward(self)(std::forward(prs)...); + } + + return {}; + }(std::forward(pairs)...); + } + + template + requires(mutableContent && sizeof...(ArgTs) > 2) + error_t setVal(ArgTs&&... args) + { + static_assert(snplib_serialization_params_c>, ""); + + using args_t = snplib_tuple_except_last_t; + } + + + template + requires mutableContent + error_t appendValue(ValueT&& value, SParT sparams = snplib_serialization_params_t{}) + { + if (_valueSeq.empty()) { + return setValue(std::forward(value), std::move(sparams)); + } + + size_t key_sz = _key.size(); + + std::ranges::copy(_config.keyval_delim, std::back_inserter(_byteSeq)); + + auto it = _byteSeq.begin(); + std::advance(it, _key.size() + _config.keyval_delim.size()); + + auto prev_size = std::ranges::distance(_byteSeq); + + auto err = snplib_serializer_t>{}(_byteSeq, std::forward(value), sparams); + if (err) { + return snplib_deduced_error(err, std::make_error_code(std::errc::invalid_argument)); + } + + // a reallocation of the byte sequence may occur so one needs to reinit _key and _value + it = _byteSeq.begin(); + std::advance(it, key_sz); + _key = {_byteSeq.begin(), it}; + + std::advance(it, _config.keyval_delim.size()); + _value = {it, _byteSeq.end()}; + + _valueSeq = snplib_split_char_range(_value, _config.valseq_delim); + + return {}; + } template