EmbeddedProto  2.0.0
EmbeddedProto is a C++ Protocol Buffer implementation specifically suitable for microcontrollers.
FieldStringBytes.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 _FIELD_STRING_BYTES_H_
32 #define _FIELD_STRING_BYTES_H_
33 
34 #include "Fields.h"
35 #include "Errors.h"
36 
37 #include <cstdint>
38 #include <string.h>
39 #include <type_traits>
40 
41 
42 namespace EmbeddedProto
43 {
44 
45  namespace internal
46  {
47 
48  class BaseStringBytes : public Field {};
49 
50  template<uint32_t MAX_LENGTH, class DATA_TYPE>
52  {
53  static_assert(std::is_same<uint8_t, DATA_TYPE>::value || std::is_same<char, DATA_TYPE>::value,
54  "This class only supports unit8_t or chars.");
55 
56  public:
57 
59  : current_length_(0),
60  data_{0}
61  {
62 
63  }
64 
66  {
67  clear();
68  }
69 
71  uint32_t get_length() const { return current_length_; }
72 
74  uint32_t get_max_length() const { return MAX_LENGTH; }
75 
77  const DATA_TYPE* get_const() const { return data_; }
78 
80 
87  DATA_TYPE& get(uint32_t index)
88  {
89  uint32_t limited_index = std::min(index, MAX_LENGTH-1);
90  // Check if we need to update the number of elements in the array.
91  if(limited_index >= current_length_) {
92  current_length_ = limited_index + 1;
93  }
94  return data_[limited_index];
95  }
96 
98 
103  const DATA_TYPE& get_const(uint32_t index) const
104  {
105  uint32_t limited_index = std::min(index, MAX_LENGTH-1);
106  return data_[limited_index];
107  }
108 
110 
117  DATA_TYPE& operator[](uint32_t index) { return this->get(index); }
118 
120 
125  const DATA_TYPE& operator[](uint32_t index) const { return this->get_const(index); }
126 
127 
128  Error set(const DATA_TYPE* data, const uint32_t length)
129  {
130  Error return_value = Error::NO_ERRORS;
131  if(MAX_LENGTH >= length)
132  {
133  current_length_ = length;
134  memcpy(data_, data, length);
135  }
136  else
137  {
138  return_value = Error::ARRAY_FULL;
139  }
140  return return_value;
141  }
142 
143 
144  Error serialize_with_id(uint32_t field_number, WriteBufferInterface& buffer) const override
145  {
146  Error return_value = Error::NO_ERRORS;
147 
148  if(0 < current_length_)
149  {
150  if(current_length_ <= buffer.get_available_size())
151  {
152  uint32_t tag = WireFormatter::MakeTag(field_number,
154  return_value = WireFormatter::SerializeVarint(tag, buffer);
155  if(Error::NO_ERRORS == return_value)
156  {
157  return_value = WireFormatter::SerializeVarint(current_length_, buffer);
158  }
159  if(Error::NO_ERRORS == return_value)
160  {
161  return_value = serialize(buffer);
162  }
163  }
164  else
165  {
166  return_value = Error::BUFFER_FULL;
167  }
168  }
169 
170  return return_value;
171  }
172 
173  Error serialize(WriteBufferInterface& buffer) const override
174  {
175  Error return_value = Error::NO_ERRORS;
176  const void* void_pointer = static_cast<const void*>(&(data_[0]));
177  const uint8_t* byte_pointer = static_cast<const uint8_t*>(void_pointer);
178  if(!buffer.push(byte_pointer, current_length_))
179  {
180  return_value = Error::BUFFER_FULL;
181  }
182  return return_value;
183  }
184 
186  {
187  uint32_t availiable;
188  Error return_value = WireFormatter::DeserializeVarint(buffer, availiable);
189  if(Error::NO_ERRORS == return_value)
190  {
191  if(MAX_LENGTH >= availiable)
192  {
193  clear();
194 
195  uint8_t byte;
196  while((current_length_ < availiable) && buffer.pop(byte))
197  {
198  data_[current_length_] = static_cast<DATA_TYPE>(byte);
199  ++current_length_;
200  }
201 
202  if(current_length_ != availiable)
203  {
204  // If at the end we did not read the same number of characters something went wrong.
205  return_value = Error::END_OF_BUFFER;
206  }
207  }
208  else
209  {
210  return_value = Error::ARRAY_FULL;
211  }
212  }
213 
214  return return_value;
215  }
216 
218  void clear() override
219  {
220  memset(data_, 0, current_length_);
221  current_length_ = 0;
222  }
223 
224  protected:
225 
227  uint32_t current_length_;
228 
230  DATA_TYPE data_[MAX_LENGTH];
231 
232  }; // End of class FieldStringBytes
233 
234  } // End of namespace internal
235 
236  template<uint32_t MAX_LENGTH>
237  class FieldString : public internal::FieldStringBytes<MAX_LENGTH, char>
238  {
239  public:
240  FieldString() = default;
241  virtual ~FieldString() = default;
242 
243  void operator=(const char* const &&rhs)
244  {
245  const uint32_t rhs_MAX_LENGTH = strlen(rhs);
246  this->current_length_ = std::min(rhs_MAX_LENGTH, MAX_LENGTH);
247  strncpy(this->data_, rhs, this->current_length_);
248 
249  // Make sure the string is null terminated.
250  if(MAX_LENGTH > this->current_length_)
251  {
252  this->data_[this->current_length_] = 0;
253  }
254  }
255  };
256 
257  template<uint32_t MAX_LENGTH>
258  class FieldBytes : public internal::FieldStringBytes<MAX_LENGTH, uint8_t>
259  {
260  public:
261  FieldBytes() = default;
262  virtual ~FieldBytes() = default;
263  };
264 
265 
266 } // End of namespace EmbeddedProto
267 
268 #endif // End of _FIELD_STRING_BYTES_H_
EmbeddedProto::internal::FieldStringBytes::serialize
Error serialize(WriteBufferInterface &buffer) const override
Definition: FieldStringBytes.h:173
EmbeddedProto::Field
Definition: Fields.h:45
Fields.h
EmbeddedProto::internal::FieldStringBytes::current_length_
uint32_t current_length_
Number of item in the data array.
Definition: FieldStringBytes.h:227
Errors.h
EmbeddedProto::internal::FieldStringBytes::set
Error set(const DATA_TYPE *data, const uint32_t length)
Definition: FieldStringBytes.h:128
EmbeddedProto::ReadBufferInterface
The pure virtual definition of a message buffer to read from.
Definition: ReadBufferInterface.h:43
EmbeddedProto::internal::FieldStringBytes::get_const
const DATA_TYPE * get_const() const
Get a constant pointer to the first element in the array.
Definition: FieldStringBytes.h:77
EmbeddedProto::WireFormatter::WireType::LENGTH_DELIMITED
@ LENGTH_DELIMITED
string, bytes, embedded messages, packed repeated fields
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
Definition: Errors.h:34
EmbeddedProto::Error::NO_ERRORS
@ NO_ERRORS
No errors have occurred.
EmbeddedProto::internal::FieldStringBytes::FieldStringBytes
FieldStringBytes()
Definition: FieldStringBytes.h:58
EmbeddedProto::WriteBufferInterface::push
virtual bool push(const uint8_t byte)=0
Push a single byte into the buffer.
EmbeddedProto::FieldString::FieldString
FieldString()=default
EmbeddedProto::WriteBufferInterface
The pure virtual definition of a message buffer used for writing .
Definition: WriteBufferInterface.h:46
EmbeddedProto::WriteBufferInterface::get_available_size
virtual uint32_t get_available_size() const =0
Obtain the total number of bytes still available in the buffer.
EmbeddedProto::Error
Error
This enumeration defines errors which can occur during serialization and deserialization.
Definition: Errors.h:38
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
EmbeddedProto::internal::FieldStringBytes::clear
void clear() override
Reset the field to it's initial value.
Definition: FieldStringBytes.h:218
EmbeddedProto::internal::FieldStringBytes::get_length
uint32_t get_length() const
Obtain the number of characters in the string right now.
Definition: FieldStringBytes.h:71
EmbeddedProto::internal::FieldStringBytes::get
DATA_TYPE & get(uint32_t index)
Get a reference to the value at the given index.
Definition: FieldStringBytes.h:87
EmbeddedProto::Error::END_OF_BUFFER
@ END_OF_BUFFER
While trying to read from the buffer we ran out of bytes tor read.
EmbeddedProto::internal::FieldStringBytes::data_
DATA_TYPE data_[MAX_LENGTH]
The text.
Definition: FieldStringBytes.h:230
EmbeddedProto::ReadBufferInterface::pop
virtual bool pop(uint8_t &byte)=0
Obtain the value of the oldest byte in the buffer and remove it from the buffer.
EmbeddedProto::internal::FieldStringBytes
Definition: FieldStringBytes.h:51
EmbeddedProto::FieldString::operator=
void operator=(const char *const &&rhs)
Definition: FieldStringBytes.h:243
EmbeddedProto::FieldString
Definition: FieldStringBytes.h:237
EmbeddedProto::internal::FieldStringBytes::get_max_length
uint32_t get_max_length() const
Obtain the maximum number characters in the string.
Definition: FieldStringBytes.h:74
EmbeddedProto::FieldBytes::~FieldBytes
virtual ~FieldBytes()=default
EmbeddedProto::Error::ARRAY_FULL
@ ARRAY_FULL
The array is full, it is not possible to push more items in it.
EmbeddedProto::internal::FieldStringBytes::get_const
const DATA_TYPE & get_const(uint32_t index) const
Get a constant reference to the value at the given index.
Definition: FieldStringBytes.h:103
EmbeddedProto::FieldBytes
Definition: FieldStringBytes.h:258
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::FieldString::~FieldString
virtual ~FieldString()=default
EmbeddedProto::internal::FieldStringBytes::operator[]
const DATA_TYPE & operator[](uint32_t index) const
Get a constant reference to the value at the given index.
Definition: FieldStringBytes.h:125
EmbeddedProto::internal::FieldStringBytes::serialize_with_id
Error serialize_with_id(uint32_t field_number, WriteBufferInterface &buffer) const override
Definition: FieldStringBytes.h:144
EmbeddedProto::internal::FieldStringBytes::deserialize
Error deserialize(ReadBufferInterface &buffer) override
Definition: FieldStringBytes.h:185
EmbeddedProto::Error::BUFFER_FULL
@ BUFFER_FULL
The write buffer is full, unable to push more bytes in to it.
EmbeddedProto::internal::FieldStringBytes::~FieldStringBytes
virtual ~FieldStringBytes()
Definition: FieldStringBytes.h:65
EmbeddedProto::FieldBytes::FieldBytes
FieldBytes()=default
EmbeddedProto::internal::BaseStringBytes
Definition: FieldStringBytes.h:48
EmbeddedProto::internal::FieldStringBytes::operator[]
DATA_TYPE & operator[](uint32_t index)
Get a reference to the value at the given index.
Definition: FieldStringBytes.h:117