ProsecCoAP 🥂
 
Loading...
Searching...
No Matches
Utils.h
Go to the documentation of this file.
1
5#ifndef __PROSECCOAP_UTILS_H__
6#define __PROSECCOAP_UTILS_H__
7
8#include <string.h> // For memcpy.
9#include <stdint.h>
10#include <stddef.h> // For size_t.
11
12namespace Coap
13{
19 namespace Utils
20 {
32 template <typename T>
33 inline void toNetworkByteOrder(T value, uint8_t *result)
34 {
35#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
36 // If the host is already big-endian, we can just memcpy the value.
37 memcpy(result, &value, sizeof(T));
38#else
39 // The host is little endian, so we need to manually convert to big-endian.
40 for (size_t i = 0; i < sizeof(T); ++i)
41 {
42 // Shift right by (sizeof(T) - 1 - i) * 8 bits, then mask the lowest byte.
43 result[i] = static_cast<uint8_t>((value >> ((sizeof(T) - 1 - i) * 8)) & 0xFF);
44 }
45#endif
46 }
47
54 inline void toNetworkByteOrder(float value, uint8_t *result)
55 {
56 uint32_t int_value;
57 memcpy(&int_value, &value, sizeof(float));
58 toNetworkByteOrder(int_value, result);
59 }
60
67 inline void toNetworkByteOrder(double value, uint8_t *result)
68 {
69 uint64_t int_value;
70 memcpy(&int_value, &value, sizeof(double));
71 toNetworkByteOrder(int_value, result);
72 }
73
74 // NOTE: The host byte order (big/little endian) does not matter, as the bit shift operator
75 // will adjust accordingly.
76 // See https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
77
93 inline constexpr uint16_t read_uint16(const uint8_t *bytes)
94 {
95 return static_cast<uint16_t>((static_cast<uint16_t>(bytes[0]) << 8) |
96 static_cast<uint16_t>(bytes[1]));
97 }
98
102 inline constexpr uint32_t read_uint32(const uint8_t *bytes)
103 {
104 return (static_cast<uint32_t>(bytes[0]) << 24) |
105 (static_cast<uint32_t>(bytes[1]) << 16) |
106 (static_cast<uint32_t>(bytes[2]) << 8) |
107 (static_cast<uint32_t>(bytes[3]));
108 }
109
113 inline constexpr uint64_t read_uint64(const uint8_t *bytes)
114 {
115 return (static_cast<uint64_t>(bytes[0]) << 56) |
116 (static_cast<uint64_t>(bytes[1]) << 48) |
117 (static_cast<uint64_t>(bytes[2]) << 40) |
118 (static_cast<uint64_t>(bytes[3]) << 32) |
119 (static_cast<uint64_t>(bytes[4]) << 24) |
120 (static_cast<uint64_t>(bytes[5]) << 16) |
121 (static_cast<uint64_t>(bytes[6]) << 8) |
122 (static_cast<uint64_t>(bytes[7]));
123 }
124
128 inline constexpr int16_t read_int16(const uint8_t *bytes)
129 {
130 // Read as unsigned to avoid bitshift undefined behaviour, then cast to signed.
131 return static_cast<int16_t>(read_uint16(bytes));
132 }
133
137 inline constexpr int32_t read_int32(const uint8_t *bytes)
138 {
139 return static_cast<int32_t>(read_uint32(bytes));
140 }
141
145 inline constexpr int64_t read_int64(const uint8_t *bytes)
146 {
147 return static_cast<int64_t>(read_uint64(bytes));
148 }
149
153 inline float read_float(const uint8_t *bytes)
154 {
155 uint32_t value = read_uint32(bytes);
156 float host_float;
157 memcpy(&host_float, &value, sizeof(float));
158 return host_float;
159 }
160
166 template <typename T = double>
167 inline T read_double(const uint8_t *bytes)
168 {
169 static_assert(sizeof(T) == 8, "Cannot read a 64-bit network double on a 32-bit double architecture (like AVR).");
170 uint64_t value = read_uint64(bytes);
171 double host_double;
172 memcpy(&host_double, &value, sizeof(double));
173 return host_double;
174 }
175 }
176}
177
178#endif
constexpr int32_t read_int32(const uint8_t *bytes)
Reads a 32-bit signed integer from a Big-Endian byte stream.
Definition Utils.h:137
T read_double(const uint8_t *bytes)
Reads a 64-bit double from a Big-Endian byte stream.
Definition Utils.h:167
float read_float(const uint8_t *bytes)
Reads a 32-bit float from a Big-Endian byte stream.
Definition Utils.h:153
constexpr uint32_t read_uint32(const uint8_t *bytes)
Reads a 32-bit unsigned integer from a Big-Endian byte stream.
Definition Utils.h:102
constexpr int16_t read_int16(const uint8_t *bytes)
Reads a 16-bit signed integer from a Big-Endian byte stream.
Definition Utils.h:128
constexpr uint16_t read_uint16(const uint8_t *bytes)
Reads a 16-bit unsigned integer from a Big-Endian byte stream.
Definition Utils.h:93
void toNetworkByteOrder(T value, uint8_t *result)
Convert an integer-like value to network byte order (i.e. big-endian).
Definition Utils.h:33
constexpr uint64_t read_uint64(const uint8_t *bytes)
Reads a 64-bit unsigned integer from a Big-Endian byte stream.
Definition Utils.h:113
constexpr int64_t read_int64(const uint8_t *bytes)
Reads a 64-bit signed integer from a Big-Endian byte stream.
Definition Utils.h:145
Namespace for the library.
Definition Definitions.h:161