DUDS
Distributed Update of Data from Something
ConversationVector.hpp
Go to the documentation of this file.
1 /*
2  * This file is part of the DUDS project. It is subject to the BSD-style
3  * license terms in the LICENSE file found in the top-level directory of this
4  * distribution and at https://github.com/jjackowski/duds/blob/master/LICENSE.
5  * No part of DUDS, including this file, may be copied, modified, propagated,
6  * or distributed except according to the terms contained in the LICENSE file.
7  *
8  * Copyright (C) 2017 Jeff Jackowski
9  */
10 #ifndef CONVERSATIONVECTOR_HPP
11 #define CONVERSATIONVECTOR_HPP
12 
13 #include <type_traits>
14 #include <vector>
16 
17 namespace duds { namespace hardware { namespace interface {
18 
23 
29 
37 
68  std::vector<char> data;
69 public:
73  struct Input { };
77  struct Output { };
85  struct FixedLength { };
94  struct VaribleLength { };
98  ConversationVector(const ConversationVector &) = default;
102  ConversationVector(Input) : ConversationPart(MpfInput | MpfExtract, 0) { };
112  input ? MpfInput | MpfExtract : Flags::Zero(), 0
113  ) { };
117  ConversationVector(const std::vector<char> &v) :
118  ConversationPart(0), data(v) { }
122  ConversationVector(std::vector<char> &&v) :
123  ConversationPart(0), data(std::move(v)) { }
124  //ConversationVector(char * array, int len, bool input) :
125  // ConversationPart(input), data(v) { }
130  ConversationVector(std::size_t length, FixedLength) :
132  MpfInput | MpfExtract, 0
133  ), data(length + val16) { }
139  ConversationVector(std::size_t length, VaribleLength) :
141  MpfInput | MpfExtract | MpfVarlen, sizeof(std::size_t)
142  ), data(length + val16) { }
149  ConversationVector(std::size_t length, bool varlen = false) :
151  MpfInput | MpfExtract | (varlen ? MpfVarlen : Flags::Zero()),
152  varlen ? sizeof(std::size_t) : 0
153  ), data(length + val16) { }
159  ConversationVector(std::size_t length, Output) :
160  ConversationPart(Flags::Zero(), 0) {
161  data.reserve(length);
162  };
166  std::vector<char>::const_iterator begin() const {
167  return data.begin();
168  }
172  std::vector<char>::const_iterator end() const {
173  return data.end();
174  }
180  void add(char i);
187  template <typename Int>
188  void addLe(Int i) {
189  static_assert(std::is_integral<Int>::value,
190  "Only integer values can be added by this function.");
191  if (input()) {
192  throw ConversationBadAdd();
193  }
194  for (std::size_t loop = sizeof(Int); loop; --loop) {
195  data.push_back((char)(i & 0xFF));
196  i >>= 8;
197  }
198  }
205  template <typename Int>
206  void addBe(Int i) {
207  static_assert(std::is_integral<Int>::value,
208  "Only integer values can be added by this function.");
209  if (input()) {
210  throw ConversationBadAdd();
211  }
212  for (std::size_t loop = sizeof(Int); loop; --loop) {
213  data.push_back((char)(i >> (8 * (sizeof(Int) - 1))));
214  i <<= 8;
215  }
216  }
223  void addLe(std::int8_t i) {
224  add((char)i);
225  }
232  void addBe(std::int8_t i) {
233  add((char)i);
234  }
242  template <typename Int>
243  void add(Int i) {
244  if (bigEndian()) {
245  addBe(i);
246  } else {
247  addLe(i);
248  }
249  }
255  void add(const std::string &str);
262  void add(std::int8_t *a, std::size_t l);
269  template <std::size_t N>
270  void add(std::int8_t (&a)[N]) {
271  add(a, N);
272  }
281  template <typename Int>
282  void addLe(const Int *a, std::size_t count) {
283  static_assert(std::is_integral<Int>::value,
284  "Only integer values can be added by this function.");
285  if (input()) {
286  throw ConversationBadAdd();
287  }
288  data.reserve(data.size() + sizeof(Int) * count);
289  for (; count; --count) {
290  Int i = *(a++);
291  for (std::size_t loop = sizeof(Int); loop; --loop) {
292  data.push_back((char)(i & 0xFF));
293  i >>= 8;
294  }
295  }
296  }
305  template <typename Int, std::size_t N>
306  void addLe(const Int (&a)[N]) {
307  addLe(a, N);
308  }
317  template <typename Int>
318  void addBe(const Int *a, std::size_t count) {
319  static_assert(std::is_integral<Int>::value,
320  "Only integer values can be added by this function.");
321  if (input()) {
322  throw ConversationBadAdd();
323  }
324  data.reserve(data.size() + sizeof(Int) * count);
325  for (; count; --count) {
326  Int i = *(a++);
327  for (std::size_t loop = sizeof(Int); loop; --loop) {
328  data.push_back((char)(i >> (8 * (sizeof(Int) - 1))));
329  i <<= 8;
330  }
331  }
332  }
341  template <typename Int, std::size_t N>
342  void addBe(const Int (&a)[N]) {
343  addBe(a, N);
344  }
353  template <typename Int>
354  void add(const Int *a, std::size_t count) {
355  if (bigEndian()) {
356  addBe(a, count);
357  } else {
358  addLe(a, count);
359  }
360  }
369  template <typename Int, std::size_t N>
370  void add(const Int (&a)[N]) {
371  if (bigEndian()) {
372  addBe(a, N);
373  } else {
374  addLe(a, N);
375  }
376  }
390  void setStartOffset(std::int16_t offset);
400  void setLength(std::size_t len);
405  void reserve(std::size_t len);
409  struct BigEndian { };
413  struct LittleEndian { };
417  struct Reserve {
418  int len;
423  Reserve(int l) : len(l) { }
424  };
425  virtual char *start() const;
426  virtual std::size_t length() const;
427 };
428 
439 template <typename Int>
441  cv.add(i);
442  return cv;
443 }
444 
456 template <typename Int, std::size_t N>
458  cv.add(a, N);
459  return cv;
460 }
461 
470  ConversationVector &cv,
471  const ConversationVector::Reserve &cvr
472 ) {
473  cv.reserve(cvr.len);
474  return cv;
475 }
476 
485  ConversationVector &cv,
487 ) {
488  cv.bigEndian(true);
489  return cv;
490 }
491 
500  ConversationVector &cv,
502 ) {
503  cv.bigEndian(false);
504  return cv;
505 }
506 
516  ConversationVector &cv,
517  const std::string &str
518 ) {
519  cv.add(str);
520  return cv;
521 }
522 
523 } } }
524 
525 #endif // #ifndef CONVERSATIONVECTOR_HPP
Used as a parameter to constructors to specify that communication will not change the length of the c...
ConversationVector(std::size_t length, Output)
Construct for output and reserve the given length within the internal vector.
ConversationVector(const std::vector< char > &v)
Construct for output and copy the given vector into this object.
void add(char i)
Adds a byte to an output part.
ConversationVector(std::size_t length, FixedLength)
Construct for fixed-length input and allocate space for the input.
bool bigEndian() const
True if this part is flagged as having data in big-endian form.
ConversationVector(std::vector< char > &&v)
Construct for output and move the given vector into this object.
Use with the insertion operator to specify big-endian data will follow.
STL namespace.
ConversationVector(std::size_t length, VaribleLength)
Construct for variable-length input and allocate space for the input.
move_impl move(unsigned int c, unsigned int r)
Display stream manipulator that moves the display cursor to the given location.
void addBe(const Int *a, std::size_t count)
Adds an array of integers to the end of an output part in big-endian form.
void addLe(const Int *a, std::size_t count)
Adds an array of integers to the end of an output part in little-endian form.
An attempt was made to change the starting offset of a ConversationVector to an invalid value...
void addLe(Int i)
Adds an integer in little-endian form to an output part.
Represents a section of a half-duplex conversation with a device.
void addLe(const Int(&a)[N])
Adds an array of integers to the end of an output part in little-endian form.
An attempt was made to add data to a conversation part flagged for input.
ConversationVector(bool input)
Construct for either output or fixed-length input.
Base class for conversation related errors.
Used as a parameter to constructors to specify an output conversation part.
An operation requiring a varible length conversation part was attempted on a part not flagged as havi...
Use with the insertion operator to specify little-endian data will follow.
std::vector< char >::const_iterator begin() const
Begining iterator to inspect the contained data.
std::vector< char >::const_iterator end() const
Ending iterator to inspect the contained data.
void addBe(Int i)
Adds an integer in big-endian form to an output part.
Reserve(int l)
Specify how many bytes to reserve.
void reserve(std::size_t len)
Reserves space in the internal vector.
void add(const Int *a, std::size_t count)
Adds an array of integers to the end of an output part.
ConversationVector & operator<<(ConversationVector &cv, const Int &i)
Insertion operator to add an integer to a ConversationVector object.
Used as a parameter to constructors to specify that communication may change the length of the part...
Use with the insertion operator to reserve space in the vector.
std::vector< char > data
The internal buffer.
ConversationVector(Input)
Construct for fixed-length input without allocating space for the input.
void addBe(const Int(&a)[N])
Adds an array of integers to the end of an output part in big-endian form.
void add(std::int8_t(&a)[N])
Adds an array to the end an output part.
ConversationVector(std::size_t length, bool varlen=false)
Construct for fixed or variable-length input and allocate space for the input.
Used as a parameter to constructors to specify an input conversation part.
void addBe(std::int8_t i)
Adds a byte to an output part.
void add(const Int(&a)[N])
Adds an array of integers to the end of an output part.
void addLe(std::int8_t i)
Adds a byte to an output part.
void add(Int i)
Adds an integer to the end an output part.
Holds a conversation part inside a vector.