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 <
typename Socket>
16 alignas(64) uint8_t m_readbuf[4096];
17 ossia::pod_vector<uint8_t> m_encoded;
18 ossia::pod_vector<char> m_decoded;
19 lifetime_token m_lifetime;
21 explicit cobs_decoder(Socket& socket)
24 m_encoded.reserve(1024);
25 m_decoded.reserve(1024);
31 socket.async_read_some(
32 boost::asio::buffer(m_readbuf),
33 [
this, alive = m_lifetime.watch(),
34 f = std::move(f)](boost::system::error_code ec, std::size_t sz)
mutable {
39 if(!f.validate_stream(ec))
43 process_bytes(f, m_readbuf, sz);
45 receive(std::move(f));
50 void process_bytes(
const F& f,
const uint8_t* data, std::size_t sz)
52 const uint8_t* ptr = data;
53 const uint8_t* end = data + sz;
58 const uint8_t* delim = ptr;
59 while(delim < end && *delim != 0x00)
64 m_encoded.insert(m_encoded.end(), ptr, delim);
72 if(!m_encoded.empty())
75 f((
const unsigned char*)m_decoded.data(), m_decoded.size());
85 const uint8_t* ptr = m_encoded.data();
86 const uint8_t* end = ptr + m_encoded.size();
90 uint8_t code = *ptr++;
94 uint8_t count = code - 1;
98 for(uint8_t j = 0; j < count; ++j)
99 m_decoded.push_back(
static_cast<char>(*ptr++));
102 if(code < 0xFF && ptr < end)
103 m_decoded.push_back(0);
106 return m_decoded.size() > 0;
110template <
typename Socket>
114 ossia::pod_vector<uint8_t> m_buf;
116 void write(
const char* data, std::size_t sz)
119 m_buf.reserve(sz + sz / 254 + 3);
121 const auto* src =
reinterpret_cast<const uint8_t*
>(data);
123 std::size_t code_idx = m_buf.size();
127 for(std::size_t i = 0; i < sz; ++i)
131 m_buf[code_idx] = code;
132 code_idx = m_buf.size();
138 m_buf.push_back(src[i]);
142 m_buf[code_idx] = code;
143 code_idx = m_buf.size();
150 m_buf[code_idx] = code;
151 m_buf.push_back(0x00);
153 this->do_write(socket, boost::asio::buffer(m_buf.data(), m_buf.size()));
156 template <
typename T>
157 void do_write(T& sock,
const boost::asio::const_buffer& buf)
159 boost::asio::write(sock, buf);
162 template <
typename T>
163 void do_write(multi_socket_writer<T>& sock,
const boost::asio::const_buffer& buf)
171 template <
typename Socket>
172 using encoder = cobs_encoder<Socket>;
173 template <
typename Socket>
174 using decoder = cobs_decoder<Socket>;