Uniot Core
0.8.1
Loading...
Searching...
No Matches
Bytes.h
Go to the documentation of this file.
1/*
2 * This is a part of the Uniot project.
3 * Copyright (C) 2016-2023 Uniot <contact@uniot.io>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#pragma once
20
21#include <Common.h>
22#include <Logger.h>
23#include <WString.h>
24#include <stdio.h>
25
26#include <functional>
27#include <type_traits>
28
38class Bytes {
39 public:
45 using Filler = std::function<size_t(uint8_t *buf, size_t size)>;
46
52 Bytes() : Bytes(nullptr, 0) {}
53
62 Bytes(const uint8_t *data, size_t size) {
63 _init();
64 if (data) {
65 _copy(data, size);
66 } else if (size) {
67 _reserve(size);
68 }
69 }
70
78 Bytes(const char *str) : Bytes((uint8_t *)str, strlen(str) + 1) // + 1 null terminator
79 {}
80
89 template <typename T>
90 Bytes(T value) : Bytes(((uint8_t *)&value), sizeof(T)) {
91 static_assert(std::is_integral<T>::value, "only integral types are allowed");
92 }
93
101 Bytes(const Bytes &value) {
102 _init();
103 *this = value;
104 }
105
113 Bytes(const String &value) {
114 _init();
115 *this = value;
116 }
117
123 virtual ~Bytes() {
124 _invalidate();
125 }
126
135 Bytes &operator=(const Bytes &rhs) {
136 if (this != &rhs) {
137 if (rhs.mBuffer) {
138 _copy(rhs.mBuffer, rhs.mSize);
139 } else {
140 _invalidate();
141 }
142 }
143 return *this;
144 }
145
154 Bytes &operator=(const String &rhs) {
155 if (rhs.length()) {
156 _copy((const uint8_t *)rhs.c_str(), rhs.length());
157 } else {
158 _invalidate();
159 }
160 return this->terminate();
161 }
162
163 // template <typename T>
164 // operator T() {
165 // return *((T *)mBuffer);
166 // }
167
178 static Bytes fromHexString(const String &hexStr) {
179 size_t len = hexStr.length();
180 if (len % 2 != 0) {
181 UNIOT_LOG_ERROR("invalid hex string length");
182 return Bytes();
183 }
184
185 Bytes bytes;
186 bytes._reserve(len / 2);
187 for (size_t i = 0; i < len; i += 2) {
188 char buf[3] = {hexStr.charAt(i), hexStr.charAt(i + 1), '\0'};
189 uint8_t b = strtol(buf, nullptr, 16);
190 bytes.mBuffer[i / 2] = b;
191 }
192 return bytes;
193 }
194
205 size_t fill(Filler filler) {
206 if (filler) {
207 return filler(mBuffer, mSize);
208 }
209 return 0;
210 }
211
221 Bytes &prune(size_t newSize) {
222 if (newSize < mSize) {
223 _reserve(newSize);
224 }
225 return *this;
226 }
227
235 const uint8_t *raw() const {
236 return mBuffer;
237 }
238
247 if (!mSize) {
248 _reserve(1);
249 return *this;
250 }
251
252 if (mBuffer[mSize - 1] != '\0') {
253 _reserve(mSize + 1);
254 mBuffer[mSize - 1] = '\0';
255 }
256 return *this;
257 }
258
266 const char *c_str() const {
267 return (const char *)mBuffer;
268 }
269
277 String toString() const {
278 return String(this->c_str());
279 }
280
288 String toHexString() const {
289 String result = "";
290 for (size_t i = 0; i < mSize; i++) {
291 char buf[3];
292 snprintf(buf, sizeof(buf), "%02X", mBuffer[i]);
293 result += buf;
294 }
295 return result;
296 }
297
303 size_t size() const {
304 return mSize;
305 }
306
312 void clean() {
313 _invalidate();
314 }
315
323 uint32_t checksum() const {
324 return CRC32(mBuffer, mSize);
325 }
326
327 private:
333 inline void _init(void) {
334 mBuffer = nullptr;
335 mSize = 0;
336 }
337
343 void _invalidate(void) {
344 if (mBuffer) {
345 free(mBuffer);
346 }
347 _init();
348 }
349
360 bool _reserve(size_t newSize) {
361 mBuffer = (uint8_t *)realloc(mBuffer, newSize);
362 if (mBuffer && (newSize > mSize)) {
363 memset(mBuffer + mSize, 0, newSize - mSize);
364 }
365 mSize = newSize;
366 return mBuffer;
367 }
368
378 Bytes &_copy(const uint8_t *data, size_t size) {
379 if (_reserve(size)) {
380 memcpy(mBuffer, data, size);
381 } else {
382 _invalidate();
383 }
384 return *this;
385 }
386
387 uint8_t *mBuffer;
388 size_t mSize;
389};
390
uint32_t checksum() const
Calculates a checksum of the byte array.
Definition Bytes.h:323
void clean()
Deallocates the internal buffer.
Definition Bytes.h:312
String toString() const
Converts the byte array to an Arduino String.
Definition Bytes.h:277
Bytes & terminate()
Ensures the byte array is null-terminated.
Definition Bytes.h:246
Bytes & operator=(const Bytes &rhs)
Assignment operator.
Definition Bytes.h:135
const uint8_t * raw() const
Gets a const pointer to the raw byte array.
Definition Bytes.h:235
Bytes(const String &value)
Constructor from Arduino String.
Definition Bytes.h:113
const char * c_str() const
Gets the byte array as a C string.
Definition Bytes.h:266
Bytes(const uint8_t *data, size_t size)
Constructor from raw byte array.
Definition Bytes.h:62
Bytes & prune(size_t newSize)
Reduces the size of the buffer.
Definition Bytes.h:221
Bytes(const Bytes &value)
Copy constructor.
Definition Bytes.h:101
Bytes & operator=(const String &rhs)
Assignment from Arduino String.
Definition Bytes.h:154
size_t fill(Filler filler)
Fills the buffer using a provided filler function.
Definition Bytes.h:205
String toHexString() const
Converts the byte array to a hexadecimal string.
Definition Bytes.h:288
std::function< size_t(uint8_t *buf, size_t size)> Filler
Function type for filling byte arrays.
Definition Bytes.h:45
virtual ~Bytes()
Destructor.
Definition Bytes.h:123
static Bytes fromHexString(const String &hexStr)
Creates a Bytes object from a hexadecimal string.
Definition Bytes.h:178
size_t size() const
Gets the size of the byte array.
Definition Bytes.h:303
Bytes()
Default constructor.
Definition Bytes.h:52
Bytes(T value)
Constructor from integral type.
Definition Bytes.h:90
Bytes(const char *str)
Constructor from C-string.
Definition Bytes.h:78
uint32_t CRC32(const void *data, size_t length, uint32_t crc=0)
Calculates CRC32-C (Castagnoli) checksum for data integrity verification.
Definition Common.h:72
#define UNIOT_LOG_ERROR(...)
Log an ERROR level message Used for critical errors that may prevent normal operation....
Definition Logger.h:226