...
This commit is contained in:
parent
56bf7abcb7
commit
8ae489f1c5
@ -46,6 +46,10 @@ template <typename R>
|
|||||||
concept adc_char_view = std::ranges::view<R> && std::same_as<std::ranges::range_value_t<R>, char>;
|
concept adc_char_view = std::ranges::view<R> && std::same_as<std::ranges::range_value_t<R>, char>;
|
||||||
|
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
concept adc_view_or_output_char_range = adc_char_view<R> || adc_output_char_range<R>;
|
||||||
|
|
||||||
|
|
||||||
template <typename R>
|
template <typename R>
|
||||||
concept adc_range_of_view_char_range = std::ranges::range<R> && std::ranges::view<std::ranges::range_value_t<R>> &&
|
concept adc_range_of_view_char_range = std::ranges::range<R> && std::ranges::view<std::ranges::range_value_t<R>> &&
|
||||||
std::same_as<std::ranges::range_value_t<std::ranges::range_value_t<R>>, char>;
|
std::same_as<std::ranges::range_value_t<std::ranges::range_value_t<R>>, char>;
|
||||||
@ -54,6 +58,10 @@ template <typename R>
|
|||||||
concept adc_range_of_input_char_range =
|
concept adc_range_of_input_char_range =
|
||||||
std::ranges::range<R> && traits::adc_input_char_range<std::ranges::range_value_t<R>>;
|
std::ranges::range<R> && traits::adc_input_char_range<std::ranges::range_value_t<R>>;
|
||||||
|
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
concept adc_range_of_view_or_output_char_range = adc_range_of_view_char_range<R> || adc_output_char_range<R>;
|
||||||
|
|
||||||
// deduce returned type of callable
|
// deduce returned type of callable
|
||||||
// template <typename T>
|
// template <typename T>
|
||||||
// using adc_retval_t = std::invoke_result_t<std::remove_cvref_t<T>>;
|
// using adc_retval_t = std::invoke_result_t<std::remove_cvref_t<T>>;
|
||||||
|
|||||||
@ -14,7 +14,7 @@ ABSTRACT DEVICE COMPONENTS LIBRARY
|
|||||||
/* DEFINITIONS OF NETWORK COMPONENTS INTERFACES */
|
/* DEFINITIONS OF NETWORK COMPONENTS INTERFACES */
|
||||||
|
|
||||||
|
|
||||||
namespace adc::traits
|
namespace adc::interfaces
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ template <typename SRVT,
|
|||||||
typename RMSGT = std::string, // receiving message type
|
typename RMSGT = std::string, // receiving message type
|
||||||
typename DURT = adc_common_duration_t // time duration type
|
typename DURT = adc_common_duration_t // time duration type
|
||||||
>
|
>
|
||||||
concept adc_netservice_c = adc_input_char_range<SMSGT> && adc_output_char_range<RMSGT> && adc_time_duration_c<DURT> &&
|
concept adc_netservice_c = traits::adc_input_char_range<SMSGT> && traits::adc_output_char_range<RMSGT> && adc_time_duration_c<DURT> &&
|
||||||
requires(SRVT srv, const SRVT srv_const) {
|
requires(SRVT srv, const SRVT srv_const) {
|
||||||
typename SRVT::netservice_ident_t;
|
typename SRVT::netservice_ident_t;
|
||||||
|
|
||||||
@ -103,53 +103,27 @@ concept adc_netservice_c = adc_input_char_range<SMSGT> && adc_output_char_range<
|
|||||||
typename SRVT::endpoint_t;
|
typename SRVT::endpoint_t;
|
||||||
|
|
||||||
// asynchronous (non-blocking) operations
|
// asynchronous (non-blocking) operations
|
||||||
asyncAccept(std::declval<const typename SRVT::endpoint_t&>(),
|
srv.asyncAccept(std::declval<const typename SRVT::endpoint_t&>(),
|
||||||
std::declval<typename SRVT::async_ctx_t&>(), std::declval<const DURT&>());
|
std::declval<typename SRVT::async_ctx_t&>(), std::declval<const DURT&>());
|
||||||
|
|
||||||
asyncConnect(std::declval<const typename SRVT::endpoint_t&>(),
|
srv.asyncConnect(std::declval<const typename SRVT::endpoint_t&>(),
|
||||||
std::declval<typename SRVT::async_ctx_t&>(), std::declval<const DURT&>());
|
std::declval<typename SRVT::async_ctx_t&>(), std::declval<const DURT&>());
|
||||||
|
|
||||||
asyncSend(std::declval<const SMSGT&>(), std::declval<typename SRVT::async_ctx_t&>(),
|
srv.asyncSend(std::declval<const SMSGT&>(), std::declval<typename SRVT::async_ctx_t&>(),
|
||||||
std::declval<const DURT&>());
|
std::declval<const DURT&>());
|
||||||
|
|
||||||
asyncReceive(std::declval<typename SRVT::async_ctx_t&>(), std::declval<const DURT&>());
|
srv.asyncReceive(std::declval<typename SRVT::async_ctx_t&>(), std::declval<const DURT&>());
|
||||||
|
|
||||||
// synchronous (blocking) operations
|
// synchronous (blocking) operations
|
||||||
accept(std::declval<const typename SRVT::endpoint_t&>(), std::declval<const DURT&>());
|
srv.accept(std::declval<const typename SRVT::endpoint_t&>(), std::declval<const DURT&>());
|
||||||
|
|
||||||
connect(std::declval<const typename SRVT::endpoint_t&>(), std::declval<const DURT&>());
|
srv.connect(std::declval<const typename SRVT::endpoint_t&>(), std::declval<const DURT&>());
|
||||||
|
|
||||||
send(std::declval<const SMSGT&>(), std::declval<const DURT&>());
|
srv.send(std::declval<const SMSGT&>(), std::declval<const DURT&>());
|
||||||
|
|
||||||
{ receive(std::declval<const DURT&>()) } -> std::same_as<RMSGT>;
|
{ srv.receive(std::declval<const DURT &>()) } -> std::same_as<RMSGT>;
|
||||||
|
|
||||||
// requires requires {
|
srv.shutdown();
|
||||||
// [](SRVT& srv_obj, const typename SRVT::endpoint_t& endpoint, const typename
|
|
||||||
// SRVT::async_ctx_t& ctx,
|
|
||||||
// const DURT& timeout) {
|
|
||||||
// srv_obj.asyncAccept(endpoint, ctx, timeout);
|
|
||||||
// srv_obj.asyncConnect(endpoint, ctx, timeout);
|
|
||||||
|
|
||||||
// srv_obj.accept(endpoint, timeout);
|
|
||||||
// srv_obj.connect(endpoint, timeout);
|
|
||||||
// }(srv, typename SRVT::endpoint_t(), typename SRVT::async_ctx_t(),
|
|
||||||
// std::chrono::seconds(1));
|
|
||||||
|
|
||||||
// []<adc::traits::adc_input_char_range R>(SRVT& srv_obj, const R& msg, const
|
|
||||||
// typename SRVT::async_ctx_t& ctx,
|
|
||||||
// const DURT& timeout) {
|
|
||||||
// srv_obj.asyncSend(msg, ctx, timeout);
|
|
||||||
// srv_obj.send(msg, timeout);
|
|
||||||
// }(srv, std::span<const char>(), typename SRVT::async_ctx_t(),
|
|
||||||
// std::chrono::seconds(1));
|
|
||||||
|
|
||||||
// []<adc::traits::adc_output_char_range R>(SRVT& srv_obj, R& msg, const typename
|
|
||||||
// SRVT::async_ctx_t& ctx,
|
|
||||||
// const DURT& timeout) {
|
|
||||||
// srv_obj.asyncReceive(ctx, timeout);
|
|
||||||
// msg = srv_obj.receive(timeout);
|
|
||||||
// }(srv, std::string(), typename SRVT::async_ctx_t(), std::chrono::seconds(1));
|
|
||||||
// };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -171,21 +145,35 @@ concept adc_netsession_c =
|
|||||||
|
|
||||||
/* NETWORK SESSION-LEVEL PROTOCOL */
|
/* NETWORK SESSION-LEVEL PROTOCOL */
|
||||||
|
|
||||||
template <typename SESS_PROTOT>
|
template <typename SESS_PROTOT,
|
||||||
concept adc_netsession_proto_c = requires(SESS_PROTOT proto, const SESS_PROTOT proto_const) {
|
typename BUFFT = std::string_view>
|
||||||
|
concept adc_netsession_proto_c = traits::adc_input_char_range<BUFFT> && requires(SESS_PROTOT proto, const SESS_PROTOT proto_const) {
|
||||||
typename SESS_PROTOT::proto_ident_t;
|
typename SESS_PROTOT::proto_ident_t;
|
||||||
|
|
||||||
// proto_ident_t ident() const (const method)
|
// proto_ident_t ident() const (const method)
|
||||||
{ proto_const.ident() } -> std::same_as<typename SESS_PROTOT::proto_ident_t>;
|
{ proto_const.ident() } -> std::same_as<typename SESS_PROTOT::proto_ident_t>;
|
||||||
|
|
||||||
[]<std::input_iterator IT>(const SESS_PROTOT& proto, IT begin, IT end) -> std::tuple<IT, IT, bool> {
|
// typename SESS_PROTOT::search_result_t;
|
||||||
return proto.parse(begin, end);
|
|
||||||
};
|
// search for the first occurence of valid protocol sequence in input user byte sequence
|
||||||
|
// the method must return std::tuple<begin, end, flag>:
|
||||||
|
// start - input range iterator of the sequence first byte
|
||||||
|
// stop - input range iterator of the sequence end ("after-the-last" byte!!!)
|
||||||
|
// flag - true if valid sequence was found, false - otherwise
|
||||||
|
{
|
||||||
|
proto.search(std::declval<const BUFFT&>())
|
||||||
|
} -> std::same_as<std::tuple<std::ranges::iterator_t<BUFFT>, std::ranges::iterator_t<BUFFT>, bool>>;
|
||||||
|
|
||||||
|
|
||||||
|
// construct netsession protocol representation of input user byte sequence
|
||||||
|
// the method must return a range of char range views or output char range
|
||||||
|
{ proto.toProto(std::declval<const BUFFT &>()) } -> traits::adc_range_of_view_or_output_char_range;
|
||||||
|
|
||||||
|
// return user byte sequence from input netsession protocol representation
|
||||||
|
// the method must return a view of char range or output char range
|
||||||
|
{ proto.fromProto(std::declval<const BUFFT &>()) } -> traits::adc_view_or_output_char_range;
|
||||||
|
|
||||||
// must return a view of R-range!
|
|
||||||
[]<std::ranges::range R>(SESS_PROTOT obj, const R& r) -> std::ranges::view auto { return obj.from(r); }(
|
|
||||||
proto, std::string());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace adc::traits
|
} // namespace adc::interfaces
|
||||||
|
|||||||
@ -27,6 +27,65 @@ static constexpr char ADC_DEFAULT_NETPROTO_STARTMARK[] = "\n\t\r\v\r\t\n";
|
|||||||
} // namespace constants
|
} // namespace constants
|
||||||
|
|
||||||
|
|
||||||
|
template <const char* STOPSEQ = constants::ADC_DEFAULT_NETPROTO_STOPSEQ>
|
||||||
|
struct AdcStopSeqSessionProto {
|
||||||
|
static constexpr std::string_view STOP_SEQ{STOPSEQ};
|
||||||
|
static constexpr size_t STOP_SEQ_SIZE = STOP_SEQ.size();
|
||||||
|
|
||||||
|
static_assert(STOP_SEQ_SIZE, "STOP BYTE SEQUENCE MUST NOT BE AN EMPTY ONE!!!");
|
||||||
|
|
||||||
|
template <traits::adc_input_char_range R>
|
||||||
|
auto search(const R& r)
|
||||||
|
{
|
||||||
|
std::tuple<std::ranges::iterator_t<R>, std::ranges::iterator_t<R>, bool> res{r.begin(), r.end(), false};
|
||||||
|
|
||||||
|
std::get<1>(res) = std::search(r.begin(), r.end(), STOP_SEQ.begin(), STOP_SEQ.end());
|
||||||
|
if (std::get<1>(res) != r.end()) { // move iterator to the one-past-the-end position
|
||||||
|
std::get<1>(res) = std::advance(std::get<1>(res), STOP_SEQ_SIZE);
|
||||||
|
std::get<2>(res) = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <traits::adc_input_char_range R>
|
||||||
|
auto toProto(const R& r)
|
||||||
|
{
|
||||||
|
// return 2-element array with the first element as a view of the input range and
|
||||||
|
// the second one - a view of the stop sequence
|
||||||
|
|
||||||
|
if constexpr (std::ranges::viewable_range<R>) {
|
||||||
|
auto res = std::array{std::ranges::subrange(r.begin(), r.end()),
|
||||||
|
std::ranges::subrange(STOP_SEQ.begin(), STOP_SEQ.end())};
|
||||||
|
|
||||||
|
return res;
|
||||||
|
} else { // return a copy of input range with appended stop sequence
|
||||||
|
auto res = r;
|
||||||
|
std::ranges::copy(STOP_SEQ, std::back_inserter(res));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::adc_input_char_range R>
|
||||||
|
auto fromProto(const R& r)
|
||||||
|
{
|
||||||
|
auto N = std::distance(r.begin(), r.end());
|
||||||
|
|
||||||
|
if (N < STOP_SEQ_SIZE) { // one must ensure for input range size correctness
|
||||||
|
return std::span<std::ranges::range_value_t<R>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (std::ranges::viewable_range<R>) {
|
||||||
|
return std::ranges::subrange(r.begin(), r.end() - STOP_SEQ_SIZE);
|
||||||
|
} else {
|
||||||
|
R res;
|
||||||
|
std::ranges::copy(r | std::views::take(N - STOP_SEQ_SIZE), std::back_inserter(res));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename InetT, const char* STOPSEQ = constants::ADC_DEFAULT_NETPROTO_STOPSEQ>
|
template <typename InetT, const char* STOPSEQ = constants::ADC_DEFAULT_NETPROTO_STOPSEQ>
|
||||||
struct AdcNetProtoStopSeq : InetT {
|
struct AdcNetProtoStopSeq : InetT {
|
||||||
static constexpr std::string_view stopSeq{STOPSEQ};
|
static constexpr std::string_view stopSeq{STOPSEQ};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user