...
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
#include <algorithm>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <print>
|
#include <print>
|
||||||
|
|
||||||
@@ -6,6 +7,8 @@
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
std::println("{:*^80}\n", " STOP-SEQ PROTOCOL ");
|
||||||
|
|
||||||
snplib::snplib_netproto_stopseq_t<> proto;
|
snplib::snplib_netproto_stopseq_t<> proto;
|
||||||
|
|
||||||
std::string bytes{"SET VAL1 10\n"};
|
std::string bytes{"SET VAL1 10\n"};
|
||||||
@@ -38,13 +41,13 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::println("\n\n");
|
std::println("\n");
|
||||||
|
|
||||||
bytes = "GET VAL2 1";
|
bytes = "GET VAL2 1";
|
||||||
bytes_vec = {std::from_range, bytes};
|
bytes_vec = {std::from_range, bytes};
|
||||||
bytes_lst = {std::from_range, bytes};
|
bytes_lst = {std::from_range, bytes};
|
||||||
|
|
||||||
std::println("MSG: ", bytes_vec);
|
std::println("MSG: {}", bytes_vec);
|
||||||
|
|
||||||
auto bs = proto.toBytes(bytes_vec);
|
auto bs = proto.toBytes(bytes_vec);
|
||||||
std::println("BYTES (from std::vector): {}", bs);
|
std::println("BYTES (from std::vector): {}", bs);
|
||||||
@@ -55,5 +58,37 @@ int main()
|
|||||||
bytes_vec = proto.toBytes<decltype(bytes_vec)>(bytes_lst);
|
bytes_vec = proto.toBytes<decltype(bytes_vec)>(bytes_lst);
|
||||||
std::println("BYTES: {}", bytes_vec);
|
std::println("BYTES: {}", bytes_vec);
|
||||||
|
|
||||||
|
|
||||||
|
std::println("\n\n{:*^80}\n", " BINARY-BLOB PROTOCOL ");
|
||||||
|
|
||||||
|
snplib::snplib_netproto_binary_blob_t<> bb_proto;
|
||||||
|
|
||||||
|
snplib::snplib_random_string_generator_t<> rstr_gen;
|
||||||
|
|
||||||
|
bytes = rstr_gen.generate(15);
|
||||||
|
bytes_vec = {std::from_range, bytes};
|
||||||
|
bytes_lst = {std::from_range, bytes};
|
||||||
|
|
||||||
|
std::println("BLOB: {}", bytes);
|
||||||
|
|
||||||
|
bs = bb_proto.toBytes(bytes_vec);
|
||||||
|
std::println("BYTES (from std::vector): {}", bs);
|
||||||
|
|
||||||
|
auto bs2 = bb_proto.toBytes(bytes_lst);
|
||||||
|
std::println("BYTES (from std::list): {}", bs2);
|
||||||
|
|
||||||
|
auto blob = std::vector(std::from_range, bs | std::views::join);
|
||||||
|
|
||||||
|
std::println("\nBYTES: {}", blob);
|
||||||
|
|
||||||
|
vmsg = bb_proto.fromBytes<std::vector<char>>(blob);
|
||||||
|
if (vmsg) {
|
||||||
|
std::println("BLOB (from std::vector): {}", vmsg.value());
|
||||||
|
} else {
|
||||||
|
std::println("VMSG ERR: {}", vmsg.error().message());
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::array<char, 30> arr = bb_proto.toBytes<decltype(arr)>(bytes_lst);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -84,7 +84,7 @@ int main()
|
|||||||
std::println("valueSeq = '{}'", kvl.valueSeq<std::list<std::string>>());
|
std::println("valueSeq = '{}'", kvl.valueSeq<std::list<std::string>>());
|
||||||
|
|
||||||
|
|
||||||
snplib_randoom_string_generator_t<> rstr_gen;
|
snplib_random_string_generator_t<> rstr_gen;
|
||||||
|
|
||||||
std::println("\n\n");
|
std::println("\n\n");
|
||||||
std::println("RAND STR: {}", rstr_gen.generate());
|
std::println("RAND STR: {}", rstr_gen.generate());
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ struct snplib_netproto_stopseq_t {
|
|||||||
} else {
|
} else {
|
||||||
auto Nelem = std::distance(bytes.begin(), found.begin());
|
auto Nelem = std::distance(bytes.begin(), found.begin());
|
||||||
if (Nelem > std::tuple_size_v<OR>) {
|
if (Nelem > std::tuple_size_v<OR>) {
|
||||||
static_assert(false, "Invalid size of the output byte sequence type!");
|
return std::unexpected(std::make_error_code(std::errc::invalid_seek));
|
||||||
}
|
}
|
||||||
|
|
||||||
OR res;
|
OR res;
|
||||||
@@ -145,7 +145,9 @@ template <size_t SZ_FIELD_WIDTH = 8>
|
|||||||
requires(SZ_FIELD_WIDTH > 0 &&
|
requires(SZ_FIELD_WIDTH > 0 &&
|
||||||
SZ_FIELD_WIDTH <= 16) // not greater than allowed for 64-bit unsigned integer representation
|
SZ_FIELD_WIDTH <= 16) // not greater than allowed for 64-bit unsigned integer representation
|
||||||
struct snplib_netproto_binary_blob_t {
|
struct snplib_netproto_binary_blob_t {
|
||||||
static constexpr std::array<char, 6> SZ_FIELD_FORMAT{'{', ':', '0', '0' + SZ_FIELD_WIDTH, 'X', '}'};
|
static constexpr size_t BLOB_SIZE_FIELD{SZ_FIELD_WIDTH};
|
||||||
|
|
||||||
|
static constexpr std::array<char, 6> BLOB_SIZE_FIELD_FORMAT{'{', ':', '0', '0' + BLOB_SIZE_FIELD, 'X', '}'};
|
||||||
|
|
||||||
template <snplib_input_char_range_c IR>
|
template <snplib_input_char_range_c IR>
|
||||||
auto toBytes(IR&& message)
|
auto toBytes(IR&& message)
|
||||||
@@ -154,7 +156,7 @@ struct snplib_netproto_binary_blob_t {
|
|||||||
|
|
||||||
Nbytes.clear();
|
Nbytes.clear();
|
||||||
// std::format_to(std::back_inserter(Nbytes), "{:08X}", std::ranges::size(std::forward<IR>(message)));
|
// std::format_to(std::back_inserter(Nbytes), "{:08X}", std::ranges::size(std::forward<IR>(message)));
|
||||||
std::format_to(std::back_inserter(Nbytes), std::string_view(SZ_FIELD_FORMAT),
|
std::format_to(std::back_inserter(Nbytes), std::string_view(BLOB_SIZE_FIELD_FORMAT),
|
||||||
std::ranges::size(std::forward<IR>(message)));
|
std::ranges::size(std::forward<IR>(message)));
|
||||||
|
|
||||||
if constexpr (std::ranges::contiguous_range<IR>) {
|
if constexpr (std::ranges::contiguous_range<IR>) {
|
||||||
@@ -163,6 +165,82 @@ struct snplib_netproto_binary_blob_t {
|
|||||||
return std::make_tuple(std::ranges::subrange(Nbytes), std::ranges::subrange(message));
|
return std::make_tuple(std::ranges::subrange(Nbytes), std::ranges::subrange(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <snplib_char_range_c OR, snplib_input_char_range_c IR>
|
||||||
|
std::expected<OR, std::error_code> fromBytes(IR&& bytes)
|
||||||
|
{
|
||||||
|
using inp_t = std::remove_cvref_t<IR>;
|
||||||
|
|
||||||
|
// return a view
|
||||||
|
static constexpr bool ret_view =
|
||||||
|
std::ranges::view<OR> && std::ranges::viewable_range<inp_t> &&
|
||||||
|
(std::constructible_from<OR, std::ranges::iterator_t<inp_t>, std::ranges::iterator_t<inp_t>> ||
|
||||||
|
std::constructible_from<OR, std::ranges::iterator_t<inp_t>, std::ranges::sentinel_t<inp_t>>);
|
||||||
|
|
||||||
|
|
||||||
|
auto bytes_sz = std::ranges::size(std::forward<IR>(bytes));
|
||||||
|
|
||||||
|
if (bytes_sz < BLOB_SIZE_FIELD) { // not enough data
|
||||||
|
return std::unexpected(std::make_error_code(std::errc::invalid_seek));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<size_t> blob_sz;
|
||||||
|
if constexpr (std::ranges::contiguous_range<IR>) {
|
||||||
|
blob_sz = snplib_num_from_range<size_t>(std::span(bytes.begin(), BLOB_SIZE_FIELD), 16);
|
||||||
|
} else {
|
||||||
|
blob_sz = snplib_num_from_range<size_t>(bytes | std::views::take(BLOB_SIZE_FIELD), 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!blob_sz) {
|
||||||
|
return std::unexpected(std::make_error_code(std::errc::invalid_argument));
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_sz -= BLOB_SIZE_FIELD;
|
||||||
|
|
||||||
|
if (bytes_sz < blob_sz.value()) {
|
||||||
|
return std::unexpected(std::make_error_code(std::errc::invalid_seek));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it_start = std::forward<IR>(bytes).begin();
|
||||||
|
std::advance(it_start, BLOB_SIZE_FIELD);
|
||||||
|
auto it_end = std::forward<IR>(bytes).begin();
|
||||||
|
std::advance(it_end, BLOB_SIZE_FIELD + blob_sz.value());
|
||||||
|
|
||||||
|
if constexpr (ret_view) {
|
||||||
|
return OR(it_start, it_end); // return without blob size field
|
||||||
|
} else if constexpr (snplib_output_char_range_c<OR>) {
|
||||||
|
if constexpr (!snplib_fixed_size_range_c<OR>) {
|
||||||
|
if constexpr (std::constructible_from<OR, std::ranges::iterator_t<inp_t>,
|
||||||
|
std::ranges::iterator_t<inp_t>>) {
|
||||||
|
return OR(it_start, it_end); // return without blob size field!!!
|
||||||
|
} else if constexpr (std::is_default_constructible_v<OR>) {
|
||||||
|
OR res;
|
||||||
|
std::ranges::copy(
|
||||||
|
std::forward<IR>(bytes) | std::views::drop(BLOB_SIZE_FIELD) | std::views::take(blob_sz.value()),
|
||||||
|
std::back_inserter(res));
|
||||||
|
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
static_assert(false, "Unsupported output byte sequence type!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (blob_sz.value() > std::tuple_size_v<OR>) {
|
||||||
|
return std::unexpected(std::make_error_code(std::errc::invalid_seek));
|
||||||
|
}
|
||||||
|
|
||||||
|
OR res;
|
||||||
|
for (auto it = res.begin(); it != res.end(); std::advance(it, 1)) {
|
||||||
|
*it = *it_start;
|
||||||
|
std::advance(it_start, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
static_assert(false, "Unsupported output byte sequence type!");
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace snplib
|
} // namespace snplib
|
||||||
@@ -290,15 +290,30 @@ OR snplib_join_char_ranges(IR&& input, DR&& delim, size_t start = 0, size_t N =
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T, snplib_input_char_range_c R>
|
template <typename T, snplib_input_char_range_c R>
|
||||||
static std::optional<T> snplib_num_from_range(R&& r)
|
static std::optional<T> snplib_num_from_range(
|
||||||
requires((std::integral<T> || std::floating_point<T>) && std::ranges::contiguous_range<R>)
|
R&& r,
|
||||||
|
std::conditional_t<std::integral<T>, int, std::chars_format> fmt =
|
||||||
|
[]() {
|
||||||
|
if constexpr (std::integral<T>)
|
||||||
|
return 10;
|
||||||
|
else
|
||||||
|
return std::chars_format::general;
|
||||||
|
}())
|
||||||
|
requires(std::integral<T> || std::floating_point<T>)
|
||||||
{
|
{
|
||||||
|
if constexpr (!std::ranges::contiguous_range<R>) {
|
||||||
|
std::string sval(std::from_range, std::forward<R>(r));
|
||||||
|
|
||||||
|
return snplib_num_from_range<T>(sval);
|
||||||
|
}
|
||||||
|
|
||||||
T val;
|
T val;
|
||||||
const char* end_ptr = &*r.end();
|
const char* end_ptr = &*r.end();
|
||||||
|
|
||||||
if constexpr (std::integral<T>) {
|
if constexpr (std::integral<T>) {
|
||||||
auto cvt_res = std::from_chars(&*r.begin(), &*r.end(), val);
|
auto cvt_res = std::from_chars(&*r.begin(), &*r.end(), val, fmt);
|
||||||
if (cvt_res.ec != std::errc()) {
|
if (cvt_res.ec != std::errc()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
} else if (cvt_res.ptr != end_ptr) {
|
} else if (cvt_res.ptr != end_ptr) {
|
||||||
@@ -325,7 +340,7 @@ static std::optional<T> snplib_num_from_range(R&& r)
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
auto cvt_res = std::from_chars(&*r.begin(), &*r.end(), val);
|
auto cvt_res = std::from_chars(&*r.begin(), &*r.end(), val, fmt);
|
||||||
|
|
||||||
if (cvt_res.ec != std::errc()) {
|
if (cvt_res.ec != std::errc()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
@@ -344,7 +359,7 @@ static std::optional<T> snplib_num_from_range(R&& r)
|
|||||||
|
|
||||||
|
|
||||||
template <std::uniform_random_bit_generator RANDOM_GEN_T = std::mt19937_64>
|
template <std::uniform_random_bit_generator RANDOM_GEN_T = std::mt19937_64>
|
||||||
class snplib_randoom_string_generator_t
|
class snplib_random_string_generator_t
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::random_device _randomDev{};
|
std::random_device _randomDev{};
|
||||||
@@ -363,30 +378,30 @@ public:
|
|||||||
|
|
||||||
static constexpr size_t DEFAULT_RANDOM_STR_LEN = 32;
|
static constexpr size_t DEFAULT_RANDOM_STR_LEN = 32;
|
||||||
|
|
||||||
snplib_randoom_string_generator_t() : _randomGen(_randomDev()) {}
|
snplib_random_string_generator_t() : _randomGen(_randomDev()) {}
|
||||||
|
|
||||||
template <typename SEED_T>
|
template <typename SEED_T>
|
||||||
snplib_randoom_string_generator_t(SEED_T seed) : _randomGen(seed)
|
snplib_random_string_generator_t(SEED_T seed) : _randomGen(seed)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template <snplib_output_char_range_c OR,
|
template <snplib_output_char_range_c OR,
|
||||||
snplib_input_char_range_c IR = decltype(snplib_randoom_string_generator_t::DEFAULT_RANDOM_CHAR_RANGE)>
|
snplib_input_char_range_c IR = decltype(snplib_random_string_generator_t::DEFAULT_RANDOM_CHAR_RANGE)>
|
||||||
OR generate(size_t len = snplib_randoom_string_generator_t::DEFAULT_RANDOM_STR_LEN,
|
OR generate(size_t len = snplib_random_string_generator_t::DEFAULT_RANDOM_STR_LEN,
|
||||||
IR char_range = snplib_randoom_string_generator_t::DEFAULT_RANDOM_CHAR_RANGE)
|
IR char_range = snplib_random_string_generator_t::DEFAULT_RANDOM_CHAR_RANGE)
|
||||||
{
|
{
|
||||||
OR res;
|
OR res;
|
||||||
|
|
||||||
size_t max_idx = std::ranges::size(char_range);
|
size_t max_idx = std::ranges::size(char_range);
|
||||||
if (max_idx < 2) {
|
if (max_idx < 2) {
|
||||||
char_range = snplib_randoom_string_generator_t::DEFAULT_RANDOM_CHAR_RANGE;
|
char_range = snplib_random_string_generator_t::DEFAULT_RANDOM_CHAR_RANGE;
|
||||||
max_idx = snplib_randoom_string_generator_t::DEFAULT_RANDOM_CHAR_RANGE.size();
|
max_idx = snplib_random_string_generator_t::DEFAULT_RANDOM_CHAR_RANGE.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::uniform_int_distribution<size_t> rdist(0, --max_idx);
|
std::uniform_int_distribution<size_t> rdist(0, --max_idx);
|
||||||
|
|
||||||
if (!len) {
|
if (!len) {
|
||||||
len = snplib_randoom_string_generator_t::DEFAULT_RANDOM_STR_LEN;
|
len = snplib_random_string_generator_t::DEFAULT_RANDOM_STR_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < len; ++i) {
|
for (size_t i = 0; i < len; ++i) {
|
||||||
@@ -396,9 +411,9 @@ public:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <snplib_input_char_range_c IR = decltype(snplib_randoom_string_generator_t::DEFAULT_RANDOM_CHAR_RANGE)>
|
template <snplib_input_char_range_c IR = decltype(snplib_random_string_generator_t::DEFAULT_RANDOM_CHAR_RANGE)>
|
||||||
std::string generate(size_t len = snplib_randoom_string_generator_t::DEFAULT_RANDOM_STR_LEN,
|
std::string generate(size_t len = snplib_random_string_generator_t::DEFAULT_RANDOM_STR_LEN,
|
||||||
IR char_range = snplib_randoom_string_generator_t::DEFAULT_RANDOM_CHAR_RANGE)
|
IR char_range = snplib_random_string_generator_t::DEFAULT_RANDOM_CHAR_RANGE)
|
||||||
{
|
{
|
||||||
return generate<std::string>(len, char_range);
|
return generate<std::string>(len, char_range);
|
||||||
}
|
}
|
||||||
@@ -406,7 +421,7 @@ public:
|
|||||||
template <snplib_output_char_range_c OR>
|
template <snplib_output_char_range_c OR>
|
||||||
OR UUIDv4String()
|
OR UUIDv4String()
|
||||||
{
|
{
|
||||||
OR res = generate(36, snplib_randoom_string_generator_t::UUID_STRING_RANGE);
|
OR res = generate(36, snplib_random_string_generator_t::UUID_STRING_RANGE);
|
||||||
auto iter = res.begin();
|
auto iter = res.begin();
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (size_t idx : std::array<size_t, 4>{8, 13, 18, 23}) {
|
for (size_t idx : std::array<size_t, 4>{8, 13, 18, 23}) {
|
||||||
|
|||||||
Reference in New Issue
Block a user