EmbeddedProto  2.0.0
EmbeddedProto is a C++ Protocol Buffer implementation specifically suitable for microcontrollers.
RepeatedField.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2020 Embedded AMS B.V. - All Rights Reserved
3  *
4  * This file is part of Embedded Proto.
5  *
6  * Embedded Proto is open source software: you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as published
8  * by the Free Software Foundation, version 3 of the license.
9  *
10  * Embedded Proto is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
17  *
18  * For commercial and closed source application please visit:
19  * <https://EmbeddedProto.com/license/>.
20  *
21  * Embedded AMS B.V.
22  * Info:
23  * info at EmbeddedProto dot com
24  *
25  * Postal address:
26  * Johan Huizingalaan 763a
27  * 1066 VH, Amsterdam
28  * the Netherlands
29  */
30 
31 #ifndef _REPEATED_FIELD_H_
32 #define _REPEATED_FIELD_H_
33 
34 #include "Fields.h"
35 #include "MessageInterface.h"
36 #include "MessageSizeCalculator.h"
37 #include "ReadBufferSection.h"
38 #include "FieldStringBytes.h"
39 #include "Errors.h"
40 
41 #include <cstdint>
42 #include <type_traits>
43 
44 
45 namespace EmbeddedProto
46 {
47 
49  template<class DATA_TYPE>
50  class RepeatedField : public Field
51  {
52  static_assert(std::is_base_of<::EmbeddedProto::Field, DATA_TYPE>::value, "A Field can only be used as template paramter.");
53 
55  static constexpr bool REPEATED_FIELD_IS_PACKED =
56  !(std::is_base_of<MessageInterface, DATA_TYPE>::value
57  || std::is_base_of<internal::BaseStringBytes, DATA_TYPE>::value);
58 
59  public:
60 
61  RepeatedField() = default;
62  virtual ~RepeatedField() = default;
63 
65  virtual uint32_t get_length() const = 0;
66 
68  virtual uint32_t get_max_length() const = 0;
69 
71  virtual uint32_t get_size() const = 0;
72 
74  virtual uint32_t get_max_size() const = 0;
75 
77 
81  virtual DATA_TYPE& get(uint32_t index) = 0;
82 
84 
88  virtual const DATA_TYPE& get_const(uint32_t index) const = 0;
89 
91 
95  DATA_TYPE& operator[](uint32_t index) { return this->get(index); }
96 
98 
102  const DATA_TYPE& operator[](uint32_t index) const { return this->get_const(index); }
103 
105 
109  virtual void set(uint32_t index, const DATA_TYPE& value) = 0;
110 
112 
117  virtual Error set_data(const DATA_TYPE* data, const uint32_t length) = 0;
118 
120 
124  virtual Error add(const DATA_TYPE& value) = 0;
125 
127  virtual void clear() = 0;
128 
130  {
131  // This function should not be called on a repeated field.
132  return Error::BUFFER_FULL;
133  };
134 
136  Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const final
137  {
138  Error return_value = Error::NO_ERRORS;
139 
140  if(REPEATED_FIELD_IS_PACKED)
141  {
142  const uint32_t size_x = this->serialized_size_packed(field_number);
143 
144  // Use the packed way of serialization for base fields.
145  if(size_x <= buffer.get_available_size())
146  {
147  if(0 < size_x)
148  {
149  uint32_t tag = WireFormatter::MakeTag(field_number,
151  return_value = WireFormatter::SerializeVarint(tag, buffer);
152  if(Error::NO_ERRORS == return_value)
153  {
154  return_value = WireFormatter::SerializeVarint(size_x, buffer);
155  if(Error::NO_ERRORS == return_value)
156  {
157  return_value = serialize_packed(buffer);
158  }
159  }
160  }
161  }
162  else
163  {
164  return_value = Error::BUFFER_FULL;
165  }
166  }
167  else
168  {
169  const uint32_t size_x = this->serialized_size_unpacked(field_number);
170  if(size_x <= buffer.get_available_size())
171  {
172  return_value = serialize_unpacked(field_number, buffer);
173  }
174  else
175  {
176  return_value = Error::BUFFER_FULL;
177  }
178  }
179 
180  return return_value;
181  }
182 
184 
190  {
191  Error return_value = Error::NO_ERRORS;
192  if(REPEATED_FIELD_IS_PACKED)
193  {
194  return_value = deserialize_packed(buffer);
195  }
196  else
197  {
198  return_value = deserialize_unpacked(buffer);
199  }
200  return return_value;
201  }
202 
204 
208  uint32_t serialized_size_packed(int32_t field_number) const
209  {
211  serialize_packed(calcBuffer);
212  return calcBuffer.get_size();
213  }
214 
216 
219  uint32_t serialized_size_unpacked(int32_t field_number) const
220  {
222  serialize_unpacked(field_number, calcBuffer);
223  return calcBuffer.get_size();
224  }
225 
226  private:
227 
228  Error serialize_packed(WriteBufferInterface& buffer) const
229  {
230  Error return_value = Error::NO_ERRORS;
231  for(uint32_t i = 0; (i < this->get_length()) && (Error::NO_ERRORS == return_value); ++i)
232  {
233  return_value = this->get_const(i).serialize(buffer);
234  }
235  return return_value;
236  }
237 
238  Error serialize_unpacked(uint32_t field_number, WriteBufferInterface& buffer) const
239  {
240  Error return_value = Error::NO_ERRORS;
241  for(uint32_t i = 0; (i < this->get_length()) && (Error::NO_ERRORS == return_value); ++i)
242  {
243  const uint32_t size_x = this->get_const(i).serialized_size();
244  uint32_t tag = WireFormatter::MakeTag(field_number,
246  return_value = WireFormatter::SerializeVarint(tag, buffer);
247  if(Error::NO_ERRORS == return_value)
248  {
249  return_value = WireFormatter::SerializeVarint(size_x, buffer);
250  if((Error::NO_ERRORS == return_value) && (0 < size_x))
251  {
252  return_value = this->get_const(i).serialize(buffer);
253  }
254  }
255  }
256  return return_value;
257  }
258 
259  Error deserialize_packed(ReadBufferInterface& buffer)
260  {
261  uint32_t size;
262  Error return_value = WireFormatter::DeserializeVarint(buffer, size);
263  ReadBufferSection bufferSection(buffer, size);
264  DATA_TYPE x;
265 
266  return_value = x.deserialize(bufferSection);
267  while(Error::NO_ERRORS == return_value)
268  {
269  return_value = this->add(x);
270  if(Error::NO_ERRORS == return_value)
271  {
272  return_value = x.deserialize(bufferSection);
273  }
274  }
275 
276  // We expect the buffersection to be empty, in that case everything is fine..
277  if(Error::END_OF_BUFFER == return_value)
278  {
279  return_value = Error::NO_ERRORS;
280  }
281 
282  return return_value;
283  }
284 
285  Error deserialize_unpacked(ReadBufferInterface& buffer)
286  {
287  Error return_value = Error::NO_ERRORS;
288 
289  // For repeated messages, strings or bytes
290  // First allocate an element in the array.
291  const uint32_t index = this->get_length();
292  if(this->get_max_length() > index)
293  {
294  // For messages read the size here, with strings and byte arrays this is include in
295  // deserialize.
296  if(std::is_base_of<MessageInterface, DATA_TYPE>::value)
297  {
298  uint32_t size;
299  return_value = WireFormatter::DeserializeVarint(buffer, size);
300  if(Error::NO_ERRORS == return_value)
301  {
302  ReadBufferSection bufferSection(buffer, size);
303  return_value = this->get(index).deserialize(bufferSection);
304  }
305  }
306  else
307  {
308  return_value = this->get(index).deserialize(buffer);
309  }
310  }
311  else
312  {
313  return_value = Error::ARRAY_FULL;
314  }
315 
316  return return_value;
317  }
318 
319  };
320 
321 
322 } // End of namespace EmbeddedProto
323 
324 #endif // End of _REPEATED_FIELD_H_
MessageSizeCalculator.h
EmbeddedProto::Field
Definition: Fields.h:45
Fields.h
MessageInterface.h
Errors.h
EmbeddedProto::RepeatedField::set_data
virtual Error set_data(const DATA_TYPE *data, const uint32_t length)=0
Given a different array of known length copy that data into this object.
EmbeddedProto::MessageSizeCalculator
This class is used in a message to calculate the current serialized size.
Definition: MessageSizeCalculator.h:50
EmbeddedProto::RepeatedField::serialize_with_id
Error serialize_with_id(uint32_t field_number, WriteBufferInterface &buffer) const final
Definition: RepeatedField.h:136
EmbeddedProto::RepeatedField::add
virtual Error add(const DATA_TYPE &value)=0
Append a value to the end of the array.
EmbeddedProto::ReadBufferInterface
The pure virtual definition of a message buffer to read from.
Definition: ReadBufferInterface.h:43
EmbeddedProto::RepeatedField
Class template that specifies the interface of an arry with the data type.
Definition: RepeatedField.h:50
EmbeddedProto::RepeatedField::get_length
virtual uint32_t get_length() const =0
Obtain the total number of DATA_TYPE items in the array.
EmbeddedProto::RepeatedField::get_size
virtual uint32_t get_size() const =0
Obtain the total number of bytes currently stored in the array.
EmbeddedProto::RepeatedField::get_max_size
virtual uint32_t get_max_size() const =0
Obtain the maximum number of bytes which can at most be stored in the array.
EmbeddedProto::WireFormatter::WireType::LENGTH_DELIMITED
@ LENGTH_DELIMITED
string, bytes, embedded messages, packed repeated fields
EmbeddedProto::RepeatedField::deserialize
Error deserialize(::EmbeddedProto::ReadBufferInterface &buffer) final
Function to deserialize this array.
Definition: RepeatedField.h:189
EmbeddedProto::WireFormatter::SerializeVarint
static Error SerializeVarint(UINT_TYPE value, WriteBufferInterface &buffer)
This function converts a given value unsigned integer to a varint formatted data buffer.
Definition: WireFormatter.h:505
EmbeddedProto::RepeatedField::get_const
virtual const DATA_TYPE & get_const(uint32_t index) const =0
Get a constant reference to the value at the given index.
EmbeddedProto::RepeatedField::~RepeatedField
virtual ~RepeatedField()=default
EmbeddedProto
Definition: Errors.h:34
EmbeddedProto::Error::NO_ERRORS
@ NO_ERRORS
No errors have occurred.
EmbeddedProto::RepeatedField::RepeatedField
RepeatedField()=default
EmbeddedProto::WriteBufferInterface
The pure virtual definition of a message buffer used for writing .
Definition: WriteBufferInterface.h:46
EmbeddedProto::Error
Error
This enumeration defines errors which can occur during serialization and deserialization.
Definition: Errors.h:38
EmbeddedProto::RepeatedField::clear
virtual void clear()=0
Remove all data in the array and set it to the default value.
EmbeddedProto::WireFormatter::DeserializeVarint
static Error DeserializeVarint(ReadBufferInterface &buffer, UINT_TYPE &value)
This function deserializes the following N bytes into a varint.
Definition: WireFormatter.h:530
ReadBufferSection.h
EmbeddedProto::Error::END_OF_BUFFER
@ END_OF_BUFFER
While trying to read from the buffer we ran out of bytes tor read.
EmbeddedProto::RepeatedField::get
virtual DATA_TYPE & get(uint32_t index)=0
Get a reference to the value at the given index.
EmbeddedProto::RepeatedField::serialized_size_unpacked
uint32_t serialized_size_unpacked(int32_t field_number) const
Calculate the size of this field when serialized.
Definition: RepeatedField.h:219
EmbeddedProto::RepeatedField::operator[]
DATA_TYPE & operator[](uint32_t index)
Get a reference to the value at the given index.
Definition: RepeatedField.h:95
FieldStringBytes.h
EmbeddedProto::Error::ARRAY_FULL
@ ARRAY_FULL
The array is full, it is not possible to push more items in it.
EmbeddedProto::RepeatedField::serialize
Error serialize(WriteBufferInterface &buffer) const
Definition: RepeatedField.h:129
EmbeddedProto::WireFormatter::MakeTag
static constexpr uint32_t MakeTag(const uint32_t field_number, const WireType type)
Create the tag of a field.
Definition: WireFormatter.h:129
EmbeddedProto::MessageSizeCalculator::get_size
uint32_t get_size() const override
Obtain the total number of bytes currently stored in the buffer.
Definition: MessageSizeCalculator.h:63
EmbeddedProto::RepeatedField::get_max_length
virtual uint32_t get_max_length() const =0
Obtain the maximum number of DATA_TYPE items which can at most be stored in the array.
EmbeddedProto::RepeatedField::serialized_size_packed
uint32_t serialized_size_packed(int32_t field_number) const
Calculate the size of this field when serialized.
Definition: RepeatedField.h:208
EmbeddedProto::RepeatedField::set
virtual void set(uint32_t index, const DATA_TYPE &value)=0
Set the value at the given index.
EmbeddedProto::RepeatedField::operator[]
const DATA_TYPE & operator[](uint32_t index) const
Get a reference to the value at the given index. But constant.
Definition: RepeatedField.h:102
EmbeddedProto::Error::BUFFER_FULL
@ BUFFER_FULL
The write buffer is full, unable to push more bytes in to it.