WIP: sequencer rework
This commit is contained in:
+44
-86
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user