This commit is contained in:
Nils Schulte 2024-01-14 20:02:01 +01:00
parent 39922749ec
commit 8d97f96db2
3 changed files with 263 additions and 265 deletions

View File

@ -1,33 +1,39 @@
#ifndef SIMPLESYNC_HPP #ifndef SIMPLESYNC_HPP
#define SIMPLESYNC_HPP #define SIMPLESYNC_HPP
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <vector>
#ifdef ARDUINO #ifdef ARDUINO
#include <Arduino.h> #include <Arduino.h>
#ifdef __AVR__ #ifdef __AVR__
#include "include/nonstd_functional.hpp" #include "include/nonstd_functional.hpp"
using nonstd::function; using nonstd::function;
#else /* ndef __AVR__ */ #else /* ndef __AVR__ */
using std::function; #define STDCLIB
#endif #endif
#else /* ndef ARDUINO */ #else /* ndef ARDUINO */
#define STDCLIB
#endif
#ifdef STDCLIB
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
using std::function; using std::function;
using std::string;
#endif #endif
namespace simplesync { namespace simplesync {
enum error_t { enum error_t {
BUFFER_OVERFLOW = (-1), BUFFER_OVERFLOW = (-1),
INVALID_COMMAND = (-2), INVALID_COMMAND = (-2),
ID_INVALID = (-3), UNKNOWN_INTERFACE = (-3),
OUT_OF_MEMORY = (-4), OUT_OF_MEMORY = (-4),
CRC_MISSMATCH = (-5), CRC_MISSMATCH = (-5),
}; };
inline int cobs_encode(uint8_t *buf_in, unsigned int buf_in_size, uint8_t *buf_out, inline int cobs_encode(uint8_t *buf_in, unsigned int buf_in_size, uint8_t *buf_out,
@ -128,47 +134,155 @@ inline uint16_t calc_fletcher_checksum(uint8_t *buf, unsigned int buf_size) {
} }
template <typename time_t, typename timedelta_t, unsigned int BUF_SIZE = 256, template <typename time_t, typename timedelta_t, unsigned int BUF_SIZE = 256,
unsigned int str_len_max = 32> bool DYNAMIC_INTERFACES = false>
class SimpleSync { class SimpleSync {
public: public:
static constexpr unsigned int STR_LEN_MAX = str_len_max; class Interface {
class NumberInterface {
public: public:
time_t last_send; uint8_t type;
char *key; string key;
timedelta_t update_interval;
std::function<int(uint8_t *buf, unsigned int buf_size)> pack;
std::function<int(uint8_t *buf, unsigned int buf_size)> unpack;
bool send_requested = true; bool send_requested = true;
int value; time_t last_send;
NumberInterface(SimpleSync &s, char *key, timedelta_t update_interval)
: key(key), update_interval(update_interval) { timedelta_t update_interval;
s.number_interfaces.push_back(this); bool update_periodically;
void *data;
bool data_owned;
Interface(uint8_t type, string key, void *data,
std::function<int(uint8_t *buf, unsigned int buf_size)> pack,
std::function<int(uint8_t *buf, unsigned int buf_size)> unpack)
: type(type), key(key), pack(pack), unpack(unpack), update_periodically(false),
data(data), data_owned(false) {}
~Interface() {
if (data != nullptr && data_owned) switch (type) {
case 0x01:
delete (int *)data;
break;
case 0x02:
delete (string *)data;
break;
default:
free(data);
break;
}
} }
}; };
class StringInterface { static Interface *NumberPtr(SimpleSync &sync, string key, int *value_ptr) {
public: sync.interfaces.push_back(std::make_unique<Interface>(
time_t last_send; 0x01, key, (void *)value_ptr,
char *key; [=](uint8_t *buf, unsigned int buf_size) -> int { /* pack */
timedelta_t update_interval; if (buf_size < sizeof(int) * 8 / 7)
bool send_requested = true; return BUFFER_OVERFLOW;
char value[str_len_max + 1]; return encode_varint(*value_ptr, buf);
StringInterface(SimpleSync &s, char *key, timedelta_t update_interval) },
: key(key), update_interval(update_interval) { [=](uint8_t *buf, unsigned int buf_size) -> int { /* unpack */
value[str_len_max] = 0x00; buf_size = 1 * buf_size;
s.string_interfaces.push_back(this); return decode_varint(buf, *value_ptr);
} }));
}; return sync.interfaces.back().get();
}
std::vector<NumberInterface *> number_interfaces; static Interface *NumberPtrPeriodic(SimpleSync &sync, string key, int *value_ptr,
std::vector<StringInterface *> string_interfaces; timedelta_t update_interval) {
auto i = NumberPtr(sync, key, value_ptr);
if (i) {
i->update_interval = update_interval;
i->update_periodically = true;
}
return i;
}
static Interface *Number(SimpleSync &sync, string key) {
auto v_ptr = new int;
Interface *i = NumberPtr(sync, key, v_ptr);
if (i)
i->data_owned = true;
else
delete v_ptr;
return i;
}
static Interface *StringPtr(SimpleSync &sync, string key, string *value_ptr) {
sync.interfaces.push_back(std::make_unique<Interface>(
0x02, key, (void *)value_ptr,
[=](uint8_t *buf, unsigned int buf_size) -> int { /* pack */
auto value_len =
1 + strlen(value_ptr->c_str());
if (buf_size < value_len)
return BUFFER_OVERFLOW;
memcpy(buf, value_ptr->c_str(),
value_len);
return value_len;
},
[=](uint8_t *buf, unsigned int buf_size) -> int { /* unpack */
auto strl = strlen((char *)buf) + 1;
if (strl > buf_size)
return BUFFER_OVERFLOW;
value_ptr->assign((char *)buf);
return strl;
}));
return sync.interfaces.back().get();
}
static Interface *StringPtrPeriodic(SimpleSync &sync, string key, string *value_ptr,
timedelta_t update_interval) {
auto i = StringPtr(sync, key, value_ptr);
if (i) {
i->update_interval = update_interval;
i->update_periodically = true;
}
return i;
}
static Interface *String(SimpleSync &sync, string key) {
auto v_ptr = new string;
Interface *i = StringPtr(sync, key, v_ptr);
if (i)
i->data_owned = true;
else
delete v_ptr;
return i;
}
// int parse_number(uint8_t *buf, unsigned int buf_size, int* value){
// return decode_varint(&buf[parsed], *value);
// }
std::vector<std::unique_ptr<Interface>> interfaces;
function<int(uint8_t *, unsigned int)> write_pkg; function<int(uint8_t *, unsigned int)> write_pkg;
function<void(NumberInterface *&, char *, int)> number_update; SimpleSync(function<int(uint8_t *, unsigned int)> write_pkg) : write_pkg(write_pkg) {}
function<void(StringInterface *&, char *, char *)> string_update;
SimpleSync(function<int(uint8_t *, unsigned int)> write_pkg, Interface *get_interface(const uint8_t type, const char * const key) const {
function<void(NumberInterface *&, char *, int)> number_update, for (auto &i : interfaces) {
function<void(StringInterface *&, char *, char *)> string_update) if (i->type == type && strcmp(i->key.c_str(), key) == 0) {
: write_pkg(write_pkg), number_update(number_update), string_update(string_update) {} return i.get();
}
}
return nullptr;
}
Interface *get_or_create_interface(uint8_t type, const char * const key) {
Interface *i_exists = get_interface(type, key);
if (i_exists) {
return i_exists;
}
if (DYNAMIC_INTERFACES) {
switch (type) {
case 0x01:
return Number(*this, key);
case 0x02:
return String(*this, key);
}
}
return nullptr;
}
int parse_pkg(uint8_t *buf, unsigned int buf_size) { int parse_pkg(uint8_t *buf, unsigned int buf_size) {
if (buf_size < 4) return CRC_MISSMATCH; if (buf_size < 4) return CRC_MISSMATCH;
@ -176,48 +290,22 @@ class SimpleSync {
if (buf[--buf_size] != (crc & 0xFF) || (buf[--buf_size] != (crc >> 8))) if (buf[--buf_size] != (crc & 0xFF) || (buf[--buf_size] != (crc >> 8)))
return CRC_MISSMATCH; return CRC_MISSMATCH;
for (unsigned int parsed = 0; parsed < buf_size;) { for (unsigned int parsed = 0; parsed < buf_size;) {
switch (buf[parsed]) { uint8_t type = buf[parsed];
switch (type) {
case 0x00: { case 0x00: {
for (auto ni : number_interfaces) ni->send_requested = true; for (auto &ni : interfaces) ni->send_requested = true;
for (auto ni : string_interfaces) ni->send_requested = true;
} break;
case 0x01: {
char *key = (char *)&buf[parsed + 1];
parsed += 1 + strlen(key) + 1;
int value;
parsed += decode_varint(&buf[parsed], value);
NumberInterface *ni_ptr = nullptr;
for (auto ni : number_interfaces) {
if (strcmp(ni->key, key) == 0) {
ni_ptr = ni;
break;
}
}
if (number_update) {
number_update(ni_ptr, key, value);
}
if (ni_ptr) {
ni_ptr->value = value;
}
} break; } break;
case 0x01:
case 0x02: { case 0x02: {
char *key = (char *)&buf[parsed + 1]; char *key = (char *)&buf[parsed + 1];
parsed += 1 + strlen(key) + 1; parsed += 1 + strlen(key) + 1;
char *value = (char *)&buf[parsed]; Interface *ni = get_or_create_interface(type, key);
unsigned int strl = strlen(value) + 1; if (ni == nullptr) return UNKNOWN_INTERFACE;
parsed += strl; int unpacked_bytes = ni->unpack(buf + parsed, buf_size - parsed);
StringInterface *stri_ptr = nullptr; if (unpacked_bytes >= 0) {
for (StringInterface *si : string_interfaces) { parsed += unpacked_bytes;
if (strcmp(si->key, key) == 0) { } else { // ERROR -> return
stri_ptr = si; return unpacked_bytes;
break;
}
}
if (string_update) {
string_update(stri_ptr, key, value);
}
if (stri_ptr) {
memcpy(stri_ptr->value, value, str_len_max > strl ? strl : str_len_max);
} }
} break; } break;
default: default:
@ -236,68 +324,52 @@ class SimpleSync {
write_pkg(cobs_buf, cobs_buf_needed); write_pkg(cobs_buf, cobs_buf_needed);
} }
private:
void encode_and_write_pkg(uint8_t *buf, unsigned int buf_size) {
if (buf_size <= 2) {
return;}
uint8_t cobs_buf[BUF_SIZE];
uint16_t crc = calc_fletcher_checksum(buf, buf_size);
buf[buf_size++] = crc >> 8;
buf[buf_size++] = crc & 0xFF;
unsigned int cobs_buf_needed = cobs_encode(buf, buf_size, cobs_buf, BUF_SIZE);
write_pkg(cobs_buf, cobs_buf_needed);
}
public:
void update(time_t time) { void update(time_t time) {
uint8_t buf[BUF_SIZE]; uint8_t buf[BUF_SIZE];
unsigned int buf_len_used = 0; unsigned int buf_len_used = 0;
for (auto ni : number_interfaces) { for (auto &ni : interfaces) {
if (ni->send_requested || if (ni->send_requested ||
(ni->last_send > time || ni->last_send <= time - ni->update_interval)) { (ni->update_periodically &&
unsigned int strl = strlen(ni->key) + 1; (ni->last_send > time || ni->last_send <= time - ni->update_interval))) {
unsigned int buf_len_needed = 1 + strl + 8 * sizeof(int) / 7; unsigned int strl = strlen(ni->key.c_str()) + 1;
unsigned int buf_len_needed =
1 + strl + 32; // TODO get real pack size (not always 32)
buf_len_needed += buf_len_needed / 0xFF + 3 + 2; // COBS overhead buf_len_needed += buf_len_needed / 0xFF + 3 + 2; // COBS overhead
if (BUF_SIZE < buf_len_needed) continue; // Error: update to large, skip interface if (BUF_SIZE < buf_len_needed) continue; // Error: update to large, skip interface
if (BUF_SIZE < buf_len_used + buf_len_needed) { if (BUF_SIZE < buf_len_used + buf_len_needed) {
uint8_t cobs_buf[BUF_SIZE]; encode_and_write_pkg(buf, buf_len_used);
uint16_t crc = calc_fletcher_checksum(buf, buf_len_used);
buf[buf_len_used++] = crc >> 8;
buf[buf_len_used++] = crc & 0xFF;
unsigned int cobs_buf_needed =
cobs_encode(buf, buf_len_used, cobs_buf, BUF_SIZE);
write_pkg(cobs_buf, cobs_buf_needed);
buf_len_used = 0; buf_len_used = 0;
} }
buf[buf_len_used++] = 0x01; buf[buf_len_used++] = ni->type;
memcpy((char *)&buf[buf_len_used], ni->key, strl); memcpy((char *)&buf[buf_len_used], ni->key.c_str(), strl);
buf_len_used += strl; buf_len_used += strl;
buf_len_used += encode_varint(ni->value, &buf[buf_len_used]); int pack_len = ni->pack(&buf[buf_len_used], BUF_SIZE - buf_len_used);
if (pack_len < 0) {
// ERROR -> return
buf_len_used = 0;
return;
}
buf_len_used += pack_len;
ni->last_send = time; ni->last_send = time;
ni->send_requested = false; ni->send_requested = false;
} }
} }
for (auto ni : string_interfaces) { encode_and_write_pkg(buf, buf_len_used);
if (ni->send_requested || buf_len_used = 0;
(ni->last_send > time || ni->last_send <= time - ni->update_interval)) {
unsigned int strl = strlen(ni->key) + 1;
unsigned int strl_value = strlen(ni->value) + 1;
unsigned int buf_len_needed = 1 + strl + strl_value;
buf_len_needed += buf_len_needed / 0xFF + 3 + 2; // COBS overhead
if (BUF_SIZE < buf_len_needed) continue; // Error: update to large, skip interface
if (BUF_SIZE < buf_len_used + buf_len_needed + 2) {
uint8_t cobs_buf[BUF_SIZE];
uint16_t crc = calc_fletcher_checksum(buf, buf_len_used);
buf[buf_len_used++] = crc >> 8;
buf[buf_len_used++] = crc & 0xFF;
unsigned int cobs_buf_needed =
cobs_encode(buf, buf_len_used, cobs_buf, BUF_SIZE);
write_pkg(cobs_buf, cobs_buf_needed);
buf_len_used = 0;
}
buf[buf_len_used++] = 0x02;
memcpy((char *)&buf[buf_len_used], ni->key, strl);
buf_len_used += strl;
memcpy((char *)&buf[buf_len_used], ni->value, strl_value);
buf_len_used += strl_value;
ni->last_send = time;
ni->send_requested = false;
}
}
if (buf_len_used == 0) return;
uint8_t cobs_buf[BUF_SIZE];
uint16_t crc = calc_fletcher_checksum(buf, buf_len_used);
buf[buf_len_used++] = crc >> 8;
buf[buf_len_used++] = crc & 0xFF;
unsigned int cobs_buf_needed = cobs_encode(buf, buf_len_used, cobs_buf, BUF_SIZE);
write_pkg(cobs_buf, cobs_buf_needed);
} }
int parse_stream_buf(uint8_t *buf, unsigned int buf_size) { int parse_stream_buf(uint8_t *buf, unsigned int buf_size) {
@ -350,31 +422,27 @@ class SimpleSync {
return 0; return 0;
} }
NumberInterface *get_number_if(const char *const key) const { int *get_number(const char * const key) {
for (const auto ni : number_interfaces) { Interface *i = get_interface(0x01, key);
if (strcmp(ni->key, key) == 0) return ni; if (i) return (int *)i->data;
}
return nullptr; return nullptr;
} }
StringInterface *get_string_if(const char *const key) const { string *get_string(const char * const key) {
for (const auto ni : string_interfaces) { Interface *i = get_interface(0x02, key);
if (strcmp(ni->key, key) == 0) return ni; if (i) return (string *)i->data;
}
return nullptr; return nullptr;
} }
#ifdef ARDUINO #ifdef ARDUINO
SimpleSync(Print *ostream, function<void(NumberInterface *&, char *, int)> number_update, SimpleSync(Print *ostream)
function<void(StringInterface *&, char *, char *)> string_update) : SimpleSync([ostream](uint8_t *buf, unsigned int buf_size) {
: write_pkg([ostream](uint8_t *buf, unsigned int buf_size) {
if (ostream) { if (ostream) {
ostream->write(buf, buf_size); ostream->write(buf, buf_size);
return 0; return 0;
} }
return -1; return -1;
}), }) {}
number_update(number_update), string_update(string_update) {}
int handle_stream(Stream &in_stream) { int handle_stream(Stream &in_stream) {
unsigned int buf_new_size = in_stream.available(); unsigned int buf_new_size = in_stream.available();
if (buf_new_size + stream_buf_used > BUF_SIZE) { if (buf_new_size + stream_buf_used > BUF_SIZE) {
@ -390,81 +458,5 @@ class SimpleSync {
#endif #endif
}; };
template <typename time_t, typename timedelta_t, unsigned int buf_len = 256,
unsigned int str_len_max = 32>
class SimpleSyncStatic : public SimpleSync<time_t, timedelta_t, buf_len, str_len_max> {
public:
SimpleSyncStatic(function<int(uint8_t *, unsigned int)> write_pkg)
: SimpleSync<time_t, timedelta_t, buf_len, str_len_max>(write_pkg, nullptr, nullptr){};
#ifdef ARDUINO
SimpleSyncStatic(Print *ostream)
: SimpleSync<time_t, timedelta_t, buf_len, str_len_max>(ostream, nullptr, nullptr) {}
#endif
};
template <typename time_t, typename timedelta_t, unsigned int buf_len = 256,
unsigned int str_len_max = 32>
class SimpleSyncDynamic : public SimpleSync<time_t, timedelta_t, buf_len, str_len_max> {
std::vector<typename SimpleSync<time_t, timedelta_t, buf_len, str_len_max>::NumberInterface *>
dyn_number_interfaces;
std::vector<typename SimpleSync<time_t, timedelta_t, buf_len, str_len_max>::StringInterface *>
dyn_string_interfaces;
std::vector<char *> dyn_keys;
public:
SimpleSyncDynamic(
function<int(uint8_t *, unsigned int)> write_pkg,
function<
void(typename SimpleSync<time_t, timedelta_t, buf_len, str_len_max>::NumberInterface *&,
char *, int)>
dyn_number_update,
function<
void(typename SimpleSync<time_t, timedelta_t, buf_len, str_len_max>::StringInterface *&,
char *, char *)>
dyn_string_update,
timedelta_t dyn_update_feq)
: SimpleSync<time_t, timedelta_t, buf_len, str_len_max>(
write_pkg,
[this, dyn_number_update, dyn_update_feq](
typename SimpleSync<time_t, timedelta_t, buf_len, str_len_max>::NumberInterface *
&ni,
char *key, int value) {
if (ni == nullptr) {
auto allocated_key = (char *)malloc(strlen(key) + 1);
strcpy(allocated_key, key);
dyn_keys.push_back(allocated_key);
ni = new SimpleSync<time_t, timedelta_t, buf_len,
str_len_max>::NumberInterface(*this, allocated_key,
dyn_update_feq);
ni->send_requested = false;
dyn_number_interfaces.push_back(ni);
}
dyn_number_update(ni, key, value);
},
[this, dyn_string_update, dyn_update_feq](
typename SimpleSync<time_t, timedelta_t, buf_len, str_len_max>::StringInterface *
&ni,
char *key, char *value) {
if (ni == nullptr) {
auto allocated_key = (char *)malloc(strlen(key) + 1);
strcpy(allocated_key, key);
dyn_keys.push_back(allocated_key);
ni = new SimpleSync<time_t, timedelta_t, buf_len,
str_len_max>::StringInterface(*this, allocated_key,
dyn_update_feq);
ni->send_requested = false;
dyn_string_interfaces.push_back(ni);
}
dyn_string_update(ni, key, value);
}){};
~SimpleSyncDynamic() {
for (auto i : dyn_number_interfaces) delete i;
for (auto i : dyn_string_interfaces) delete i;
for (auto i : dyn_keys) free(i);
};
#ifdef ARDUINO
SimpleSyncDynamic(Print *ostream)
: SimpleSync<time_t, timedelta_t, buf_len, str_len_max>(ostream, nullptr, nullptr) {}
#endif
};
} // namespace simplesync } // namespace simplesync
#endif // SIMPLESYNC_HPP #endif // SIMPLESYNC_HPP

View File

@ -8,44 +8,42 @@
#include "simplesync.hpp" #include "simplesync.hpp"
namespace py = pybind11; namespace py = pybind11;
typedef simplesync::SimpleSyncDynamic<std::chrono::time_point<std::chrono::steady_clock>, typedef simplesync::SimpleSync<std::chrono::time_point<std::chrono::steady_clock>,
std::chrono::nanoseconds, 1024> std::chrono::nanoseconds, 1024, true>
SimpleS; SimpleS;
PYBIND11_MODULE(pysimplesync, m) { PYBIND11_MODULE(pysimplesync, m) {
py::class_<SimpleS>(m, "SimpleSync") py::class_<SimpleS>(m, "SimpleSync")
.def(py::init([]() { .def(py::init([]() {
return std::unique_ptr<SimpleS>(new SimpleS( return std::unique_ptr<SimpleS>(new SimpleS([](uint8_t *buf, unsigned int buf_size) {
[](uint8_t *buf, unsigned int buf_size) { py::print(py::bytes((char *)buf, buf_size));
py::print(py::bytes((char *)buf, buf_size)); return 0;
return 0; }));
},
[](SimpleS::NumberInterface *&, char *key, int value) {
py::print(std::string(key), ": ", value);
},
nullptr, std::chrono::nanoseconds::max()));
})) }))
.def( .def(
"__getitem__", "__getitem__",
[](SimpleS &s, const std::string &key) -> py::object { [](SimpleS &s, const std::string &key) -> py::object {
auto ni = s.get_number_if(key.c_str()); auto ni = s.get_number(key.c_str());
if (ni) return py::int_(ni->value); if (ni) return py::int_(*ni);
auto si = s.get_string_if(key.c_str()); auto si = s.get_string(key.c_str());
if (si) return py::str(si->value); if (si) return py::str(*si);
throw pybind11::key_error(); throw pybind11::key_error();
}, },
py::is_operator()) py::is_operator())
.def( .def(
"__getitem__", "__getitem__",
[](SimpleS &s, unsigned int i) -> py::tuple { [](SimpleS &s, unsigned int i) -> py::tuple {
if (i < s.number_interfaces.size()) { if (i < s.interfaces.size()) {
return py::make_tuple(py::str(s.number_interfaces[i]->key), auto &interface = s.interfaces[i];
py::int_(s.number_interfaces[i]->value)); if (!interface) throw pybind11::index_error();
} switch (interface->type) {
i -= s.number_interfaces.size(); case 0x01:
if (i < s.string_interfaces.size()) { return py::make_tuple(py::str(interface->key),
return py::make_tuple(py::str(s.string_interfaces[i]->key), py::int_(*s.get_number(interface->key.c_str())));
py::str(s.string_interfaces[i]->value)); case 0x02:
return py::make_tuple(py::str(interface->key),
py::str(*s.get_string(interface->key.c_str())));
}
} }
throw pybind11::index_error(); throw pybind11::index_error();
}, },
@ -54,20 +52,17 @@ PYBIND11_MODULE(pysimplesync, m) {
"__setitem__", "__setitem__",
[](SimpleS &s, const std::string &key, py::object value) { [](SimpleS &s, const std::string &key, py::object value) {
if (py::isinstance<py::int_>(value)) { if (py::isinstance<py::int_>(value)) {
auto ni = s.get_number_if(key.c_str()); auto ni = s.get_or_create_interface(0x01, key.c_str());
if (ni) { if (ni) {
ni->value = value.cast<int>(); *(int *)ni->data = value.cast<int>();
ni->send_requested = true; ni->send_requested = true;
return; return;
} }
} } else if (py::isinstance<py::str>(value)) {
else if (py::isinstance<py::str>(value)) { auto ni = s.get_or_create_interface(0x02, key.c_str());
auto ni = s.get_string_if(key.c_str());
if (ni) { if (ni) {
if(value.cast<std::string>().length() > SimpleS::STR_LEN_MAX) *(std::string *)ni->data = value.cast<std::string>();
throw pybind11::buffer_error(); ni->send_requested = true;
strcpy(ni->value, value.cast<std::string>().c_str());
ni->send_requested = true;
return; return;
} }
} else } else

View File

@ -1,5 +1,6 @@
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <iostream>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "simplesync.hpp" #include "simplesync.hpp"
@ -46,33 +47,43 @@ unsigned int buf_used = 0;
TEST(simplesync_test, encode_decode) { TEST(simplesync_test, encode_decode) {
buf_used = 0; buf_used = 0;
typedef simplesync::SimpleSyncStatic<int, int, 999> S; typedef simplesync::SimpleSync<int, int, 512, true> S;
S s([](uint8_t *buf, unsigned int buf_size) { S s_send([](uint8_t *buf, unsigned int buf_size) {
memcpy(stream_buf + buf_used, buf, buf_size); memcpy(stream_buf + buf_used, buf, buf_size);
buf_used += buf_size; buf_used += buf_size;
return 0; return 0;
}); });
S s_recv([](uint8_t *, unsigned int) {
return 0;
});
S::NumberInterface n1(s, (char *)"n1", 0); int n1 = 4;
S::StringInterface s1(s, (char *)"s1", 0); int n2 = 2;
S::NumberInterface n2(s, (char *)"n2", 2); std::string str = "hello";
S::NumberPtrPeriodic(s_send, "n1",&n1,0);
n1.value = 4; S::NumberPtrPeriodic(s_send, "n2",&n2,2);
strcpy(s1.value, "hallo"); S::StringPtrPeriodic(s_send, "s1",&str, 0);
n2.value = 2;
for (int time = 0; time < 5; time += 1) { for (int time = 0; time < 5; time += 1) {
buf_used = 0; buf_used = 0;
s.update(time); s_send.update(time);
s.update(time); s_send.update(time);
for(unsigned int i = 0;i < buf_used; i+=1) std::cout << std::hex <<(int) stream_buf[i] << " ";
std::cout << std::dec << std::endl;
unsigned int parsed = 0; unsigned int parsed = 0;
for (unsigned int i = 1; i <= buf_used; i += 1) for (unsigned int i = 1; i <= buf_used; i += 1)
parsed += s.parse_stream_buf(stream_buf + parsed, i - parsed); parsed += s_recv.parse_stream_buf(stream_buf + parsed, i - parsed);
ASSERT_EQ(parsed, buf_used); ASSERT_EQ(parsed, buf_used);
} }
ASSERT_EQ(n1.value, 4); str = "hollo2";
ASSERT_EQ(n2.value, 2); ASSERT_EQ(*s_recv.get_number((char*)"n1"), n1);
ASSERT_STREQ(s1.value,"hallo"); ASSERT_EQ(*s_recv.get_number((char*)"n2"), n2);
ASSERT_STREQ(s_send.get_string((char*)"s1")->c_str(),"hollo2");
ASSERT_STREQ(str.c_str(),"hollo2");
ASSERT_STREQ(s_recv.get_string((char*)"s1")->c_str(),"hello");
ASSERT_EQ(4, n1);
ASSERT_EQ(2, n2);
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {