emlabcpp
modern opinionated embedded C++ library
cobs.h
Go to the documentation of this file.
1 #pragma once
23 
24 #include "../algorithm.h"
25 #include "../view.h"
26 
27 #include <cstddef>
28 
29 namespace emlabcpp
30 {
31 
33 
35 {
36 public:
38  : target( target )
39  {
40  }
41 
42  bool insert( std::byte b )
43  {
44  if ( b != std::byte{ 0 } ) {
45  count += 1;
46  *p = b;
47  } else {
48  *last_p = std::byte{ count };
49  count = 1;
50  last_p = p;
51  }
52 
53  ++p;
54 
55  if ( p == target.end() )
56  return false;
57 
58  if ( count == 255 ) {
59  *last_p = std::byte{ 255 };
60  count = 1;
61  last_p = p++;
62  }
63 
64  return p != target.end();
65  }
66 
68  {
69  *last_p = std::byte{ count };
70  return { target.begin(), p };
71  }
72 
73 private:
74  view< std::byte* > target;
75  std::byte* last_p = target.begin();
76  std::byte* p = std::next( last_p );
77  uint8_t count = 1;
78 };
79 
83 inline std::tuple< bool, view< std::byte* > >
85 {
86  cobs_encoder e( target );
87  for ( std::byte b : source )
88  if ( !e.insert( b ) )
89  return { false, {} };
90  return { true, std::move( e ).commit() };
91 }
92 
94 {
95  [[nodiscard]] std::optional< std::byte > get( std::byte inpt ) const
96  {
97  if ( offset == 1 ) {
98  if ( nonzero )
99  return std::nullopt;
100  else
101  return std::byte{ 0 };
102  }
103  return inpt;
104  }
105 
107  {
108  return offset == 1 && nonzero;
109  }
110 
111  void advance( std::byte inpt )
112  {
113  if ( offset == 1 ) {
114  nonzero = inpt == std::byte{ 255 };
115  offset = static_cast< uint8_t >( inpt );
116  } else {
117  offset--;
118  }
119  }
120 
121  [[nodiscard]] std::optional< std::byte > iter( std::byte inpt )
122  {
123  std::optional< std::byte > const b = get( inpt );
124  advance( inpt );
125  return b;
126  }
127 
128  bool nonzero = false;
129  uint8_t offset = 1;
130 
131  cobs_decoder() = default;
132 
134  : nonzero( b == std::byte{ 255 } )
135  , offset( static_cast< uint8_t >( b ) )
136  {
137  }
138 };
139 
143 inline std::tuple< bool, view< std::byte* > >
145 {
146 
147  std::byte* target_current = target.begin();
148  cobs_decoder dec( source.front() );
149 
150  for ( std::byte const b : tail( source ) ) {
151 
152  std::optional< std::byte > val = dec.iter( b );
153 
154  if ( !val.has_value() )
155  continue;
156  *target_current = *val;
157  target_current += 1;
158 
159  if ( target_current == target.end() )
160  return { false, target };
161  }
162  return { true, { target.begin(), target_current } };
163 }
164 
165 template < typename Iter >
166 class decode_cobs_iter;
167 
168 } // namespace emlabcpp
169 
170 template < typename Iter >
171 struct std::iterator_traits< emlabcpp::decode_cobs_iter< Iter > >
172 {
174  using difference_type = std::ptrdiff_t;
175  using pointer = value_type*;
176  using const_pointer = value_type const*;
178  using iterator_category = std::input_iterator_tag;
179 };
180 
181 namespace emlabcpp
182 {
183 
184 template < typename Iter >
185 class decode_cobs_iter : public generic_iterator< decode_cobs_iter< Iter > >
186 {
187 public:
188  decode_cobs_iter( Iter iter )
189  : iter_( iter )
190  {
191  }
192 
194  {
195  // note: we do assume that iterator skips places without value
196  // NOLINTNEXLINE
197  return *dec_.get( *iter_ );
198  }
199 
201  {
202  dec_.advance( *iter_ );
203  ++iter_;
204  if ( dec_.non_value_byte() ) {
205  dec_.advance( *iter_ );
206  ++iter_;
207  }
208  return *this;
209  }
210 
212  {
213  decode_cobs_iter res{ *this };
214  ( *this )++;
215  return res;
216  }
217 
218  bool operator==( decode_cobs_iter const& other ) const
219  {
220  return iter_ == other.iter_;
221  }
222 
223 private:
224  cobs_decoder dec_;
225  Iter iter_;
226 };
227 
228 template < typename Iter >
230 {
231  return {
232  ++decode_cobs_iter< Iter >{ data.begin() },
234 }
235 
236 } // namespace emlabcpp
TODO: make this no inline.
Definition: cobs.h:35
cobs_encoder(view< std::byte * > target)
Definition: cobs.h:37
bool insert(std::byte b)
Definition: cobs.h:42
view< std::byte * > commit() &&
Definition: cobs.h:67
Definition: cobs.h:186
decode_cobs_iter & operator++()
Definition: cobs.h:200
bool operator==(decode_cobs_iter const &other) const
Definition: cobs.h:218
decode_cobs_iter operator++(int)
Definition: cobs.h:211
std::byte operator*() const
Definition: cobs.h:193
decode_cobs_iter(Iter iter)
Definition: cobs.h:188
constexpr EndIterator end() const
Past the end iterator.
Definition: view.h:110
constexpr Iterator begin() const
Start of the dataset iterator.
Definition: view.h:104
constexpr value_type const & front() const
Returns first value of the range.
Definition: view.h:147
hdr_state next(hdr_state cs) noexcept
Definition: page.h:43
MIT License.
Definition: impl.h:31
view< decode_cobs_iter< Iter >, decode_cobs_iter< Iter > > cobs_decode_view(view< Iter > data)
Definition: cobs.h:229
constexpr pointer data() noexcept
Returns pointer to first item of the storage.
Definition: static_storage.h:108
constexpr view< Iterator > tail(Container &&cont, int const step=1)
Returns range over Container, which skips first item of container.
Definition: algorithm.h:94
std::tuple< bool, view< std::byte * > > encode_cobs(view< std::byte const * > source, view< std::byte * > target)
Encodes data from source range into target buffer with Consistent Overhead Byte Stuffing (COBS) encod...
Definition: cobs.h:84
std::tuple< bool, view< std::byte * > > decode_cobs(view< std::byte const * > source, view< std::byte * > target)
Decodes data from source range into target buffer with Consistent Overhead Byte Stuffing (COBS) encod...
Definition: cobs.h:144
T res
Definition: algorithm.h:505
constexpr auto find(Container &&cont, T const &item)
Finds first item in container 'cont' that is equal to 'item', returns iterator for container,...
Definition: algorithm.h:140
physical_quantity< 0, 0, 0, 0, 0, 0, 0, 0, 1 > byte
Definition: physical_quantity.h:118
generic_iterator simplifies custom iterator implementation using CRTP.
Definition: iterator.h:62
Definition: cobs.h:94
void advance(std::byte inpt)
Definition: cobs.h:111
std::optional< std::byte > get(std::byte inpt) const
Definition: cobs.h:95
std::optional< std::byte > iter(std::byte inpt)
Definition: cobs.h:121
cobs_decoder(std::byte b)
Definition: cobs.h:133
uint8_t offset
Definition: cobs.h:129
bool nonzero
Definition: cobs.h:128
bool non_value_byte()
Definition: cobs.h:106
physical_quantity represents all physical units defined using the International System of Units and m...
Definition: physical_quantity.h:56
std::input_iterator_tag iterator_category
Definition: cobs.h:178
value_type const * const_pointer
Definition: cobs.h:176
std::ptrdiff_t difference_type
Definition: cobs.h:174