This commit is contained in:
Timur A. Fatkhullin
2024-06-15 21:23:57 +03:00
parent daf4e1eab9
commit 9a2baa702d
5 changed files with 182 additions and 116 deletions

View File

@@ -43,91 +43,17 @@ void convertToBytes(ByteStorageT& res, const T& v, const Ts&... vs)
} // namespace utils
namespace traits
{
template <typename T, typename IT>
concept adc_netmessage_c = requires(const T t) { // const methods
requires std::same_as<std::iter_value_t<IT>, char>;
{ t.empty() } -> std::convertible_to<bool>;
{ t.byteSize() } -> std::convertible_to<size_t>;
{ t.bytes() } -> adc_output_char_range;
{ t.byteView() } -> adc_range_of_view_char_range;
{ t.setFromBytes(std::input_iterator<IT>) } -> std::same_as<void>;
};
} // namespace traits
/*
Trivial message interface:
byte storage: just a char-range
*/
*/
template <traits::adc_output_char_range ByteStorageT = std::string, traits::adc_char_view ByteViewT = std::string_view>
class AdcNetMessageTrivialInterface
class AdcNetMessageInterface
{
public:
virtual ~AdcNetMessageTrivialInterface() = default;
typedef ByteStorageT byte_storage_t;
typedef ByteViewT byte_view_t;
bool empty() const { return std::ranges::distance(_bytes.begin(), _bytes.end()) == 0; }
size_t byteSize() const
{
//
return std::ranges::distance(_bytes.begin(), _bytes.end());
}
// get a copy of message bytes
template <traits::adc_output_char_range R>
R bytes() const
{
R r;
std::ranges::copy(_bytes, std::back_inserter(r));
return r;
}
virtual ByteStorageT bytes() const
{
//
return bytes<ByteStorageT>();
}
// get a view of message bytes
template <traits::adc_range_of_view_char_range R>
R bytesView() const
{
R r;
r.emplace_back(_bytes.begin(), _bytes.end());
return r;
}
std::vector<ByteViewT> bytesView() const
{
//
return bytesView<std::vector<ByteViewT>>();
}
protected:
ByteStorageT _bytes;
AdcNetMessageTrivialInterface() = default;
};
/*
interface for more complex messages:
byte storage: std::vector of char-range (sequence of buffers)
*/
template <traits::adc_output_char_range ByteStorageT = std::string, traits::adc_char_view ByteViewT = std::string_view>
class AdcNetMessageSeqInterface
{
public:
virtual ~AdcNetMessageSeqInterface() = default;
virtual ~AdcNetMessageInterface() = default;
bool empty() const
{
@@ -201,11 +127,11 @@ public:
}
protected:
std::vector<ByteStorageT> _bytes;
std::vector<ByteStorageT> _bytes; // sequence of byte buffers
size_t _reservedNum;
AdcNetMessageSeqInterface(size_t reserved = 0) : _reservedNum(reserved), _bytes()
AdcNetMessageInterface(size_t reserved = 0) : _reservedNum(reserved), _bytes()
{
// reserve the "_reservedNum" first elements
_bytes.resize(_reservedNum);
@@ -220,16 +146,24 @@ protected:
// Generic message class
template <traits::adc_output_char_range ByteStorageT = std::string, traits::adc_char_view ByteViewT = std::string_view>
class AdcGenericNetMessage : public AdcNetMessageTrivialInterface<ByteStorageT, ByteViewT>
class AdcGenericNetMessage : public AdcNetMessageInterface<ByteStorageT, ByteViewT>
{
using base_t = AdcNetMessageTrivialInterface<ByteStorageT, ByteViewT>;
using base_t = AdcNetMessageInterface<ByteStorageT, ByteViewT>;
public:
using typename base_t::byte_storage_t;
using typename base_t::byte_view_t;
using base_t::base_t;
using base_t::bytes;
using base_t::bytesView;
using base_t::empty;
AdcGenericNetMessage() : base_t()
{
// just the single buffer
this->_bytes.resize(1);
}
template <typename T, typename... Ts>
AdcGenericNetMessage(const T& v, const Ts&... vs) : AdcGenericNetMessage()
@@ -241,13 +175,13 @@ public:
template <typename T, typename... Ts>
void appendBytes(const T& v, const Ts&... vs)
{
utils::convertToBytes(this->_bytes, v, vs...);
utils::convertToBytes(this->_bytes[0], v, vs...);
}
template <typename T, typename... Ts>
void setBytes(const T& v, const Ts&... vs)
{
this->_bytes = ByteStorageT();
this->_bytes[0] = ByteStorageT();
appendBytes(v, vs...);
}
@@ -257,7 +191,7 @@ public:
void appendFromBytes(IT begin, IT end)
requires std::same_as<std::iter_value_t<IT>, char>
{
std::copy(begin, end, std::back_inserter(this->_bytes));
std::copy(begin, end, std::back_inserter(this->_bytes[0]));
}
@@ -265,7 +199,7 @@ public:
void setFromBytes(IT begin, IT end)
requires std::same_as<std::iter_value_t<IT>, char>
{
this->_bytes = ByteStorageT();
this->_bytes[0] = ByteStorageT();
appendFromBytes(begin, end);
}
@@ -283,10 +217,10 @@ static constexpr char ADC_DEFAULT_KEY_TOKEN_DELIMITER[] = " ";
template <const char* TOKEN_DELIM = constants::ADC_DEFAULT_TOKEN_DELIMITER,
traits::adc_output_char_range ByteStorageT = std::string,
traits::adc_char_view ByteViewT = std::string_view>
class AdcTokenNetMessage : public AdcNetMessageSeqInterface<ByteStorageT, ByteViewT>
class AdcTokenNetMessage : public AdcNetMessageInterface<ByteStorageT, ByteViewT>
{
// AdcNetMessageSeqInterface<ByteStorageT, ByteViewT>::_bytes - tokens
using base_t = AdcNetMessageSeqInterface<ByteStorageT, ByteViewT>;
using base_t = AdcNetMessageInterface<ByteStorageT, ByteViewT>;
public:
static constexpr std::string_view tokenDelimiter{TOKEN_DELIM};
@@ -457,7 +391,7 @@ public:
using base_t::tokens;
AdcKeyTokenNetMessage()
AdcKeyTokenNetMessage() : base_t()
{
this->_reservedNum = 1; // reserve the first element for keyword
this->_bytes.resize(this->_reservedNum);
@@ -599,4 +533,29 @@ public:
}
};
namespace traits
{
template <typename T>
concept adc_netmessage_c = requires {
typename T::byte_storage_t;
typename T::byte_view_t;
std::derived_from<T, AdcNetMessageInterface<typename T::byte_storage_t, typename T::byte_view_t>>;
};
// template <typename T, typename IT>
// concept adc_netmessage_c = requires(const T t) { // const methods
// requires std::same_as<std::iter_value_t<IT>, char>;
// { t.empty() } -> std::convertible_to<bool>;
// { t.byteSize() } -> std::convertible_to<size_t>;
// { t.bytes() } -> adc_output_char_range;
// { t.byteView() } -> adc_range_of_view_char_range;
// { t.setFromBytes(std::input_iterator<IT>) } -> std::same_as<void>;
// };
} // namespace traits
} // namespace adc