ByteVector.hpp
Go to the documentation of this file.
1 #ifndef BYTE_VECTOR_HPP
2 #define BYTE_VECTOR_HPP
3 
4 #include <cstdint>
5 #include <limits>
6 #include <memory>
7 #include <type_traits>
8 #include <vector>
9 #include "Value.hpp"
10 
11 namespace msp {
12 
13 struct Packable;
14 
15 class ByteVector : public std::vector<uint8_t> {
16 public:
20  ByteVector() : offset(0) {}
21 
27  template <typename T1>
28  ByteVector(T1 arg1) : std::vector<uint8_t>(arg1), offset(0) {}
29 
37  template <typename T1, typename T2>
38  ByteVector(T1 arg1, T2 arg2) :
39  std::vector<uint8_t>(arg1, arg2),
40  offset(0) {}
41 
49  template <typename T, typename std::enable_if<std::is_integral<T>::value,
50  T>::type* = nullptr>
51  bool pack(const T& val) {
52  // little endian packing
53  for(size_t i(0); i < sizeof(val); ++i) {
54  this->push_back(val >> (i * 8) & 0xFF);
55  }
56  return true;
57  }
58 
67  template <typename T,
68  typename std::enable_if<std::is_floating_point<T>::value,
69  T>::type* = nullptr>
70  bool pack(const T& val) {
71  ByteVector b(sizeof(val));
72  reinterpret_cast<T&>(b.front()) = val;
73  return this->pack(b);
74  }
75 
89  template <typename encoding_T, typename T1, typename T2,
90  typename std::enable_if<std::is_arithmetic<T1>::value,
91  T1>::type* = nullptr,
92  typename std::enable_if<std::is_arithmetic<T2>::value,
93  T2>::type* = nullptr>
94  bool pack(const T1 val, const T2 scale, const T2 offset = 0) {
95  const T1 tmp = (val + offset) * scale;
96  if(tmp <= std::numeric_limits<encoding_T>::min())
97  return pack(std::numeric_limits<encoding_T>::min());
98  else if(tmp >= std::numeric_limits<encoding_T>::max())
99  return pack(std::numeric_limits<encoding_T>::max());
100  return pack(static_cast<encoding_T>(tmp));
101  }
102 
110  bool pack(const std::string& val,
111  size_t max_len = std::numeric_limits<size_t>::max()) {
112  size_t count = 0;
113  for(auto c : val) {
114  this->push_back(c);
115  if(++count == max_len) break;
116  }
117  // TODO: validate that this null termination is the right thing to do in
118  // all cases definitly correct in tested cases
119  this->push_back(0);
120  return true;
121  }
122 
130  bool pack(const ByteVector& data,
131  size_t max_len = std::numeric_limits<size_t>::max()) {
132  size_t count = 0;
133  for(auto c : data) {
134  this->push_back(c);
135  if(++count == max_len) break;
136  }
137  return true;
138  }
139 
146  template <typename T,
147  typename std::enable_if<std::is_base_of<Packable, T>::value,
148  T>::type* = nullptr>
149  bool pack(const T& val) {
150  return val.pack_into(*this);
151  }
152 
166  template <typename encoding_T, typename T1, typename T2,
167  typename std::enable_if<std::is_arithmetic<T1>::value,
168  T1>::type* = nullptr,
169  typename std::enable_if<std::is_arithmetic<T2>::value,
170  T2>::type* = nullptr>
171  bool pack(const Value<T1> val, const T2 scale, const T2 offset = 0) {
172  if(!val.set()) return false;
173  return pack<encoding_T>(val(), scale, offset);
174  }
175 
183  bool pack(const Value<ByteVector>& val,
184  size_t max_len = std::numeric_limits<size_t>::max()) {
185  if(!val.set()) return false;
186  return pack(val(), max_len);
187  }
188 
196  bool pack(const Value<std::string>& val,
197  size_t max_len = std::numeric_limits<size_t>::max()) {
198  if(!val.set()) return false;
199  return pack(val(), max_len);
200  }
201 
209  template <class T> bool pack(const Value<T>& val) {
210  if(!val.set()) return false;
211  return pack(val());
212  }
213 
222  template <typename T, typename std::enable_if<std::is_integral<T>::value,
223  T>::type* = nullptr>
224  bool unpack(T& val) const {
225  if(unpacking_remaining() < sizeof(val)) return false;
226  val = 0;
227  for(size_t i(0); i < sizeof(val); ++i) {
228  val |= (*this)[offset++] << (8 * i);
229  }
230  return true;
231  }
232 
238  bool unpack(bool& val) const {
239  if(unpacking_remaining() < 1) return false;
240  val = (*this)[offset++];
241  return true;
242  }
243 
253  template <typename T,
254  typename std::enable_if<std::is_floating_point<T>::value,
255  T>::type* = nullptr>
256  bool unpack(T& val) const {
257  if(unpacking_remaining() < sizeof(val)) return false;
258  val = reinterpret_cast<const T&>((*this)[offset]);
259  offset += sizeof(val);
260  return true;
261  }
262 
271  bool unpack(std::string& val,
272  size_t count = std::numeric_limits<size_t>::max()) const {
273  if(count == std::numeric_limits<size_t>::max())
274  count = unpacking_remaining();
275  if(count > unpacking_remaining()) return false;
276  bool rc = true;
277  val.clear();
278  int8_t tmp;
279  for(size_t i = 0; i < count; ++i) {
280  rc &= unpack(tmp);
281  val += tmp;
282  }
283  return rc;
284  }
285 
295  bool unpack(ByteVector& val,
296  size_t count = std::numeric_limits<size_t>::max()) const {
297  if(count == std::numeric_limits<size_t>::max())
298  count = unpacking_remaining();
299  if(!consume(count)) return false;
300  val.clear();
301  val.insert(
302  val.end(), unpacking_iterator(), unpacking_iterator() + count);
303  return true;
304  }
305 
319  template <typename encoding_T, typename T1, typename T2,
320  typename std::enable_if<std::is_arithmetic<T1>::value,
321  T1>::type* = nullptr,
322  typename std::enable_if<std::is_arithmetic<T2>::value,
323  T2>::type* = nullptr>
324  bool unpack(T1& val, T2 scale, T2 offset = 0) const {
325  bool rc = true;
326  encoding_T tmp = 0;
327  rc &= unpack(tmp);
328  val = static_cast<T1>(tmp) / scale;
329  val -= offset;
330  return rc;
331  }
332 
338  template <typename T,
339  typename std::enable_if<std::is_base_of<Packable, T>::value,
340  T>::type* = nullptr>
341  bool unpack(T& obj) const {
342  return obj.unpack_from(*this);
343  }
344 
353  template <class T> bool unpack(Value<T>& val) const {
354  return val.set() = unpack(val());
355  }
356 
367  size_t count = std::numeric_limits<size_t>::max()) const {
368  return val.set() = unpack(val(), count);
369  }
370 
381  size_t count = std::numeric_limits<size_t>::max()) const {
382  return val.set() = unpack(val(), count);
383  }
384 
398  template <typename encoding_T, typename T1, typename T2 = float,
399  typename std::enable_if<std::is_arithmetic<T1>::value,
400  T1>::type* = nullptr,
401  typename std::enable_if<std::is_arithmetic<T2>::value,
402  T2>::type* = nullptr>
403  bool unpack(Value<T1>& val, T2 scale = 1, T2 offset = 0) const {
404  return val.set() = unpack<encoding_T>(val(), scale, offset);
405  }
406 
412  std::size_t unpacking_offset() const { return offset; }
413 
419  return this->begin() + offset;
420  }
421 
426  std::vector<uint8_t>::const_iterator unpacking_iterator() const {
427  return this->begin() + offset;
428  }
429 
436  bool consume(std::size_t count) const {
437  if(count > unpacking_remaining()) {
438  return false;
439  }
440  offset += count;
441  return true;
442  }
443 
448  std::size_t unpacking_remaining() const { return this->size() - offset; }
449 
450 protected:
451  mutable std::size_t offset;
452 };
453 
458 struct Packable {
459  virtual ~Packable() {}
460  virtual bool pack_into(ByteVector& data) const = 0;
461  virtual bool unpack_from(const ByteVector& data) = 0;
462 };
463 
464 typedef std::shared_ptr<ByteVector> ByteVectorPtr;
465 typedef std::unique_ptr<ByteVector> ByteVectorUptr;
466 
467 } // namespace msp
468 
469 inline std::ostream& operator<<(std::ostream& s, const msp::ByteVector& val) {
470  s << std::hex;
471  for(const auto& v : val) {
472  s << uint32_t(v) << " ";
473  }
474  s << std::dec << std::endl;
475  return s;
476 }
477 
478 #endif
Definition of a pure virtual class used to indicate that a child class can pack itself into a ByteVec...
Definition: ByteVector.hpp:458
bool pack(const ByteVector &data, size_t max_len=std::numeric_limits< size_t >::max())
Packs another ByteVector into the ByteVector.
Definition: ByteVector.hpp:130
ByteVector(T1 arg1)
ByteVector constructor.
Definition: ByteVector.hpp:28
bool unpack(T &val) const
Extracts little endian integers from the ByteVector. Consumes a number of bytes matching sizeof(T)...
Definition: ByteVector.hpp:224
ByteVector()
ByteVector constructor.
Definition: ByteVector.hpp:20
bool pack(const std::string &val, size_t max_len=std::numeric_limits< size_t >::max())
Packs string data into the ByteVector.
Definition: ByteVector.hpp:110
bool unpack(T &obj) const
unpack Unpacks an an object which inherits from type Packable
Definition: ByteVector.hpp:341
bool unpack(Value< std::string > &val, size_t count=std::numeric_limits< size_t >::max()) const
Extracts data from the ByteVector and stores it in a Value<std::string>. Consumes all remaining data ...
Definition: ByteVector.hpp:366
bool pack(const Value< T > &val)
Packs the contents of a Value<T> into the ByteVector.
Definition: ByteVector.hpp:209
bool unpack(std::string &val, size_t count=std::numeric_limits< size_t >::max()) const
Extracts data from the ByteVector and stores it in a std::string. Consumes all remaining data unless ...
Definition: ByteVector.hpp:271
bool unpack(ByteVector &val, size_t count=std::numeric_limits< size_t >::max()) const
Extracts data from the ByteVector and stores it in a another ByteVector. Consumes all remaining data ...
Definition: ByteVector.hpp:295
bool pack(const Value< std::string > &val, size_t max_len=std::numeric_limits< size_t >::max())
Packs a Value<std::string> into the ByteVector.
Definition: ByteVector.hpp:196
ByteVector(T1 arg1, T2 arg2)
ByteVector constructor.
Definition: ByteVector.hpp:38
bool unpack(Value< T > &val) const
Unpacks Value types other than string and ByteVector specializations.
Definition: ByteVector.hpp:353
std::vector< uint8_t >::const_iterator unpacking_iterator() const
Gives an iterator to the next element ready for unpacking.
Definition: ByteVector.hpp:426
bool pack(const T &val)
Packs integer types into the ByteVector. Ensures little endian packing.
Definition: ByteVector.hpp:51
bool unpack(Value< T1 > &val, T2 scale=1, T2 offset=0) const
Unpacks scaled Value types (e.g. scaled int to floating point) as val = (packed_val/scale)-offset.
Definition: ByteVector.hpp:403
bool pack(const T1 val, const T2 scale, const T2 offset=0)
Packs scaled values (e.g. float to scaled int) as packed_val = (val+offset)*scale.
Definition: ByteVector.hpp:94
std::size_t offset
Definition: ByteVector.hpp:451
bool consume(std::size_t count) const
Manually consumes data, thus skipping the values.
Definition: ByteVector.hpp:436
std::unique_ptr< ByteVector > ByteVectorUptr
Definition: ByteVector.hpp:465
asio::buffers_iterator< asio::streambuf::const_buffers_type > iterator
Definition: Client.hpp:19
bool pack(const Value< T1 > val, const T2 scale, const T2 offset=0)
Packs scaled value types (e.g. value<float> to scaled int) as packed_val = (val+offset)*scale.
Definition: ByteVector.hpp:171
bool unpack(bool &val) const
unpack Extracts a boolen from a single byte
Definition: ByteVector.hpp:238
virtual ~Packable()
Definition: ByteVector.hpp:459
std::ostream & operator<<(std::ostream &s, const msp::ByteVector &val)
Definition: ByteVector.hpp:469
bool unpack(Value< ByteVector > &val, size_t count=std::numeric_limits< size_t >::max()) const
Extracts data from the ByteVector and stores it in a Value<ByteVector>. Consumes all remaining data u...
Definition: ByteVector.hpp:380
bool unpack(T1 &val, T2 scale, T2 offset=0) const
Unpacks scaled value types (e.g. scaled int to floating point) as val = (packed_val/scale)-offset.
Definition: ByteVector.hpp:324
bool set() const
Queries if the data has been set.
Definition: Value.hpp:53
std::vector< uint8_t >::iterator unpacking_iterator()
Gives an iterator to the next element ready for unpacking.
Definition: ByteVector.hpp:418
bool pack(const Value< ByteVector > &val, size_t max_len=std::numeric_limits< size_t >::max())
Packs a Value<ByteVector> into the ByteVector.
Definition: ByteVector.hpp:183
std::size_t unpacking_remaining() const
Returns the number of bytes still avialable for unpacking.
Definition: ByteVector.hpp:448
std::size_t unpacking_offset() const
Gives the number of bytes which have already been consumed by unpack operations.
Definition: ByteVector.hpp:412
std::shared_ptr< ByteVector > ByteVectorPtr
Definition: ByteVector.hpp:464


msp
Author(s): Christian Rauch
autogenerated on Tue Oct 6 2020 03:38:57