WIP: sequencer rework

This commit is contained in:
2021-09-26 22:30:36 +03:00
parent fd64d8726c
commit ca38dfa2f1
4 changed files with 694 additions and 372 deletions
+44 -86
View File
@@ -54,48 +54,7 @@ namespace tbx {
*
* \example implementation example
* \code
* using Queue = equeue<char, 512, true>;
*
* class BG95 :
* public BG95_base<BG95, Queue, 256> {
* using base_type = BG95_base<BG95, Queue, 256>;
* using range_t = typename Queue::range_t;
* private: // data
* Queue rx_q{};
* std::atomic<size_t> lines{};
* public:
* BG95() :
* rx_q(equeue<char, 512, true>::data_match::MATCH_PUSH, base_type::delimiter, [&](){
* lines.fetch_add(1, std::memory_order_acq_rel);
* }), lines(0) {
* // init code here ...
* }
* // ISR handler
* void usart_isr_ (void) {
* rx_q << // char from ISR
* }
* // CRTP requirements
* size_t get(char* data, bool wait =false) {
* do {
* if (lines.load(std::memory_order_acquire)) {
* size_t n =0;
* do{
* *data << rx_q;
* ++n;
* } while (*data++ != base_type::delimiter);
* lines.fetch_sub(1, std::memory_order_acq_rel);
* return n;
* }
* } while (wait);
* return 0;
* }
* size_t put (const char* data, size_t n) {
* // send data to UART
* return n;
* }
* const range_t contents() const { return range_t {rx_q.begin(), rx_q.end()}; }
* clock_t clock() { } // return systems CPU time
* };
* \endcode
*
* \tparam Impl_t
@@ -103,30 +62,30 @@ namespace tbx {
* \tparam N
* \tparam Delimiter
*/
template<typename Impl_t, typename Cont_t, size_t N, char Delimiter ='\n'>
template<typename Impl_t, size_t N, char Delimiter ='\n'>
class BG95_base
: public sequencer<BG95_base<Impl_t, Cont_t, N, Delimiter>, Cont_t, char, N>{
: public sequencer<BG95_base<Impl_t, N, Delimiter>, char, N>{
_CRTP_IMPL(Impl_t);
static_assert(
std::is_same_v<typename Cont_t::value_type, char>,
"Cont_t must be a container of type char"
);
// local type dispatch
using base_type = sequencer<BG95_base, Cont_t, char, N>;
using str_view_t = typename base_type::str_view_t;
using range_t = typename Cont_t::range_t;
using base_type = sequencer<BG95_base, char, N>;
//! \name Public types
//! @{
public:
using action_t = typename base_type::action_t;
using control_t = typename base_type::control_t;
using match_t = typename base_type::match_t;
using handler_ft = typename base_type::handler_ft;
using value_type = char;
using pointer_type = char*;
using size_type = size_t;
using string_view = typename base_type::string_view;
using action_t = typename base_type::action_t;
using control_t = typename base_type::control_t;
using match_ft = typename base_type::match_ft;
using handler_ft = typename base_type::handler_ft;
template<size_t Nm>
using script_t = typename base_type::template script_t<Nm>;
using script_t = typename base_type::template script_t<Nm>;
//! Publish delimiter
constexpr static char delimiter = Delimiter;
@@ -134,8 +93,8 @@ class BG95_base
//! Required types for inetd async handler operation
//! @{
struct inetd_handler_t {
str_view_t token;
match_t match;
string_view token;
match_ft match;
handler_ft handler;
};
template <size_t Nm>
@@ -169,8 +128,8 @@ class BG95_base
size_t put (const char* data, size_t n) {
return impl().put (data, n);
}
const range_t contents () const {
return impl().contents();
size_t contents (char* data) {
return impl().contents(data);
}
clock_t clock () {
return impl().clock();
@@ -197,30 +156,29 @@ class BG95_base
}
template <char Marker = '%'>
std::pair<size_t, bool> parse (const char* expected, const str_view_t buffer, char* token) {
if (*expected == Marker) {
// We have Marker. Copy to token the next part of buffer, from begin up to expected[1] where
// the expected[1] character is and return the size of that part.
auto next = std::find(buffer.begin(), buffer.end(), expected[1]);
if (next == buffer.end()) {
*token =0;
return std::make_pair(0, false);
std::pair<size_t, bool> parse (const char* expected, const string_view buffer, char* token) {
do {
if (*expected == Marker) {
// We have Marker. Copy to token the next part of buffer, from begin up to expected[1] where
// the expected[1] character is and return the size of that part.
auto next = std::find(buffer.begin(), buffer.end(), expected[1]);
if (next == buffer.end())
break;
char* nullpos = std::copy(buffer.begin(), next, token);
*nullpos =0;
return std::make_pair(next - buffer.begin(), true);
}
char* nullpos = std::copy(buffer.begin(), next, token);
*nullpos =0;
return std::make_pair(next - buffer.begin(), true);
}
else if (*expected == buffer.front()) {
// We have character match, copy the character to token and return 1 (the char size)
*token++ = buffer.front();
*token =0;
return std::make_pair(1, false);
}
else {
// Discrepancy. Return 0 (none parsed)
*token =0;
return std::make_pair(0, false);
}
else if (*expected == buffer.front()) {
// We have character match, copy the character to token and return 1 (the char size)
*token++ = buffer.front();
*token =0;
return std::make_pair(1, false);
}
} while (0);
// Fail to parse
*token =0;
return std::make_pair(0, false);
}
//! @}
@@ -297,7 +255,7 @@ class BG95_base
* \endcode
*/
template <typename T, char Marker = '%'>
bool command (const str_view_t cmd, const str_view_t expected, T* value, clock_t timeout =0) {
bool command (const string_view cmd, const string_view expected, T* value, clock_t timeout =0) {
char buffer[N];
char token[N];
@@ -343,7 +301,7 @@ class BG95_base
bool match = false;
if (inetd_handlers != nullptr) {
for (auto& h : *inetd_handlers)
match |= base_type::check_handle(h.token, h.match, h.handler, {buffer.data(), resp_size});
match |= base_type::check_handle({buffer.data(), resp_size}, h.token, h.match, h.handler);
}
// if no match forward data to receive channel.
if (!match) {