...
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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 = "/";
|
||||
|
||||
100
include/snipplib/network/snplib_network.h
Normal file
100
include/snipplib/network/snplib_network.h
Normal 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
|
||||
@@ -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
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "../concepts/snplib_concepts.h"
|
||||
#include "../serialization/snplib_serialization.h"
|
||||
|
||||
namespace snplib
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user