1 // Copyright (c) 2012, Robert Escriva
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright notice,
8 // this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright
10 // notice, this list of conditions and the following disclaimer in the
11 // documentation and/or other materials provided with the distribution.
12 // * Neither the name of this project nor the names of its contributors may
13 // be used to endorse or promote products derived from this software
14 // without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 // POSSIBILITY OF SUCH DAMAGE.
27
28 #ifndef e_endian_h_
29 #define e_endian_h_
30
31 // C
32 #include <stdint.h>
33
34 namespace e
35 {
36
37 // Pack values into the buffer
38 inline uint8_t*
pack8be(uint8_t number,uint8_t * buffer)39 pack8be(uint8_t number, uint8_t* buffer)
40 {
41 buffer[0] = number;
42 return buffer + sizeof(uint8_t);
43 }
44
45 inline uint8_t*
pack8le(uint8_t number,uint8_t * buffer)46 pack8le(uint8_t number, uint8_t* buffer)
47 {
48 buffer[0] = number;
49 return buffer + sizeof(uint8_t);
50 }
51
52 inline uint8_t*
pack16be(uint16_t number,uint8_t * buffer)53 pack16be(uint16_t number, uint8_t* buffer)
54 {
55 buffer[0] = number >> 8;
56 buffer[1] = number & 0xff;
57 return buffer + sizeof(uint16_t);
58 }
59
60 inline uint8_t*
pack16le(uint16_t number,uint8_t * buffer)61 pack16le(uint16_t number, uint8_t* buffer)
62 {
63 buffer[0] = number & 0xff;
64 buffer[1] = number >> 8;
65 return buffer + sizeof(uint16_t);
66 }
67
68 inline uint8_t*
pack32be(uint32_t number,uint8_t * buffer)69 pack32be(uint32_t number, uint8_t* buffer)
70 {
71 buffer[0] = number >> 24;
72 buffer[1] = (number >> 16) & 0xff;
73 buffer[2] = (number >> 8) & 0xff;
74 buffer[3] = number & 0xff;
75 return buffer + sizeof(uint32_t);
76 }
77
78 inline uint8_t*
pack32le(uint32_t number,uint8_t * buffer)79 pack32le(uint32_t number, uint8_t* buffer)
80 {
81 buffer[0] = number & 0xff;
82 buffer[1] = (number >> 8) & 0xff;
83 buffer[2] = (number >> 16) & 0xff;
84 buffer[3] = number >> 24;
85 return buffer + sizeof(uint32_t);
86 }
87
88 inline uint8_t*
pack64be(uint64_t number,uint8_t * buffer)89 pack64be(uint64_t number, uint8_t* buffer)
90 {
91 buffer[0] = number >> 56;
92 buffer[1] = (number >> 48) & 0xff;
93 buffer[2] = (number >> 40) & 0xff;
94 buffer[3] = (number >> 32) & 0xff;
95 buffer[4] = (number >> 24) & 0xff;
96 buffer[5] = (number >> 16) & 0xff;
97 buffer[6] = (number >> 8) & 0xff;
98 buffer[7] = number & 0xff;
99 return buffer + sizeof(uint64_t);
100 }
101
102 inline uint8_t*
pack64le(uint64_t number,uint8_t * buffer)103 pack64le(uint64_t number, uint8_t* buffer)
104 {
105 buffer[0] = number & 0xff;
106 buffer[1] = (number >> 8) & 0xff;
107 buffer[2] = (number >> 16) & 0xff;
108 buffer[3] = (number >> 24) & 0xff;
109 buffer[4] = (number >> 32) & 0xff;
110 buffer[5] = (number >> 40) & 0xff;
111 buffer[6] = (number >> 48) & 0xff;
112 buffer[7] = number >> 56;
113 return buffer + sizeof(uint64_t);
114 }
115
116 inline uint8_t*
packfloatbe(float number,uint8_t * buffer)117 packfloatbe(float number, uint8_t* buffer)
118 {
119 union {float f; uint32_t i;};
120 f = number;
121 return pack32be(i, buffer);
122 }
123
124 inline uint8_t*
packfloatle(float number,uint8_t * buffer)125 packfloatle(float number, uint8_t* buffer)
126 {
127 union {float f; uint32_t i;};
128 f = number;
129 return pack32le(i, buffer);
130 }
131
132 inline uint8_t*
packdoublebe(double number,uint8_t * buffer)133 packdoublebe(double number, uint8_t* buffer)
134 {
135 union {double d; uint64_t i;};
136 d = number;
137 return pack64be(i, buffer);
138 }
139
140 inline uint8_t*
packdoublele(double number,uint8_t * buffer)141 packdoublele(double number, uint8_t* buffer)
142 {
143 union {double d; uint64_t i;};
144 d = number;
145 return pack64le(i, buffer);
146 }
147
148 // Unpack values from the buffer
149 inline const uint8_t*
unpack8be(const uint8_t * buffer,uint8_t * number)150 unpack8be(const uint8_t* buffer, uint8_t* number)
151 {
152 *number = buffer[0];
153 return buffer + sizeof(uint8_t);
154 }
155
156 inline const uint8_t*
unpack8le(const uint8_t * buffer,uint8_t * number)157 unpack8le(const uint8_t* buffer, uint8_t* number)
158 {
159 *number = buffer[0];
160 return buffer + sizeof(uint8_t);
161 }
162
163 inline const uint8_t*
unpack16be(const uint8_t * buffer,uint16_t * number)164 unpack16be(const uint8_t* buffer, uint16_t* number)
165 {
166 *number = static_cast<uint16_t>(buffer[0]) << 8
167 | static_cast<uint16_t>(buffer[1]);
168 return buffer + sizeof(uint16_t);
169 }
170
171 inline const uint8_t*
unpack16le(const uint8_t * buffer,uint16_t * number)172 unpack16le(const uint8_t* buffer, uint16_t* number)
173 {
174 *number = static_cast<uint16_t>(buffer[0])
175 | static_cast<uint16_t>(buffer[1]) << 8;
176 return buffer + sizeof(uint16_t);
177 }
178
179 inline const uint8_t*
unpack32be(const uint8_t * buffer,uint32_t * number)180 unpack32be(const uint8_t* buffer, uint32_t* number)
181 {
182 *number = static_cast<uint32_t>(buffer[0]) << 24
183 | static_cast<uint32_t>(buffer[1]) << 16
184 | static_cast<uint32_t>(buffer[2]) << 8
185 | static_cast<uint32_t>(buffer[3]);
186 return buffer + sizeof(uint32_t);
187 }
188
189 inline const uint8_t*
unpack32le(const uint8_t * buffer,uint32_t * number)190 unpack32le(const uint8_t* buffer, uint32_t* number)
191 {
192 *number = static_cast<uint32_t>(buffer[0])
193 | static_cast<uint32_t>(buffer[1]) << 8
194 | static_cast<uint32_t>(buffer[2]) << 16
195 | static_cast<uint32_t>(buffer[3]) << 24;
196 return buffer + sizeof(uint32_t);
197 }
198
199 inline const uint8_t*
unpack64be(const uint8_t * buffer,uint64_t * number)200 unpack64be(const uint8_t* buffer, uint64_t* number)
201 {
202 *number = static_cast<uint64_t>(buffer[0]) << 56
203 | static_cast<uint64_t>(buffer[1]) << 48
204 | static_cast<uint64_t>(buffer[2]) << 40
205 | static_cast<uint64_t>(buffer[3]) << 32
206 | static_cast<uint64_t>(buffer[4]) << 24
207 | static_cast<uint64_t>(buffer[5]) << 16
208 | static_cast<uint64_t>(buffer[6]) << 8
209 | static_cast<uint64_t>(buffer[7]);
210 return buffer + sizeof(uint64_t);
211 }
212
213 inline const uint8_t*
unpack64le(const uint8_t * buffer,uint64_t * number)214 unpack64le(const uint8_t* buffer, uint64_t* number)
215 {
216 *number = static_cast<uint64_t>(buffer[0])
217 | static_cast<uint64_t>(buffer[1]) << 8
218 | static_cast<uint64_t>(buffer[2]) << 16
219 | static_cast<uint64_t>(buffer[3]) << 24
220 | static_cast<uint64_t>(buffer[4]) << 32
221 | static_cast<uint64_t>(buffer[5]) << 40
222 | static_cast<uint64_t>(buffer[6]) << 48
223 | static_cast<uint64_t>(buffer[7]) << 56;
224 return buffer + sizeof(uint64_t);
225 }
226
227 inline const uint8_t*
unpackfloatbe(const uint8_t * buffer,float * number)228 unpackfloatbe(const uint8_t* buffer, float* number)
229 {
230 union {float f; uint32_t i;};
231 const uint8_t* ret = unpack32be(buffer, &i);
232 *number = f;
233 return ret;
234 }
235
236 inline const uint8_t*
unpackfloatle(const uint8_t * buffer,float * number)237 unpackfloatle(const uint8_t* buffer, float* number)
238 {
239 union {float f; uint32_t i;};
240 const uint8_t* ret = unpack32le(buffer, &i);
241 *number = f;
242 return ret;
243 }
244
245 inline const uint8_t*
unpackdoublebe(const uint8_t * buffer,double * number)246 unpackdoublebe(const uint8_t* buffer, double* number)
247 {
248 union {double d; uint64_t i;};
249 const uint8_t* ret = unpack64be(buffer, &i);
250 *number = d;
251 return ret;
252 }
253
254 inline const uint8_t*
unpackdoublele(const uint8_t * buffer,double * number)255 unpackdoublele(const uint8_t* buffer, double* number)
256 {
257 union {double d; uint64_t i;};
258 const uint8_t* ret = unpack64le(buffer, &i);
259 *number = d;
260 return ret;
261 }
262
263 #define SIGNED_WRAPPER(SZ, END) \
264 inline const uint8_t* \
265 unpack ## SZ ## END(const uint8_t* buffer, int ## SZ ## _t* number) \
266 { \
267 uint ## SZ ## _t tmp; \
268 const uint8_t* ret = unpack ## SZ ## END(buffer, &tmp); \
269 *number = static_cast<int ## SZ ## _t>(tmp); \
270 return ret; \
271 }
272
273 SIGNED_WRAPPER(8, be)
274 SIGNED_WRAPPER(8, le)
275 SIGNED_WRAPPER(16, be)
276 SIGNED_WRAPPER(16, le)
277 SIGNED_WRAPPER(32, be)
278 SIGNED_WRAPPER(32, le)
279 SIGNED_WRAPPER(64, be)
280 SIGNED_WRAPPER(64, le)
281
282 #undef SIGNED_WRAPPER
283
284 #define PACKCHAR_INT_WRAPPER(SZ, END) \
285 inline const char* \
286 unpack ## SZ ## END(const char* buffer, uint ## SZ ## _t* number) \
287 { \
288 return reinterpret_cast<const char*>(unpack ## SZ ## END(reinterpret_cast<const uint8_t*>(buffer), number)); \
289 } \
290 inline const char* \
291 unpack ## SZ ## END(const char* buffer, int ## SZ ## _t* number) \
292 { \
293 return reinterpret_cast<const char*>(unpack ## SZ ## END(reinterpret_cast<const uint8_t*>(buffer), number)); \
294 } \
295 inline char* \
296 pack ## SZ ## END(int ## SZ ## _t number, char* buffer) \
297 { \
298 return reinterpret_cast<char*>(pack ## SZ ## END(number, reinterpret_cast<uint8_t*>(buffer))); \
299 }
300
301 PACKCHAR_INT_WRAPPER(8, be)
302 PACKCHAR_INT_WRAPPER(8, le)
303 PACKCHAR_INT_WRAPPER(16, be)
304 PACKCHAR_INT_WRAPPER(16, le)
305 PACKCHAR_INT_WRAPPER(32, be)
306 PACKCHAR_INT_WRAPPER(32, le)
307 PACKCHAR_INT_WRAPPER(64, be)
308 PACKCHAR_INT_WRAPPER(64, le)
309
310 #undef PACKCHAR_INT_WRAPPER
311
312 #define PACKCHAR_FLOAT_WRAPPER(TYPE, END) \
313 inline const char* \
314 unpack ## TYPE ## END(const char* buffer, TYPE* number) \
315 { \
316 return reinterpret_cast<const char*>(unpack ## TYPE ## END(reinterpret_cast<const uint8_t*>(buffer), number)); \
317 } \
318 inline char* \
319 pack ## TYPE ## END(TYPE number, char* buffer) \
320 { \
321 return reinterpret_cast<char*>(pack ## TYPE ## END(number, reinterpret_cast<uint8_t*>(buffer))); \
322 }
323
324 PACKCHAR_FLOAT_WRAPPER(float, be)
325 PACKCHAR_FLOAT_WRAPPER(float, le)
326 PACKCHAR_FLOAT_WRAPPER(double, be)
327 PACKCHAR_FLOAT_WRAPPER(double, le)
328
329 #undef PACKCHAR_FLOAT_WRAPPER
330
331 } // namespace e
332
333 #endif // e_endian_h_
334