MIP_SDK  v3.0.0
MicroStrain Communications Library for embedded systems
readwrite.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include "../platform.hpp"
4 
5 #include <cstring>
6 #include <stdint.h>
7 #include <stddef.h>
8 #include <type_traits>
9 
10 // Don't depend on C++ standard since it could be different between
11 // compiling this lib and the user's project including this file.
12 // In that case there would be two conflicting definitions of Endian!
13 // Maybe use a CMake variable in the future.
14 //
15 //#if __cpp_lib_endian >= 201907L
16 //#include <bit>
17 //#endif
18 
19 #ifdef MICROSTRAIN_USE_STD_ENDIAN
20 
21 #include <bit>
22 
23 namespace microstrain
24 {
25 namespace serialization
26 {
27  using Endian = std::endian;
28 } // namespace serialization
29 } // namespace microstrain
30 
31 #else // MICROSTRAIN_USE_STD_ENDIAN
32 
33 namespace microstrain
34 {
35 namespace serialization
36 {
37 
38 enum class Endian
39 {
40  little,
41  big,
42  //native = little,
43 };
44 
45 } // namespace serialization
46 } // namespace microstrain
47 
48 #endif // MICROSTRAIN_USE_STD_ENDIAN
49 
50 namespace microstrain
51 {
52 namespace serialization
53 {
54 
55 //
56 // Write to buffer
57 //
58 
59 namespace big_endian
60 {
61 
62 template<class T>
63 typename std::enable_if<std::is_arithmetic<T>::value && sizeof(T) == 1, size_t>::type
64 /*size_t*/ write(uint8_t *buffer, T value)
65 {
66  buffer[0] = reinterpret_cast<const uint8_t *>(&value)[0];
67  return sizeof(T);
68 }
69 
70 template<class T>
71 typename std::enable_if<std::is_arithmetic<T>::value && sizeof(T) == 2, size_t>::type
72 /*size_t*/ write(uint8_t *buffer, T value)
73 {
74  buffer[0] = reinterpret_cast<const uint8_t *>(&value)[1];
75  buffer[1] = reinterpret_cast<const uint8_t *>(&value)[0];
76  return sizeof(T);
77 }
78 
79 template<class T>
80 typename std::enable_if<std::is_arithmetic<T>::value && sizeof(T) == 4, size_t>::type
81 /*size_t*/ write(uint8_t *buffer, T value)
82 {
83  buffer[0] = reinterpret_cast<const uint8_t *>(&value)[3];
84  buffer[1] = reinterpret_cast<const uint8_t *>(&value)[2];
85  buffer[2] = reinterpret_cast<const uint8_t *>(&value)[1];
86  buffer[3] = reinterpret_cast<const uint8_t *>(&value)[0];
87  return sizeof(T);
88 }
89 
90 template<class T>
91 typename std::enable_if<std::is_arithmetic<T>::value && sizeof(T) == 8, size_t>::type
92 /*size_t*/ write(uint8_t *buffer, T value)
93 {
94  buffer[0] = reinterpret_cast<const uint8_t *>(&value)[7];
95  buffer[1] = reinterpret_cast<const uint8_t *>(&value)[6];
96  buffer[2] = reinterpret_cast<const uint8_t *>(&value)[5];
97  buffer[3] = reinterpret_cast<const uint8_t *>(&value)[4];
98  buffer[4] = reinterpret_cast<const uint8_t *>(&value)[3];
99  buffer[5] = reinterpret_cast<const uint8_t *>(&value)[2];
100  buffer[6] = reinterpret_cast<const uint8_t *>(&value)[1];
101  buffer[7] = reinterpret_cast<const uint8_t *>(&value)[0];
102  return sizeof(T);
103 }
104 
105 } // namespace big_endian
106 namespace little_endian
107 {
108 
109 template<class T>
110 typename std::enable_if<std::is_arithmetic<T>::value, size_t>::type
111 /*size_t*/ write(uint8_t *buffer, T value)
112 {
113  std::memcpy(buffer, &value, sizeof(value));
114  return sizeof(value);
115 }
116 
117 } // namespace little_endian
118 
119 
120 template<Endian E, class T>
121 typename std::enable_if<std::is_arithmetic<T>::value, size_t>::type
122 /*size_t*/ write(uint8_t* buffer, T value) { return E==Endian::little ? little_endian::write(buffer,value) : big_endian::write(buffer,value); }
123 
124 
125 //
126 // Read from buffer
127 //
128 
129 namespace big_endian
130 {
131 
132 template<class T>
133 typename std::enable_if<std::is_arithmetic<T>::value && sizeof(T)==1, size_t>::type
134 /*size_t*/ read(const uint8_t* buffer, T& value)
135 {
136  reinterpret_cast<uint8_t*>(&value)[0] = buffer[0];
137  return sizeof(T);
138 }
139 
140 template<class T>
141 typename std::enable_if<std::is_arithmetic<T>::value && sizeof(T)==2, size_t>::type
142 /*size_t*/ read(const uint8_t* buffer, T& value)
143 {
144  reinterpret_cast<uint8_t*>(&value)[0] = buffer[1];
145  reinterpret_cast<uint8_t*>(&value)[1] = buffer[0];
146  return sizeof(T);
147 }
148 
149 template<class T>
150 typename std::enable_if<std::is_arithmetic<T>::value && sizeof(T)==4, size_t>::type
151 /*size_t*/ read(const uint8_t* buffer, T& value)
152 {
153  reinterpret_cast<uint8_t*>(&value)[0] = buffer[3];
154  reinterpret_cast<uint8_t*>(&value)[1] = buffer[2];
155  reinterpret_cast<uint8_t*>(&value)[2] = buffer[1];
156  reinterpret_cast<uint8_t*>(&value)[3] = buffer[0];
157  return sizeof(T);
158 }
159 
160 template<class T>
161 typename std::enable_if<std::is_arithmetic<T>::value && sizeof(T)==8, size_t>::type
162 /*size_t*/ read(const uint8_t* buffer, T& value)
163 {
164  reinterpret_cast<uint8_t*>(&value)[0] = buffer[7];
165  reinterpret_cast<uint8_t*>(&value)[1] = buffer[6];
166  reinterpret_cast<uint8_t*>(&value)[2] = buffer[5];
167  reinterpret_cast<uint8_t*>(&value)[3] = buffer[4];
168  reinterpret_cast<uint8_t*>(&value)[4] = buffer[3];
169  reinterpret_cast<uint8_t*>(&value)[5] = buffer[2];
170  reinterpret_cast<uint8_t*>(&value)[6] = buffer[1];
171  reinterpret_cast<uint8_t*>(&value)[7] = buffer[0];
172  return sizeof(T);
173 }
174 
175 } // namespace big_endian
176 namespace little_endian
177 {
178 
179 template<class T>
180 typename std::enable_if<std::is_arithmetic<T>::value, size_t>::type
181 /*size_t*/ read(const uint8_t* buffer, T& value)
182 {
183  std::memcpy(&value, buffer, sizeof(T));
184  return sizeof(T);
185 }
186 
187 } // namespace little_endian
188 
189 
190 template<Endian E, class T>
191 size_t read(const uint8_t* buffer, T& value)
192 {
193  return (E==Endian::little) ? little_endian::read(buffer, value) : big_endian::read(buffer, value);
194 }
195 
196 // Read T and return by value
197 template<Endian E, class T>
198 T read(const uint8_t* buffer)
199 {
200  T value;
201  read<E,T>(buffer, value);
202  return value;
203 }
204 
205 } // namespace serialization
206 } // namespace microstrain
microstrain::serialization::Endian::big
@ big
microstrain::serialization::read
size_t read(const uint8_t *buffer, T &value)
Definition: readwrite.hpp:191
microstrain::serialization::write
std::enable_if< std::is_arithmetic< T >::value, size_t >::type write(uint8_t *buffer, T value)
Definition: readwrite.hpp:122
microstrain::serialization::big_endian::write
std::enable_if< std::is_arithmetic< T >::value &&sizeof(T)==1, size_t >::type write(uint8_t *buffer, T value)
Definition: readwrite.hpp:64
microstrain::serialization::Endian::little
@ little
microstrain::serialization::little_endian::read
std::enable_if< std::is_arithmetic< T >::value, size_t >::type read(const uint8_t *buffer, T &value)
Definition: readwrite.hpp:181
microstrain::serialization::little_endian::write
std::enable_if< std::is_arithmetic< T >::value, size_t >::type write(uint8_t *buffer, T value)
Definition: readwrite.hpp:111
microstrain
Definition: embedded_time.h:8
microstrain::serialization::big_endian::read
std::enable_if< std::is_arithmetic< T >::value &&sizeof(T)==1, size_t >::type read(const uint8_t *buffer, T &value)
Definition: readwrite.hpp:134
microstrain::serialization::Endian
Endian
Definition: readwrite.hpp:38