MIP SDK  0.0.1
MicroStrain Communications Library for embedded systems
mip.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cstring>
4 
5 #include <stdint.h>
6 #include <stddef.h>
7 
8 #include "mip_packet.h"
9 #include "mip_field.h"
10 #include "mip_parser.h"
11 #include "mip_offsets.h"
13 #include "mip_types.h"
14 
15 #include <assert.h>
16 
25 
32 namespace mip
33 {
34 
36 
37 template<class Field> struct MipFieldInfo;
38 
42 
46 class Field : public C::mip_field
47 {
48 public:
50  Field() { C::mip_field::_payload=nullptr; C::mip_field::_payload_length=0; C::mip_field::_field_descriptor=0x00; C::mip_field::_descriptor_set=0x00; C::mip_field::_remaining_length=0; }
52  Field(uint8_t descriptor_set, uint8_t field_descriptor, const uint8_t* payload, uint8_t payload_length) { C::mip_field_init(this, descriptor_set, field_descriptor, payload, payload_length); }
54  Field(const uint8_t* header, uint8_t total_length, uint8_t descriptor_set) { *this = C::mip_field_from_header_ptr(header, total_length, descriptor_set); }
56  Field(const C::mip_field& other) { std::memcpy(static_cast<C::mip_field*>(this), &other, sizeof(C::mip_field)); }
57 
59  uint8_t descriptorSet() const { return C::mip_field_descriptor_set(this); }
61  uint8_t fieldDescriptor() const { return C::mip_field_field_descriptor(this); }
63  uint8_t payloadLength() const { return C::mip_field_payload_length(this); }
65  const uint8_t* payload() const { return C::mip_field_payload(this); }
66 
67  template<class Field>
68  bool extract(Field& field) const { return mip::extract(field, payload(), payloadLength(), 0, true); }
69 
73  uint8_t payload(unsigned int index) const { return payload()[index]; }
74 
76  bool isValid() const { return C::mip_field_is_valid(this); }
77 
79  Field nextAfter() const { return C::mip_field_next_after(this); }
81  bool next() { return C::mip_field_next(this); }
82 
83 
86 
88  bool isData() const { return isDataDescriptorSet(descriptorSet()); }
89 
92 
95 
97  bool isReply() const { return isCommandSet() && isReplyFieldDescriptor(fieldDescriptor()) && payloadLength()==2; }
98 };
99 
100 
110 class Packet : public C::mip_packet
111 {
112  class FieldIterator;
113 
114 public:
116  Packet(uint8_t* buffer, size_t bufferSize, uint8_t descriptorSet) { C::mip_packet_create(this, buffer, bufferSize, descriptorSet); }
118  Packet(uint8_t* buffer, size_t length) { C::mip_packet_from_buffer(this, buffer, length); }
120  Packet(const C::mip_packet* other) { std::memcpy(static_cast<C::mip_packet*>(this), other, sizeof(*this)); }
122  Packet(const C::mip_packet& other) { std::memcpy(static_cast<C::mip_packet*>(this), &other, sizeof(*this)); }
123 
124  uint8_t descriptorSet() const { return C::mip_packet_descriptor_set(this); }
126  uint8_t payloadLength() const { return C::mip_packet_payload_length(this); }
127 
128  bool isData() const { return C::mip_packet_is_data(this); }
129  bool isCommand() const { return !C::mip_packet_is_data(this); }
130 
131  const uint8_t* pointer() const { return C::mip_packet_pointer(this); }
132  const uint8_t* payload() const { return C::mip_packet_payload(this); }
133 
134  uint16_t checksumValue() const { return C::mip_packet_checksum_value(this); }
135  uint16_t computeChecksum() const { return C::mip_packet_compute_checksum(this); }
136 
137  bool isSane() const { return C::mip_packet_is_sane(this); }
138  bool isValid() const { return C::mip_packet_is_valid(this); }
139  bool isEmpty() const { return C::mip_packet_is_empty(this); }
140 
143 
144  bool addField(uint8_t fieldDescriptor, const uint8_t* payload, size_t payloadLength) { return C::mip_packet_add_field(this, fieldDescriptor, payload, payloadLength); }
145  RemainingCount allocField(uint8_t fieldDescriptor, uint8_t payloadLength, uint8_t** payloadPtr_out) { return C::mip_packet_alloc_field(this, fieldDescriptor, payloadLength, payloadPtr_out); }
146  RemainingCount reallocLastField(uint8_t* payloadPtr, uint8_t newPayloadLength) { return C::mip_packet_realloc_last_field(this, payloadPtr, newPayloadLength); }
147  RemainingCount cancelLastField(uint8_t* payloadPtr) { return C::mip_packet_cancel_last_field(this, payloadPtr); }
148 
149  void finalize() { C::mip_packet_finalize(this); }
150 
151  void reset(uint8_t descSet) { C::mip_packet_reset(this, descSet); }
152  void reset() { reset(descriptorSet()); }
153 
156 
159  FieldIterator begin() const { return firstField(); }
160 
163 #if __cpp_range_based_for >= 201603
164  std::nullptr_t end() const { return nullptr; }
165 #else
166  FieldIterator end() const { return Field(); }
167 #endif
168 
169  template<class Field>
170  bool addField(const Field& field, uint8_t fieldDescriptor = Field::FIELD_DESCRIPTOR)
171  {
172  uint8_t* payload;
173  size_t available = allocField(fieldDescriptor, 0, &payload);
174  Serializer serializer(payload, available);
175  insert(serializer, field);
176  return reallocLastField(payload, serializer.length()) >= 0;
177  }
178 
179  template<class Field>
180  static Packet createFromField(uint8_t* buffer, size_t bufferSize, const Field& field, uint8_t fieldDescriptor=Field::FIELD_DESCRIPTOR)
181  {
182  Packet packet(buffer, bufferSize, Field::DESCRIPTOR_SET);
183  packet.addField<Field>(field, fieldDescriptor);
184  packet.finalize();
185  return packet;
186  }
187 
188 private:
191  class FieldIterator
192  {
193  public:
194  FieldIterator(const Field& first) : mField(first) {}
195  FieldIterator() {}
196 
197  bool operator==(const FieldIterator& other) const {
198  // Required to make invalid fields equivalent for range-based for loop
199  if( !mField.isValid() && !other.mField.isValid() )
200  return true;
201  return mField.descriptorSet() == other.mField.descriptorSet() && mField.fieldDescriptor() == other.mField.fieldDescriptor() && mField.payload() == other.mField.payload();
202  }
203  bool operator!=(const FieldIterator& other) const { return !(*this == other); }
204 
205  bool operator==(std::nullptr_t) const { return !mField.isValid(); }
206  bool operator!=(std::nullptr_t) const { return mField.isValid(); }
207 
208  const Field& operator*() const { return mField; }
209 
210  FieldIterator& operator++() { mField.next(); return *this; }
211  private:
212  Field mField;
213  };
214 
215 };
216 
217 
223 class Parser : public C::mip_parser
224 {
225 public:
227  Parser(uint8_t* buffer, size_t bufferSize, C::mip_packet_callback callback, void* callbackObject, Timeout timeout) { C::mip_parser_init(this, buffer, bufferSize, callback, callbackObject, timeout); }
229  Parser(uint8_t* buffer, size_t bufferSize, bool (*callback)(void*,const Packet*,Timestamp), void* callbackObject, Timeout timeout) { C::mip_parser_init(this, buffer, bufferSize, (C::mip_packet_callback)callback, callbackObject, timeout); }
230 
231  Parser(uint8_t* buffer, size_t bufferSize, Timeout timeout) { C::mip_parser_init(this, buffer, bufferSize, nullptr, nullptr, timeout); }
232 
233  template<class T, bool (T::*Callback)(const Packet&, Timestamp)>
234  void setCallback(T& object);
235 
237  void reset() { C::mip_parser_reset(this); }
238 
240  RemainingCount parse(const uint8_t* inputBuffer, size_t inputCount, Timestamp timestamp, unsigned int maxPackets) { return C::mip_parser_parse(this, inputBuffer, inputCount, timestamp, maxPackets); }
241 
243  Timeout timeout() const { return C::mip_parser_timeout(this); }
246 };
247 
248 
269 template<class T, bool (T::*Callback)(const Packet&, Timestamp)>
270 void Parser::setCallback(T& object)
271 {
272  C::mip_packet_callback callback = [](void* obj, const C::mip_packet* pkt, Timestamp timestamp)->bool
273  {
274  return (static_cast<T*>(obj)->*Callback)(Packet(pkt), timestamp);
275  };
276 
277  C::mip_parser_set_callback(this, callback, &object);
278 }
279 
305 template<class Function>
306 bool parseMipDataFromSource(C::mip_parser& parser, Function reader, size_t maxPackets)
307 {
308  uint8_t* ptr;
309  size_t maxCount = C::mip_parser_get_write_ptr(&parser, &ptr);
310 
311  size_t count;
312  Timestamp timestamp;
313  if( !reader(ptr, maxCount, &count, &timestamp) )
314  return false;
315 
316  assert(count <= maxCount);
317 
318  C::mip_parser_process_written(&parser, count, timestamp, maxPackets);
319 
320  return true;
321 }
322 
325 
326 } // namespace mip
C++ class representing a MIP field.
Definition: mip.hpp:47
uint8_t fieldDescriptor() const
Returns the field descriptor.
Definition: mip.hpp:61
bool isCommand() const
Determines if the field holds a command.
Definition: mip.hpp:91
Field nextAfter() const
Gets the next field after the specified field._.
Definition: mip.hpp:79
Field()
Construct an empty MIP field.
Definition: mip.hpp:50
const uint8_t * payload() const
Returns the payload pointer for the field data.
Definition: mip.hpp:65
Field(const uint8_t *header, uint8_t total_length, uint8_t descriptor_set)
Constructs a mip_field from a pointer to the heaader.
Definition: mip.hpp:54
bool isCommandSet() const
Determines if the field is from a command descriptor set (a command, reply, or response field).
Definition: mip.hpp:85
Field(const C::mip_field &other)
Creates a Field class from the mip_field C struct.
Definition: mip.hpp:56
uint8_t descriptorSet() const
Returns the descriptor set of the packet containing this field._.
Definition: mip.hpp:59
bool next()
Updates the mip_field to refer to the next field in a packet.
Definition: mip.hpp:81
bool isValid() const
Returns true if the field has a valid field descriptor.
Definition: mip.hpp:76
bool extract(Field &field) const
Definition: mip.hpp:68
uint8_t payload(unsigned int index) const
Index the payload at the given location.
Definition: mip.hpp:73
bool isData() const
Determines if the field contains a data field.
Definition: mip.hpp:88
uint8_t payloadLength() const
Returns the length of the payload.
Definition: mip.hpp:63
bool isReply() const
Determines if the field holds an ack/nack reply code.
Definition: mip.hpp:97
bool isResponse() const
Determines if the field holds command response data.
Definition: mip.hpp:94
Field(uint8_t descriptor_set, uint8_t field_descriptor, const uint8_t *payload, uint8_t payload_length)
Constructs a mip_field given the parameters.
Definition: mip.hpp:52
C++ class representing a MIP Packet.
Definition: mip.hpp:111
bool isSane() const
Definition: mip.hpp:137
uint8_t descriptorSet() const
Definition: mip.hpp:124
void reset()
Resets the packet using the same descriptor set.
Definition: mip.hpp:152
bool isEmpty() const
Definition: mip.hpp:139
RemainingCount remainingSpace() const
Definition: mip.hpp:142
FieldIterator begin() const
Definition: mip.hpp:159
void reset(uint8_t descSet)
Definition: mip.hpp:151
RemainingCount reallocLastField(uint8_t *payloadPtr, uint8_t newPayloadLength)
Definition: mip.hpp:146
bool isCommand() const
Definition: mip.hpp:129
Field firstField() const
Returns the first field in the packet.
Definition: mip.hpp:155
PacketLength totalLength() const
Definition: mip.hpp:125
static Packet createFromField(uint8_t *buffer, size_t bufferSize, const Field &field, uint8_t fieldDescriptor=Field::FIELD_DESCRIPTOR)
Definition: mip.hpp:180
uint16_t computeChecksum() const
Definition: mip.hpp:135
const uint8_t * pointer() const
Definition: mip.hpp:131
const uint8_t * payload() const
Definition: mip.hpp:132
bool isData() const
Definition: mip.hpp:128
Packet(const C::mip_packet &other)
Constructs a C++ Packet class from the base C object.
Definition: mip.hpp:122
void finalize()
Definition: mip.hpp:149
bool addField(const Field &field, uint8_t fieldDescriptor=Field::FIELD_DESCRIPTOR)
Definition: mip.hpp:170
Packet(uint8_t *buffer, size_t length)
Initializes a MIP packet from an existing buffer.
Definition: mip.hpp:118
Packet(const C::mip_packet *other)
Constructs a C++ Packet class from the base C object.
Definition: mip.hpp:120
RemainingCount allocField(uint8_t fieldDescriptor, uint8_t payloadLength, uint8_t **payloadPtr_out)
Definition: mip.hpp:145
RemainingCount cancelLastField(uint8_t *payloadPtr)
Definition: mip.hpp:147
PacketLength bufferSize() const
Definition: mip.hpp:141
uint16_t checksumValue() const
Definition: mip.hpp:134
FieldIterator end() const
Definition: mip.hpp:166
bool addField(uint8_t fieldDescriptor, const uint8_t *payload, size_t payloadLength)
Definition: mip.hpp:144
Packet(uint8_t *buffer, size_t bufferSize, uint8_t descriptorSet)
Definition: mip.hpp:116
uint8_t payloadLength() const
Definition: mip.hpp:126
bool isValid() const
Definition: mip.hpp:138
C++ class representing a MIP parser.
Definition: mip.hpp:224
void reset()
Definition: mip.hpp:237
Parser(uint8_t *buffer, size_t bufferSize, C::mip_packet_callback callback, void *callbackObject, Timeout timeout)
Definition: mip.hpp:227
Parser(uint8_t *buffer, size_t bufferSize, Timeout timeout)
Definition: mip.hpp:231
Timeout timeout() const
Definition: mip.hpp:243
RemainingCount parse(const uint8_t *inputBuffer, size_t inputCount, Timestamp timestamp, unsigned int maxPackets)
Definition: mip.hpp:240
Parser(uint8_t *buffer, size_t bufferSize, bool(*callback)(void *, const Packet *, Timestamp), void *callbackObject, Timeout timeout)
Definition: mip.hpp:229
void setTimeout(Timeout timeout)
Definition: mip.hpp:245
Serialization class.
Definition: serialization.h:145
size_t length() const
Definition: serialization.h:151
bool mip_packet_is_empty(const mip_packet *packet)
bool mip_packet_is_valid(const mip_packet *packet)
void mip_packet_from_buffer(mip_packet *packet, uint8_t *buffer, size_t length)
uint8_t mip_packet_payload_length(const mip_packet *packet)
const uint8_t * mip_packet_pointer(const mip_packet *packet)
remaining_count mip_packet_remaining_space(const mip_packet *packet)
bool mip_packet_is_data(const mip_packet *packet)
uint8_t mip_packet_descriptor_set(const mip_packet *packet)
uint16_t mip_packet_checksum_value(const mip_packet *packet)
uint16_t mip_packet_compute_checksum(const mip_packet *packet)
packet_length mip_packet_total_length(const mip_packet *packet)
packet_length mip_packet_buffer_size(const mip_packet *packet)
const uint8_t * mip_packet_payload(const mip_packet *packet)
bool mip_packet_is_sane(const mip_packet *packet)
bool mip_field_is_valid(const mip_field *field)
const uint8_t * mip_field_payload(const mip_field *field)
uint8_t mip_field_field_descriptor(const mip_field *field)
uint8_t mip_field_descriptor_set(const mip_field *field)
uint8_t mip_field_payload_length(const mip_field *field)
mip_field mip_field_first_from_packet(const mip_packet *packet)
mip_field mip_field_next_after(const mip_field *field)
mip_field mip_field_from_header_ptr(const uint8_t *header, uint8_t total_length, uint8_t descriptor_set)
bool mip_field_next(mip_field *field)
void mip_packet_reset(mip_packet *packet, uint8_t descriptor_set)
remaining_count mip_packet_alloc_field(mip_packet *packet, uint8_t field_descriptor, uint8_t payload_length, uint8_t **payload_ptr_out)
remaining_count mip_packet_cancel_last_field(mip_packet *packet, uint8_t *payload_ptr)
remaining_count mip_packet_realloc_last_field(mip_packet *packet, uint8_t *payload_ptr, uint8_t new_payload_length)
void mip_packet_create(mip_packet *packet, uint8_t *buffer, size_t buffer_size, uint8_t descriptor_set)
bool mip_packet_add_field(mip_packet *packet, uint8_t field_descriptor, const uint8_t *payload, uint8_t payload_length)
void mip_packet_finalize(mip_packet *packet)
@ DESCRIPTOR_SET
Definition: commands_3dm.hpp:32
bool parseMipDataFromSource(C::mip_parser &parser, Function reader, size_t maxPackets)
Read data from a source into the internal parsing buffer.
Definition: mip.hpp:306
void setCallback(T &object)
Initializes the MIP Parser.
Definition: mip.hpp:270
void mip_field_init(mip_field *field, uint8_t descriptor_set, uint8_t field_descriptor, const uint8_t *payload, uint8_t payload_length)
uint_least16_t packet_length
Type used for the length of a MIP packet.
Definition: mip_packet.h:32
void mip_parser_reset(mip_parser *parser)
void mip_parser_init(mip_parser *parser, uint8_t *buffer, size_t buffer_size, mip_packet_callback callback, void *callback_object, timestamp_type timeout)
void mip_parser_process_written(mip_parser *parser, size_t count, timestamp_type timestamp, unsigned int max_packets)
size_t mip_parser_get_write_ptr(mip_parser *parser, uint8_t **ptr_out)
bool(* mip_packet_callback)(void *user, const mip_packet *packet, timestamp_type timestamp)
Callback function which receives parsed MIP packets.
Definition: mip_parser.h:45
timeout_type mip_parser_timeout(const mip_parser *parser)
remaining_count mip_parser_parse(mip_parser *parser, const uint8_t *input_buffer, size_t input_count, timestamp_type timestamp, unsigned int max_packets)
void mip_parser_set_callback(mip_parser *parser, mip_packet_callback callback, void *callback_object)
void mip_parser_set_timeout(mip_parser *parser, timeout_type timeout)
A collection of C++ classes and functions covering the full mip api.
Definition: commands_3dm.c:11
void extract(Serializer &serializer, Bitfield< Derived > &bitfield)
Definition: descriptors.h:98
C::timestamp_type Timestamp
Definition: mip_types.h:43
bool isReplyFieldDescriptor(uint8_t fieldDescriptor)
Definition: descriptors.h:119
void insert(Serializer &serializer, const Bitfield< Derived > &bitfield)
Definition: descriptors.h:97
C::timeout_type Timeout
Definition: mip_types.h:44
bool isResponseFieldDescriptor(uint8_t fieldDescriptor)
Definition: descriptors.h:120
bool isCommandFieldDescriptor(uint8_t fieldDescriptor)
Definition: descriptors.h:118
bool isDataDescriptorSet(uint8_t descriptorSet)
Definition: descriptors.h:113
C::packet_length PacketLength
Definition: mip.hpp:35
C::remaining_count RemainingCount
Definition: mip_types.h:42
bool isCommandDescriptorSet(uint8_t descriptorSet)
Definition: descriptors.h:114
A structure representing a MIP field.
Definition: mip_field.h:53
Structure representing a MIP Packet.
Definition: mip_packet.h:44
MIP Parser state.
Definition: mip_parser.h:56
Definition: mip.hpp:37