This commit is contained in:
2026-06-29 18:46:44 +03:00
parent 700d5bed10
commit 1a80e70e0c
8 changed files with 181 additions and 93 deletions

View File

@@ -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

View File

@@ -1,9 +1,7 @@
#include <list>
#include <print>
// #include "../utils/snplib_string.h"
// #include "../include/snipplib/snplib_string.h"
#include <snipplib/utils/snplib_keyvalue.h>
#include <snipplib/utils/snplib_keyvalue_expr.h>
#include <snipplib/utils/snplib_string.h>
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());

View File

@@ -2,6 +2,9 @@
#include <chrono>
#include <concepts>
#include <coroutine>
#include <expected>
#include <future>
#include <ranges>
namespace snplib
@@ -154,4 +157,42 @@ static auto snplib_deduced_error(ErrT const& err, FallbackErrT const& fallback_e
}
}
template <typename T>
concept snplib_expected_c = requires {
[]<typename ValT, snplib_error_c ErrT>(std::type_identity<std::expected<ValT, ErrT>>) {
}(std::type_identity<std::remove_cvref_t<T>>{});
};
// template <typename T, typename ValT>
// concept snplib_expected_c = requires {
// []<snplib_error_c ErrT>(std::type_identity<std::expected<ValT, ErrT>>) {
// }(std::type_identity<std::remove_cvref_t<T>>{});
// };
// result of asynchronous callable
template <typename T, typename UT = void>
concept snplib_awaiter_c = requires(T t, std::coroutine_handle<> hndl) {
{ t.await_ready() } -> std::convertible_to<bool>;
// 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<UT>;
};
template <typename T, typename UT = void>
concept snplib_awaitable_c = snplib_awaiter_c<T, UT> || requires(T t) {
{ t.operator co_await() } -> snplib_awaiter_c<UT>;
};
template <typename T, typename UT = void>
concept snplib_async_retval_c = snplib_awaitable_c<T, UT> && snplib_expected_c<UT>;
} // namespace snplib

View File

@@ -11,6 +11,9 @@
namespace snplib
{
/* AN UNORDERED MAP WITH ABILITY OF STORING DIFFERENT TYPE VALUES */
/* (A HETEROGENEOUS UNORDERED MAP) */
template <snplib_hashable_c KeyT>
class HeterogenMap

View File

@@ -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 = "/";

View File

@@ -0,0 +1,100 @@
#pragma once
#include "../concepts/snplib_concepts.h"
namespace snplib
{
template <typename T>
concept snplib_net_endpoint_c = requires(T t, const T t_const) {
// static constexpr member
std::formattable<decltype(T::id), char>;
[]() { [[maybe_unused]] static constexpr auto val = T::id; }();
{ t.endpoint() } -> snplib_char_range_c;
{ t_const.proto() } -> std::formattable<char>;
{ t_const.host() } -> std::formattable<char>;
{ t_const.path() } -> std::formattable<char>;
{ t_const.port() } -> std::formattable<char>;
};
template <typename T>
concept snplib_net_connection_c = requires(T t) {
// static constexpr member
std::formattable<decltype(T::id), char>;
[]() { [[maybe_unused]] static constexpr auto val = T::id; }();
typename T::message_t; // minimal allowed unit of read/write operations
{ t.send(std::declval<typename T::message_t>()) } -> snplib_async_retval_c;
{ t.recv() } -> snplib_async_retval_c<typename T::message_t>;
t.close();
};
template <typename T>
concept snplib_net_session_c = std::derived_from<T, std::enable_shared_from_this<T>> && requires(T t) {
// static constexpr member
std::formattable<decltype(T::id), char>;
[]() { [[maybe_unused]] static constexpr auto val = T::id; }();
snplib_net_connection_c<typename T::connection_t>;
{ t.start(std::declval<typename T::connection_t>()) } -> snplib_async_retval_c;
t.stop();
};
template <typename T>
concept snplib_net_listener_c = requires(T t) {
// static constexpr member
std::formattable<decltype(T::id), char>;
[]() { [[maybe_unused]] static constexpr auto val = T::id; }();
snplib_net_session_c<typename T::session_t>;
{ t.accept() } -> snplib_async_retval_c<typename T::session_t>;
// { t.accept() } -> snplib_expected_c; // must return std::expected<snplib_net_session_c, snplib_error_c>
// snplib_net_session_c<typename std::invoke_result_t<decltype(t.accept)>::value_type>;
{ t.start() } -> snplib_error_c;
t.stop();
};
struct snplib_netserver_iface_t {
virtual ~snplib_netserver_iface_t() = default;
template <std::derived_from<snplib_netserver_iface_t> SelfT, snplib_net_listener_c LT>
auto start(this SelfT&& self, LT&& listener)
{
return std::forward<SelfT>(self).start(std::forward<LT>(listener));
}
protected:
snplib_netserver_iface_t() = default;
};
template <typename T>
concept snplib_netserver_c = requires(T t) {
// static constexpr member
std::formattable<decltype(T::id), char>;
[]() { [[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

View File

@@ -6,13 +6,16 @@
namespace snplib
{
/* A SIMPLE KEY-VALUE CHAR-RANGE EXPRESSION PARSER AND MANIPULATOR */
template <typename T>
concept snplib_serializable_c =
requires { []<typename VT>(std::type_identity<VT>) {}(std::type_identity<std::remove_cvref_t<T>>{}); };
concept snplib_serializable_c = requires { snplib_serializer_t<std::remove_cvref_t<T>>{}; };
template <snplib_char_range_c ByteSeqT>
requires(std::ranges::viewable_range<ByteSeqT> && !std::ranges::borrowed_range<ByteSeqT>)
class snplib_keyvalue_t
class snplib_keyvalue_expr_t
{
public:
static constexpr bool mutableContent = snplib_output_char_range_c<ByteSeqT>;
@@ -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<R>) {
// 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<decltype(_valueSeq)>(_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 <snplib_char_range_c R>
constexpr R key() const
{
@@ -186,9 +145,7 @@ public:
auto valueSeq(size_t start = 0, size_t N = std::numeric_limits<size_t>::max()) const
// std::vector<std::string_view> valueSeq(size_t start = 0, size_t N = std::numeric_limits<size_t>::max()) const
{
// return valueSeq<std::vector<std::string_view>>(start, N);
return valueSeq<decltype(_valueSeq)>(start, N);
// return _valueSeq;
}
@@ -227,13 +184,10 @@ public:
_byteSeq.clear();
auto err = snplib_serializer_t<std::remove_cvref_t<KeyT>>{}(_byteSeq, std::forward<KeyT>(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 <snplib_serializable_c ValueT, snplib_serialization_params_c SParT = snplib_serialization_params_t>
@@ -242,13 +196,10 @@ public:
{
auto err = snplib_serializer_t<std::remove_cvref_t<ValueT>>{}(_byteSeq, std::forward<ValueT>(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<mutableContent, std::string, std::conditional_t<contiguousContent, std::string_view,
// std::string>>
// _key;
// std::
// conditional_t<mutableContent, std::string, std::conditional_t<contiguousContent, std::string_view,
// std::string>>
// _value;
std::conditional_t<contiguousContent, std::string_view, std::ranges::subrange<typename ByteSeqT::iterator>> _key;
std::conditional_t<contiguousContent, std::string_view, std::ranges::subrange<typename ByteSeqT::iterator>> _value;
// std::conditional_t<contiguousContent, std::string_view, std::views::all_t<ByteSeqT>> _key;
// std::conditional_t<contiguousContent, std::string_view, std::views::all_t<ByteSeqT>> _value;
std::vector<decltype(_value)> _valueSeq;
std::conditional_t<contiguousContent, std::string_view, std::ranges::subrange<typename ByteSeqT::iterator>> _key{};
std::conditional_t<contiguousContent, std::string_view, std::ranges::subrange<typename ByteSeqT::iterator>>
_value{};
std::vector<decltype(_value)> _valueSeq{};
config_t _config;
config_t _config{};
bool _isValid{false};
};
} // namespace snplib

View File

@@ -4,6 +4,7 @@
#include <string>
#include "../concepts/snplib_concepts.h"
#include "../serialization/snplib_serialization.h"
namespace snplib
{