...
This commit is contained in:
parent
3e19ca4dd6
commit
8bcc8edbb0
@ -27,6 +27,49 @@ static auto AdcTrimSpaces(R&& r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum class AdcTrimType { TRIM_LEFT, TRIM_RIGHT, TRIM_BOTH };
|
||||||
|
|
||||||
|
template <traits::adc_char_view VR, traits::adc_char_range R>
|
||||||
|
requires std::ranges::contiguous_range<R>
|
||||||
|
static auto AdcTrimSpacesView(R&& r, AdcTrimType type = AdcTrimType::TRIM_BOTH)
|
||||||
|
{
|
||||||
|
auto is_space = [](const auto& ch) { return ch == ' '; };
|
||||||
|
|
||||||
|
auto end = std::forward<R>(r).end();
|
||||||
|
|
||||||
|
auto f1 = std::forward<R>(r).begin();
|
||||||
|
|
||||||
|
if (type != AdcTrimType::TRIM_RIGHT) {
|
||||||
|
// look for the first non-space symbol
|
||||||
|
f1 = std::ranges::find_if_not(std::forward<R>(r), is_space);
|
||||||
|
if (f1 == end) { // all are spaces!
|
||||||
|
return VR();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto f2 = end;
|
||||||
|
|
||||||
|
if (type != AdcTrimType::TRIM_LEFT) {
|
||||||
|
auto f3 = f1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
f2 = std::ranges::find_if(++f3, end, is_space);
|
||||||
|
if (f2 == end)
|
||||||
|
break;
|
||||||
|
f3 = std::ranges::find_if_not(f2 + 1, end, is_space);
|
||||||
|
} while (f3 != end);
|
||||||
|
}
|
||||||
|
|
||||||
|
return VR(f1, f2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::adc_char_range R>
|
||||||
|
static auto AdcTrimSpacesView(R&& r, AdcTrimType type = AdcTrimType::TRIM_BOTH)
|
||||||
|
{
|
||||||
|
return AdcTrimSpacesView<std::string_view>(std::forward<R>(r), type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename ValueT, traits::adc_char_range R>
|
template <typename ValueT, traits::adc_char_range R>
|
||||||
static ValueT AdcFromChars(R&& range)
|
static ValueT AdcFromChars(R&& range)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../common/adc_utils.h"
|
#include "../common/adc_utils.h"
|
||||||
#include "adc_netmsg.h"
|
// #include "adc_netmsg.h"
|
||||||
|
|
||||||
namespace adc
|
namespace adc
|
||||||
{
|
{
|
||||||
@ -11,23 +11,160 @@ namespace adc
|
|||||||
namespace constants
|
namespace constants
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static constexpr char ADC_DEFAULT_KEY_VALUE_DELIMITER1[] = " ";
|
||||||
static constexpr char ADC_DEFAULT_KEY_PARAM_DELIMITER[] = " ";
|
static constexpr char ADC_DEFAULT_KEY_PARAM_DELIMITER[] = " ";
|
||||||
static constexpr char ADC_DEFAULT_PARAM_PARAM_DELIMITER[] = " ";
|
static constexpr char ADC_DEFAULT_PARAM_PARAM_DELIMITER[] = " ";
|
||||||
|
static constexpr char ADC_DEFAULT_COMPOSITE_PARAM_DELIMITER[] = ",";
|
||||||
|
|
||||||
} // namespace constants
|
} // namespace constants
|
||||||
|
|
||||||
|
|
||||||
template <traits::adc_output_char_range ByteSeqT>
|
|
||||||
class AdcDeviceNetMessage : protected AdcKeyValueMessage<ByteSeqT, constants::ADC_DEFAULT_KEY_PARAM_DELIMITER>
|
template <traits::adc_char_range ByteSeqT,
|
||||||
|
const char* KEY_VALUE_DELIM = constants::ADC_DEFAULT_KEY_VALUE_DELIMITER1,
|
||||||
|
const char* VALUE_DELIM = constants::ADC_DEFAULT_COMPOSITE_PARAM_DELIMITER>
|
||||||
|
class AdcKeyValueMessage1
|
||||||
{
|
{
|
||||||
using base_t = AdcKeyValueMessage<ByteSeqT, constants::ADC_DEFAULT_KEY_PARAM_DELIMITER>;
|
public:
|
||||||
|
static constexpr std::span keyValueDelimiter{KEY_VALUE_DELIM, sizeof(KEY_VALUE_DELIM) - 1};
|
||||||
|
static constexpr std::span valueDelimiter{VALUE_DELIM, sizeof(VALUE_DELIM) - 1};
|
||||||
|
|
||||||
|
AdcKeyValueMessage1(ByteSeqT& byte_seq) : _byteSequence(byte_seq) {}
|
||||||
|
|
||||||
|
virtual ~AdcKeyValueMessage1() = default;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
requires(traits::adc_char_view<T> && std::ranges::contiguous_range<ByteSeqT>) ||
|
||||||
|
traits::adc_output_char_range<T>
|
||||||
|
auto key() const
|
||||||
|
{
|
||||||
|
if constexpr (traits::adc_char_view<T> && std::ranges::contiguous_range<ByteSeqT>) {
|
||||||
|
auto bs = utils::AdcTrimSpacesView<T>(_byteSequence, utils::AdcTrimType::TRIM_LEFT);
|
||||||
|
auto found = std::ranges::search(bs, keyValueDelimiter);
|
||||||
|
|
||||||
|
// if (found.empty) { // no value
|
||||||
|
// return bs;
|
||||||
|
// }
|
||||||
|
|
||||||
|
return utils::AdcTrimSpacesView<T>(std::span<const char>(bs.begin(), found.begin()),
|
||||||
|
utils::AdcTrimType::TRIM_RIGHT);
|
||||||
|
} else {
|
||||||
|
T res;
|
||||||
|
|
||||||
|
auto bs = _byteSequence | std::views::drop_while([](const auto& ch) { return ch = ' '; });
|
||||||
|
|
||||||
|
auto found = std::ranges::search(bs, keyValueDelimiter);
|
||||||
|
std::ranges::copy(bs.begin(), found.begin(), std::back_inserter(res));
|
||||||
|
// if (found.empty()) { // no value
|
||||||
|
// std::ranges::copy(bs, std::back_inserter(res));
|
||||||
|
// } else {
|
||||||
|
// std::ranges::copy(bs.begin(), found.begin(), std::back_inserter(res));
|
||||||
|
// }
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto key() const
|
||||||
|
{
|
||||||
|
if constexpr (std::ranges::contiguous_range<ByteSeqT>) {
|
||||||
|
return key<std::string_view>();
|
||||||
|
} else {
|
||||||
|
return key<std::string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
requires(traits::adc_char_view<T> && std::ranges::contiguous_range<ByteSeqT>) ||
|
||||||
|
traits::adc_output_char_range<T>
|
||||||
|
auto value() const
|
||||||
|
{
|
||||||
|
if constexpr (traits::adc_char_view<T> && std::ranges::contiguous_range<ByteSeqT>) {
|
||||||
|
auto bs = utils::AdcTrimSpacesView<T>(_byteSequence, utils::AdcTrimType::TRIM_LEFT);
|
||||||
|
auto found = std::ranges::search(bs, keyValueDelimiter);
|
||||||
|
|
||||||
|
// if (found.empty()) { // no value
|
||||||
|
// return T();
|
||||||
|
// }
|
||||||
|
|
||||||
|
return T(found.end(), _byteSequence.end());
|
||||||
|
} else {
|
||||||
|
T res;
|
||||||
|
|
||||||
|
auto bs = _byteSequence | std::views::drop_while([](const auto& ch) { return ch = ' '; });
|
||||||
|
|
||||||
|
auto found = std::ranges::search(bs, keyValueDelimiter);
|
||||||
|
if (!found.empty()) {
|
||||||
|
std::ranges::copy(found.end(), _byteSequence.end(), std::back_inserter(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto value() const
|
||||||
|
{
|
||||||
|
if constexpr (std::ranges::contiguous_range<ByteSeqT>) {
|
||||||
|
return value<std::string_view>();
|
||||||
|
} else {
|
||||||
|
return value<std::string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename KeyT, typename ValueT>
|
||||||
|
requires traits::adc_output_char_range<ByteSeqT>
|
||||||
|
AdcKeyValueMessage1& setKeyValue(KeyT&& key, ValueT&& value)
|
||||||
|
{
|
||||||
|
if (std::ranges::size(_byteSequence)) {
|
||||||
|
_byteSequence = _byteSequence();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ranges::copy(
|
||||||
|
utils::AdcDefaultValueConverter<KEY_VALUE_DELIM>::template serialize<ByteSeqT>(std::forward<KeyT>(key)),
|
||||||
|
std::back_inserter(_byteSequence));
|
||||||
|
|
||||||
|
std::ranges::copy(keyValueDelimiter, std::back_inserter(_byteSequence));
|
||||||
|
|
||||||
|
std::ranges::copy(
|
||||||
|
utils::AdcDefaultValueConverter<KEY_VALUE_DELIM>::template serialize(std::forward<ValueT>(value)),
|
||||||
|
std::back_inserter(_byteSequence));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename ValueT>
|
||||||
|
AdcKeyValueMessage1& setValue(ValueT&& value)
|
||||||
|
{
|
||||||
|
std::vector<char> kw;
|
||||||
|
std::ranges::copy(key<std::span<const char>>(), std::back_inserter(kw));
|
||||||
|
|
||||||
|
return setKeyValue(kw, std::forward<ValueT>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ByteSeqT& _byteSequence;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <traits::adc_char_range ByteSeqT,
|
||||||
|
const char* KEY_PARAM_DELIM = constants::ADC_DEFAULT_KEY_PARAM_DELIMITER,
|
||||||
|
const char* PARAM_PARAM_DELIM = constants::ADC_DEFAULT_PARAM_PARAM_DELIMITER,
|
||||||
|
const char* COMPOSITE_PARAM_DELIM = constants::ADC_DEFAULT_COMPOSITE_PARAM_DELIMITER>
|
||||||
|
class AdcDeviceNetMessage : public AdcKeyValueMessage1<ByteSeqT, KEY_PARAM_DELIM, COMPOSITE_PARAM_DELIM>
|
||||||
|
{
|
||||||
|
using base_t = AdcKeyValueMessage1<ByteSeqT, KEY_PARAM_DELIM, COMPOSITE_PARAM_DELIM>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr std::span keyParamDelimiter{constants::ADC_DEFAULT_KEY_PARAM_DELIMITER,
|
static constexpr std::span keyParamDelimiter{KEY_PARAM_DELIM, sizeof(KEY_PARAM_DELIM) - 1};
|
||||||
sizeof(constants::ADC_DEFAULT_KEY_PARAM_DELIMITER)};
|
|
||||||
|
|
||||||
static constexpr std::span paramParamDelimiter{constants::ADC_DEFAULT_PARAM_PARAM_DELIMITER,
|
static constexpr std::span paramParamDelimiter{PARAM_PARAM_DELIM, sizeof(PARAM_PARAM_DELIM) - 1};
|
||||||
sizeof(constants::ADC_DEFAULT_PARAM_PARAM_DELIMITER)};
|
|
||||||
|
static constexpr std::span compParamDelimiter{COMPOSITE_PARAM_DELIM, sizeof(COMPOSITE_PARAM_DELIM) - 1};
|
||||||
|
|
||||||
|
|
||||||
AdcDeviceNetMessage(ByteSeqT& byte_seq) : base_t(byte_seq) {}
|
AdcDeviceNetMessage(ByteSeqT& byte_seq) : base_t(byte_seq) {}
|
||||||
@ -35,8 +172,22 @@ public:
|
|||||||
template <traits::adc_char_view VT>
|
template <traits::adc_char_view VT>
|
||||||
VT keyword() const
|
VT keyword() const
|
||||||
{
|
{
|
||||||
auto v = utils::AdcTrimSpaces(base_t::template key<VT>());
|
// auto v = utils::AdcTrimSpaces(base_t::template key<VT>());
|
||||||
return VT(v.begin(), v.end());
|
// return VT(std::begin(v), std::end(v));
|
||||||
|
|
||||||
|
std::span<const char> key;
|
||||||
|
// first, remove spaces at the beginning and end of byte sequence
|
||||||
|
auto bs = utils::AdcTrimSpacesView<std::span<const char>>(this->_byteSequence);
|
||||||
|
|
||||||
|
auto found = std::ranges::search(bs, keyParamDelimiter);
|
||||||
|
if (found.empty()) { // only keyword
|
||||||
|
return VT(bs.begin(), bs.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
key = std::span(bs.begin(), found.begin());
|
||||||
|
|
||||||
|
|
||||||
|
return utils::AdcTrimSpacesView<VT>(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto keyword() const
|
auto keyword() const
|
||||||
@ -49,6 +200,33 @@ public:
|
|||||||
auto params(size_t start = 0, size_t N = std::numeric_limits<size_t>::max())
|
auto params(size_t start = 0, size_t N = std::numeric_limits<size_t>::max())
|
||||||
{
|
{
|
||||||
auto val = base_t::template value<std::ranges::range_value_t<R>>();
|
auto val = base_t::template value<std::ranges::range_value_t<R>>();
|
||||||
|
|
||||||
|
// auto p = utils::AdcTokenManip(val).tokens(start, N);
|
||||||
|
|
||||||
|
R res;
|
||||||
|
std::ranges::for_each(std::views::split(val, keyParamDelimiter) | std::views::drop(start) | std::views::take(N),
|
||||||
|
[&res](const auto& el) {
|
||||||
|
// remove spaces
|
||||||
|
std::back_inserter(res) = utils::AdcTrimSpacesView<std::ranges::range_value_t<R>>(el);
|
||||||
|
// std::ranges::copy(utils::AdcTrimSpaces(el), std::back_inserter(res));
|
||||||
|
});
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto params(size_t start = 0, size_t N = std::numeric_limits<size_t>::max())
|
||||||
|
{
|
||||||
|
return params<std::vector<std::string_view>>(start, N);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <traits::adc_output_char_range R>
|
||||||
|
auto joinParams(size_t start = 0, size_t N = std::numeric_limits<size_t>::max())
|
||||||
|
{
|
||||||
|
R res;
|
||||||
|
utils::AdcJoinRange(params<std::vector<std::span<const char>>>(start, N), paramParamDelimiter, res);
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
// #include "../common/adc_utils.h"
|
// #include "../common/adc_utils.h"
|
||||||
// #include "../net/adc_netmessage.h"
|
// #include "../net/adc_netmessage.h"
|
||||||
|
|
||||||
|
#include "../net/adc_device_netmsg.h"
|
||||||
#include "../net/adc_endpoint.h"
|
#include "../net/adc_endpoint.h"
|
||||||
#include "../net/adc_netmsg.h"
|
#include "../net/adc_netmsg.h"
|
||||||
|
|
||||||
@ -80,6 +81,18 @@ TEST_CASE("[ADC NET MESSAGE]")
|
|||||||
ept.setEndpoint(ee);
|
ept.setEndpoint(ee);
|
||||||
|
|
||||||
std::cout << "EPT: [" << ept.endpoint() << "]\n";
|
std::cout << "EPT: [" << ept.endpoint() << "]\n";
|
||||||
|
|
||||||
|
|
||||||
|
std::string bs = " SET EXP 1.24 0.23652 9.765432 ";
|
||||||
|
std::cout << "BS: {" << bs << "}\n";
|
||||||
|
|
||||||
|
AdcDeviceNetMessage md(bs);
|
||||||
|
|
||||||
|
std::cout << "KEY = {" << md.keyword() << "}\n";
|
||||||
|
std::cout << "KEY = {" << md.key() << "}\n";
|
||||||
|
for (auto& pp : md.params(1, 2)) {
|
||||||
|
std::cout << "PAR: " << pp << "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user