From 1a80e70e0c84abf5a6e0138efff737f61b9b9317 Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Mon, 29 Jun 2026 18:46:44 +0300 Subject: [PATCH] ... --- CMakeLists.txt | 3 +- examples/str_exam.cpp | 8 +- include/snipplib/concepts/snplib_concepts.h | 41 +++++++ include/snipplib/containers/snplib_hmap.h | 3 + include/snipplib/network/snplib_endpoint.h | 2 + include/snipplib/network/snplib_network.h | 100 +++++++++++++++ ...plib_keyvalue.h => snplib_keyvalue_expr.h} | 116 +++++------------- include/snipplib/utils/snplib_string.h | 1 + 8 files changed, 181 insertions(+), 93 deletions(-) create mode 100644 include/snipplib/network/snplib_network.h rename include/snipplib/utils/{snplib_keyvalue.h => snplib_keyvalue_expr.h} (62%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 50ccb2e..d5418ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ set(LIB_HEADERS include/snipplib/concepts/snplib_traits.h include/snipplib/utils/snplib_hash.h include/snipplib/utils/snplib_string.h + include/snipplib/utils/snplib_keyvalue_expr.h include/snipplib/utils/snplib_utils.h include/snipplib/containers/snplib_hmap.h include/snipplib/serialization/snplib_serialization.h @@ -33,7 +34,6 @@ if(BUILD_EXAMPLES) target_link_libraries(${EXAM_HMAP} ${PROJECT_NAME}) endif() - include(GNUInstallDirs) include(CMakePackageConfigHelpers) @@ -44,7 +44,6 @@ install( RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) - set(SNPLIB_CONFIG_INSTALLDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} # CACHE PATH diff --git a/examples/str_exam.cpp b/examples/str_exam.cpp index 839342d..0f9be7d 100644 --- a/examples/str_exam.cpp +++ b/examples/str_exam.cpp @@ -1,9 +1,7 @@ #include #include -// #include "../utils/snplib_string.h" -// #include "../include/snipplib/snplib_string.h" -#include +#include #include using namespace snplib; @@ -63,7 +61,7 @@ int main() std::vector v{std::from_range, si}; ll = {std::from_range, si}; - snplib_keyvalue_t kv{v}; + snplib_keyvalue_expr_t kv{v}; std::println("\n\nKV = {}", v); std::println("key = '{}'", kv.key()); @@ -75,7 +73,7 @@ int main() kv.setKeyValue("VAL", std::make_tuple(1, std::string{"RRR"}, 10.24)); std::println("\n\nKV = {}", v); - snplib_keyvalue_t kvl{ll}; + snplib_keyvalue_expr_t kvl{ll}; std::println("\n\nKV = {}", ll); std::println("key = '{}'", kvl.key()); diff --git a/include/snipplib/concepts/snplib_concepts.h b/include/snipplib/concepts/snplib_concepts.h index 9bcca7a..85caeba 100644 --- a/include/snipplib/concepts/snplib_concepts.h +++ b/include/snipplib/concepts/snplib_concepts.h @@ -2,6 +2,9 @@ #include #include +#include +#include +#include #include namespace snplib @@ -154,4 +157,42 @@ static auto snplib_deduced_error(ErrT const& err, FallbackErrT const& fallback_e } } + +template +concept snplib_expected_c = requires { + [](std::type_identity>) { + }(std::type_identity>{}); +}; + +// template +// concept snplib_expected_c = requires { +// [](std::type_identity>) { +// }(std::type_identity>{}); +// }; + + +// result of asynchronous callable + +template +concept snplib_awaiter_c = requires(T t, std::coroutine_handle<> hndl) { + { t.await_ready() } -> std::convertible_to; + + // await_suspend can return void, bool, or a coroutine_handle + t.await_suspend(hndl); + + // await_resume must return the specific type UT + { t.await_resume() } -> std::same_as; +}; + + +template +concept snplib_awaitable_c = snplib_awaiter_c || requires(T t) { + { t.operator co_await() } -> snplib_awaiter_c; +}; + + +template +concept snplib_async_retval_c = snplib_awaitable_c && snplib_expected_c; + + } // namespace snplib \ No newline at end of file diff --git a/include/snipplib/containers/snplib_hmap.h b/include/snipplib/containers/snplib_hmap.h index 815620e..0f8cb71 100644 --- a/include/snipplib/containers/snplib_hmap.h +++ b/include/snipplib/containers/snplib_hmap.h @@ -11,6 +11,9 @@ namespace snplib { +/* AN UNORDERED MAP WITH ABILITY OF STORING DIFFERENT TYPE VALUES */ +/* (A HETEROGENEOUS UNORDERED MAP) */ + template class HeterogenMap diff --git a/include/snipplib/network/snplib_endpoint.h b/include/snipplib/network/snplib_endpoint.h index 316826e..efad640 100644 --- a/include/snipplib/network/snplib_endpoint.h +++ b/include/snipplib/network/snplib_endpoint.h @@ -40,6 +40,8 @@ namespace snplib class snplib_endpoint_t { public: + static constexpr std::string_view id{"SNPLIB-NET-ENDPOINT"}; + static constexpr std::string_view protoHostDelim = "://"; static constexpr std::string_view hostPortDelim = ":"; static constexpr std::string_view portPathDelim = "/"; diff --git a/include/snipplib/network/snplib_network.h b/include/snipplib/network/snplib_network.h new file mode 100644 index 0000000..ee7964f --- /dev/null +++ b/include/snipplib/network/snplib_network.h @@ -0,0 +1,100 @@ +#pragma once + +#include "../concepts/snplib_concepts.h" + +namespace snplib +{ + + +template +concept snplib_net_endpoint_c = requires(T t, const T t_const) { + // static constexpr member + std::formattable; + []() { [[maybe_unused]] static constexpr auto val = T::id; }(); + + { t.endpoint() } -> snplib_char_range_c; + + { t_const.proto() } -> std::formattable; + { t_const.host() } -> std::formattable; + { t_const.path() } -> std::formattable; + { t_const.port() } -> std::formattable; +}; + + +template +concept snplib_net_connection_c = requires(T t) { + // static constexpr member + std::formattable; + []() { [[maybe_unused]] static constexpr auto val = T::id; }(); + + typename T::message_t; // minimal allowed unit of read/write operations + + { t.send(std::declval()) } -> snplib_async_retval_c; + { t.recv() } -> snplib_async_retval_c; + + t.close(); +}; + + +template +concept snplib_net_session_c = std::derived_from> && requires(T t) { + // static constexpr member + std::formattable; + []() { [[maybe_unused]] static constexpr auto val = T::id; }(); + + snplib_net_connection_c; + + { t.start(std::declval()) } -> snplib_async_retval_c; + + t.stop(); +}; + + +template +concept snplib_net_listener_c = requires(T t) { + // static constexpr member + std::formattable; + []() { [[maybe_unused]] static constexpr auto val = T::id; }(); + + snplib_net_session_c; + + { t.accept() } -> snplib_async_retval_c; + + // { t.accept() } -> snplib_expected_c; // must return std::expected + + // snplib_net_session_c::value_type>; + + { t.start() } -> snplib_error_c; + + t.stop(); +}; + + +struct snplib_netserver_iface_t { + virtual ~snplib_netserver_iface_t() = default; + + template SelfT, snplib_net_listener_c LT> + auto start(this SelfT&& self, LT&& listener) + { + return std::forward(self).start(std::forward(listener)); + } + +protected: + snplib_netserver_iface_t() = default; +}; + +template +concept snplib_netserver_c = requires(T t) { + // static constexpr member + std::formattable; + []() { [[maybe_unused]] static constexpr auto val = T::id; }(); + + + // start/stop all listeners + { t.start() } -> snplib_error_c; + + { t.stop() } -> snplib_error_c; + + { t.disconnectClients() } -> snplib_error_c; +}; +} // namespace snplib \ No newline at end of file diff --git a/include/snipplib/utils/snplib_keyvalue.h b/include/snipplib/utils/snplib_keyvalue_expr.h similarity index 62% rename from include/snipplib/utils/snplib_keyvalue.h rename to include/snipplib/utils/snplib_keyvalue_expr.h index d262004..dceacc8 100644 --- a/include/snipplib/utils/snplib_keyvalue.h +++ b/include/snipplib/utils/snplib_keyvalue_expr.h @@ -6,13 +6,16 @@ namespace snplib { + +/* A SIMPLE KEY-VALUE CHAR-RANGE EXPRESSION PARSER AND MANIPULATOR */ + + template -concept snplib_serializable_c = - requires { [](std::type_identity) {}(std::type_identity>{}); }; +concept snplib_serializable_c = requires { snplib_serializer_t>{}; }; template requires(std::ranges::viewable_range && !std::ranges::borrowed_range) -class snplib_keyvalue_t +class snplib_keyvalue_expr_t { public: static constexpr bool mutableContent = snplib_output_char_range_c; @@ -29,18 +32,21 @@ public: std::string_view valseq_delim{DEFAULT_VALSEQ_DELIM_SEQ}; }; - constexpr snplib_keyvalue_t(ByteSeqT& bytes, config_t cfg = config_t{}) : _byteSeq(bytes), _config(cfg) + constexpr snplib_keyvalue_expr_t(ByteSeqT& bytes, config_t cfg = config_t{}) : _byteSeq(bytes), _config(cfg) { fromByteSequence(bytes, cfg); } - virtual ~snplib_keyvalue_t() = default; + virtual ~snplib_keyvalue_expr_t() = default; + // parse from char range error_t fromByteSequence(ByteSeqT& bytes, config_t cfg = config_t{}) { _byteSeq = bytes; _config = cfg; + _isValid = false; + // key and value auto bs = snplib_trim_spaces_as_view(bytes, TrimType::TRIM_LEFT); @@ -57,74 +63,27 @@ public: _value = decltype(_value)(found.end(), bs.end()); } - - // if constexpr (contiguousContent) { - // auto bs = snplib_trim_spaces_as_view(bytes, TrimType::TRIM_LEFT); - // auto found = std::ranges::search(bs, _config.keyval_delim); - - // if (found.empty()) { // no value - // _key = snplib_trim_spaces_as_view(bs, TrimType::TRIM_RIGHT); - - // _value = std::string_view(); - // } else { - // _key = snplib_trim_spaces_as_view(std::string_view(bs.begin(), found.begin()), TrimType::TRIM_RIGHT); - - // // do not delete space at the end of value-string! - // _value = std::string_view(found.end(), bs.end()); - // } - - // } else if constexpr (std::ranges::viewable_range) { - // auto bs = bytes | std::views::drop_while(snplib_is_space); - // auto found = std::ranges::search(bs, _config.keyval_delim); - - // _value.clear(); - - // if (found.empty()) { // no value - // _key = snplib_trim_spaces(bs, TrimType::TRIM_RIGHT); - // } else { - // _key.clear(); - // auto N = std::ranges::distance(bs.begin(), found.begin()); - // std::ranges::copy(std::views::all(bs) | std::views::take(N) | std::views::reverse | - // std::views::drop_while(snplib_is_space), - // std::back_inserter(_key)); - - // std::ranges::copy(found.end(), bs.end(), std::back_inserter(_value)); - // } - // } else { // always coping - // auto bs = snplib_trim_spaces(bytes, TrimType::TRIM_LEFT); - // auto found = std::ranges::search(bs, _config.keyval_delim); - - // _value.clear(); - - // if (found.empty()) { // no value - // _key = snplib_trim_spaces(bs, TrimType::TRIM_RIGHT); - // } else { - // _key.clear; - // auto N = std::ranges::distance(bs.begin(), found.begin()); - // // std::ranges::copy_n(bs.begin(), N, std::back_inserter(_key)); - - // size_t i = 0; - // for (auto it = bs.begin(); it != found.begin(); ++it, ++i) { - // if (i < N) { - // if (!snplib_is_space(*it)) { - // std::back_inserter(_key) = *it; - // } - // } - // } - // } - - // std::ranges::copy(found.end(), bs.end(), std::back_inserter(_value)); - // } - // split value to elements if (!_value.empty()) { _valueSeq = snplib_split_char_range(_value, _config.valseq_delim); } + if (_key.empty() && !mutableContent) { // at least key must be present + _isValid = false; + return std::make_error_code(std::errc::invalid_argument); + } else { // for mutable content an empty key is allowed! + _isValid = true; + } + return {}; } + bool isValid() const + { + return _isValid; + } + template constexpr R key() const { @@ -186,9 +145,7 @@ public: auto valueSeq(size_t start = 0, size_t N = std::numeric_limits::max()) const // std::vector valueSeq(size_t start = 0, size_t N = std::numeric_limits::max()) const { - // return valueSeq>(start, N); return valueSeq(start, N); - // return _valueSeq; } @@ -227,13 +184,10 @@ public: _byteSeq.clear(); auto err = snplib_serializer_t>{}(_byteSeq, std::forward(key), sparams); if (err) { - // return snplib_deduced_error(err, std::errc::invalid_argument); return snplib_deduced_error(err, std::make_error_code(std::errc::invalid_argument)); - // return std::make_error_code(std::errc::invalid_argument); } return {}; - // return std::make_error_code(std::errc{}); } template @@ -242,13 +196,10 @@ public: { auto err = snplib_serializer_t>{}(_byteSeq, std::forward(value), sparams); if (err) { - // return snplib_deduced_error(err, std::errc::invalid_argument); return snplib_deduced_error(err, std::make_error_code(std::errc::invalid_argument)); - // return std::make_error_code(std::errc::invalid_argument); } return {}; - // return std::make_error_code(std::errc{}); } @@ -273,21 +224,14 @@ public: protected: ByteSeqT& _byteSeq; - // std:: - // conditional_t> - // _key; - // std:: - // conditional_t> - // _value; - std::conditional_t> _key; - std::conditional_t> _value; - // std::conditional_t> _key; - // std::conditional_t> _value; - std::vector _valueSeq; + std::conditional_t> _key{}; + std::conditional_t> + _value{}; + std::vector _valueSeq{}; - config_t _config; + config_t _config{}; + + bool _isValid{false}; }; } // namespace snplib \ No newline at end of file diff --git a/include/snipplib/utils/snplib_string.h b/include/snipplib/utils/snplib_string.h index 189658d..552034c 100644 --- a/include/snipplib/utils/snplib_string.h +++ b/include/snipplib/utils/snplib_string.h @@ -4,6 +4,7 @@ #include #include "../concepts/snplib_concepts.h" +#include "../serialization/snplib_serialization.h" namespace snplib {