2#include <ossia/detail/pod_vector.hpp>
3#include <ossia/network/sockets/writers.hpp>
5#include <boost/asio/buffer.hpp>
6#include <boost/asio/error.hpp>
7#include <boost/asio/write.hpp>
12template <u
int8_t Start = 0x02, u
int8_t End = 0x03, u
int8_t Escape = 0x10>
13struct delimiter_framing
16 Start != End && Start != Escape && End != Escape,
17 "start, end, and escape bytes must be distinct");
19 template <
typename Socket>
23 alignas(64) uint8_t m_readbuf[4096];
24 ossia::pod_vector<char> m_decoded;
30 } m_status{waiting_start};
32 explicit decoder(Socket& socket)
35 m_decoded.reserve(1024);
41 socket.async_read_some(
42 boost::asio::buffer(m_readbuf),
44 f = std::move(f)](boost::system::error_code ec, std::size_t sz)
mutable {
45 if(!f.validate_stream(ec))
49 process_bytes(f, m_readbuf, sz);
51 receive(std::move(f));
56 void process_bytes(
const F& f,
const uint8_t* data, std::size_t sz)
58 const uint8_t* ptr = data;
59 const uint8_t* end = data + sz;
63 if(m_status == reading_data)
66 const uint8_t* run_end = ptr;
67 while(run_end < end && *run_end != End && *run_end != Escape
74 m_decoded.end(),
reinterpret_cast<const char*
>(ptr),
75 reinterpret_cast<const char*
>(run_end));
80 process_byte(f, *ptr++);
84 process_byte(f, *ptr++);
90 void process_byte(
const F& f, uint8_t
byte)
97 m_status = reading_data;
106 m_status = waiting_start;
107 if(m_decoded.size() > 0)
108 f((
const unsigned char*)m_decoded.data(), m_decoded.size());
112 m_status = reading_escape;
119 m_decoded.push_back(
byte);
125 m_decoded.push_back(
byte);
126 m_status = reading_data;
132 template <
typename Socket>
136 ossia::pod_vector<uint8_t> m_buf;
138 void write(
const char* data, std::size_t sz)
141 m_buf.reserve(sz * 2 + 2);
142 m_buf.push_back(Start);
144 auto* src =
reinterpret_cast<const uint8_t*
>(data);
145 for(std::size_t i = 0; i < sz; ++i)
152 m_buf.push_back(Escape);
153 m_buf.push_back(src[i]);
156 m_buf.push_back(src[i]);
160 m_buf.push_back(End);
162 this->do_write(socket, boost::asio::buffer(m_buf.data(), m_buf.size()));
165 template <
typename T>
166 void do_write(T& sock,
const boost::asio::const_buffer& buf)
168 boost::asio::write(sock, buf);
171 template <
typename T>
172 void do_write(multi_socket_writer<T>& sock,
const boost::asio::const_buffer& buf)
180using stx_etx_framing = delimiter_framing<0x02, 0x03, 0x10>;