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