DUDS
Distributed Update of Data from Something
ConversationExtractor.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  */
16 #include <duds/general/Errors.hpp>
17 
18 namespace duds { namespace hardware { namespace interface {
19 
25 
32 
53  Conversation::PartVector::const_iterator piter;
57  const Conversation *c;
61  const char *pos;
65  std::size_t remain;
70  void set();
71 public:
77  ConversationExtractor() : c(nullptr), pos(nullptr), remain(0) { }
82  ConversationExtractor(const Conversation &con) : c(&con) {
83  set();
84  };
89  c(nullptr), pos(cp.start()), remain(cp.length()) { }
101  void reset() {
102  set();
103  };
114  void reset(const Conversation &con) {
115  c = &con;
116  set();
117  };
121  void reset(const ConversationPart &cp) {
122  c = nullptr;
123  pos = cp.start();
124  remain = cp.length();
125  }
130  bool end() const {
131  return !pos;
132  }
139  std::size_t remaining() const {
140  return remain;
141  }
156  void advance(std::size_t bytes);
164  void nextPart();
178  template <typename Int>
179  void readLe(Int &i) {
180  static_assert(std::is_integral<Int>::value,
181  "Only integer values can be read by this function.");
182  if (remain < sizeof(Int)) {
184  }
185  const char *p = pos;
186  for (std::size_t loop = sizeof(Int); loop; --loop, ++p) {
187  // use unsigned type for shift to LSb; signed gives different result
188  i = (((typename std::make_unsigned<Int>::type)i >> 8) |
189  (((Int)*p) << (8 * (sizeof(Int) - 1)))
190  );
191  }
192  advance(sizeof(Int));
193  }
207  template <typename Int>
208  void readBe(Int &i) {
209  static_assert(std::is_integral<Int>::value,
210  "Only integer values can be read by this function.");
211  if (remain < sizeof(Int)) {
213  }
214  const char *p = pos;
215  for (std::size_t loop = sizeof(Int); loop; --loop, ++p) {
216  i = (i << 8) | *p;
217  }
218  advance(sizeof(Int));
219  }
233  template <typename Int>
234  void read(Int &i) {
235  // if at end of all parts, the iterator is c->cend() and pos is null
236  if (!pos) {
238  }
239  if ((*piter)->bigEndian()) {
240  readBe(i);
241  } else {
242  readLe(i);
243  }
244  }
259  template <typename Int>
260  void readLe(Int *a, std::size_t count) {
261  static_assert(std::is_integral<Int>::value,
262  "Only integer values can be read by this function.");
263  int len = (int)sizeof(Int) * count;
264  if (remain < len) {
266  }
267  const char *p = pos;
268  for (; count; --count, ++a) {
269  for (std::size_t loop = sizeof(Int); loop; --loop, ++p) {
270  // use unsigned type for shift to LSb
271  *a = ((((typename std::make_unsigned<Int>::type)*a) >> 8) |
272  (((Int)*p) << (8 * (sizeof(Int) - 1)))
273  );
274  }
275  }
276  advance(len);
277  }
292  template <typename Int>
293  void readBe(Int *a, std::size_t count) {
294  static_assert(std::is_integral<Int>::value,
295  "Only integer values can be read by this function.");
296  int len = (int)sizeof(Int) * count;
297  if (remain < len) {
299  }
300  const char *p = pos;
301  for (; count; --count, ++a) {
302  for (std::size_t loop = sizeof(Int); loop; --loop, ++p) {
303  *a = (*a << 8) | *p;
304  }
305  }
306  advance(len);
307  }
322  template <typename Int, std::size_t N>
323  void readLe(Int (&a)[N]) {
324  readLe(a, N);
325  }
340  template <typename Int, std::size_t N>
341  void readBe(Int (&a)[N]) {
342  readBe(a, N);
343  }
358  template <typename Int>
359  void read(Int *a, std::size_t count) {
360  // if at end of all parts, the iterator is c->cend() and pos is null
361  if (!pos) {
363  }
364  if ((*piter)->bigEndian()) {
365  readBe(a, count);
366  } else {
367  readLe(a, count);
368  }
369  }
384  template <typename Int, std::size_t N>
385  void read(Int (&a)[N]) {
386  // if at end of all parts, the iterator is c->cend() and pos is null
387  if (!pos) {
389  }
390  if ((*piter)->bigEndian()) {
391  readBe(a, N);
392  } else {
393  readLe(a, N);
394  }
395  }
408  void read(char *dest, std::size_t len);
424  template <class Cont, typename Iter>
425  void read(Cont &cont, Iter &start, std::size_t len) {
426  if (remain < len) {
428  }
429  cont.insert(start, pos, pos + len);
430  advance(len);
431  }
432 };
433 
449 template <typename Int>
451  ce.read(i);
452  return ce;
453 }
454 
471 template <typename Int, std::size_t N>
473  ce.read(a, N);
474  return ce;
475 }
476 
477 } } }
An attempt was made to extract data past the end of a conversation or a conversation part...
ConversationExtractor(const ConversationPart &cp)
Must use functions that specifiy either big or little endian.
std::size_t remain
The remaining number of bytes to read in the part referenced by piter.
A ConversationExtractor was asked to operate on a Conversation, but one is not set.
void reset()
Prepares the object to extract another time from the same Conversation object used previously...
const char * pos
Pointer to the next byte to read.
Conversation::PartVector::const_iterator piter
Iterator to the current part being read.
void readLe(Int(&a)[N])
Reads an array of integers in little-endian form.
void readBe(Int &i)
Reads an integer in big-endian form.
std::size_t remaining() const
Returns the number of bytes remaining in the current conversation part.
const Conversation * c
The Conversation object with the parts to read.
void reset(const Conversation &con)
Prepares the object to extract from the given Conversation.
Represents a section of a half-duplex conversation with a device.
void readLe(Int &i)
Reads an integer in little-endian form.
void reset(const ConversationPart &cp)
Must use functions that specify either big or little endian.
ConversationExtractor(const Conversation &con)
Constructs to extract from the given Conversation.
void read(Cont &cont, Iter &start, std::size_t len)
Reads by inserting bytes into a container.
Base class for conversation related errors.
bool end() const
Returns true when all the extractible conversation data has been extracted.
ConversationExtractor & operator>>(ConversationExtractor &ce, Int &i)
Extraction operator to read an integer from a Conversation through a ConversationExtractor object...
void readLe(Int *a, std::size_t count)
Reads an array of integers in little-endian form.
void read(Int(&a)[N])
Reads an array of integers in the endianess flagged in the conversation part.
void read(Int &i)
Reads an integer in the endianess flagged in the conversation part.
virtual std::size_t length() const =0
Returns the length of the buffer following the start pointer.
virtual char * start() const =0
Returns a pointer to the begining of the conversation part&#39;s buffer.
Header for Conversarion; includes ConversationVector.hpp and ConversationExternal.hpp.
void readBe(Int(&a)[N])
Reads an array of integers in big-endian form.
void readBe(Int *a, std::size_t count)
Reads an array of integers in big-endian form.
ConversationExtractor()
Constructs with nothing to extract.
Extracts data from a Conversation without modifying the Conversation or copying from it...
General errors.
#define DUDS_THROW_EXCEPTION(x)
Works like BOOST_THROW_EXCEPTION, but includes a stack trace if DUDS_ERRORS_VERBOSE is defined...
Definition: Errors.hpp:48
Represents a two-way conversation with a device.
void read(Int *a, std::size_t count)
Reads an array of integers in the endianess flagged in the conversation part.