| Wireshark 4.7.0 The Wireshark network protocol analyzer

Loading...
Searching...
No Matches
pint.h
Go to the documentation of this file.
1
13#ifndef __PINT_H__
14#define __PINT_H__
15
16#include <inttypes.h>
17
18#include <glib.h>
19
20/* Routines that take a possibly-unaligned pointer to a 16-bit, 24-bit,
21 * 32-bit, 40-bit, ... 64-bit integral quantity, in a particular byte
22 * order, and fetch the value and return it in host byte order.
23 *
24 * The pntohuN() routines fetch big-endian unsigned values; the pletohuN()
25 * routines fetch little-endian unsigned values.
26 */
27
28/* On most architectures, accesses of 16, 32, and 64 bit quantities can be
29 * heavily optimized. gcc and clang recognize portable versions below and,
30 * at -Os and higher, optimize them appropriately (for gcc, that includes
31 * for z/Architecture, PPC64, MIPS, etc.). Older versions don't do as good
32 * of a job with 16 bit accesses, though.
33 *
34 * Unfortunately, MSVC and icc (both the "classic" version and the new
35 * LLVM-based Intel C Compiler) do not, according to Matt Godbolt's Compiler
36 * Explorer (https://godbolt.org) as of the end of 2022. They *do* recognize
37 * and optimize a memcpy based approach (which avoids unaligned accesses on,
38 * say, ARM32), though that requires byteswapping appropriately.
39 */
40
41#if (defined(_MSC_VER) && !defined(__clang__)) || defined(__INTEL_COMPILER) || defined(__INTEL_LLVM_COMPILER)
42/* MSVC or Intel C Compiler (Classic or new LLVM version), but not
43 * clang-cl on Windows.
44 */
45/* Unfortunately, C23 did not fully accept the N3022 Modern Bit Utilities
46 * proposal, so a standard bytereverse function has been deferred for some
47 * future version:
48 * https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3048.htm
49 * https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3022.htm
50 *
51 * So choose byteswap intrinsics we know we have.
52 */
53#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__INTEL_LLVM_COMPILER) && !defined(__clang__)
54/* Intel and clang-cl both define _MSC_VER when compiling on Windows for
55 * greater compatibility (just as they define __GNUC__ on other platforms).
56 * However, at least on some versions, while including the MSVC <stdlib.h>
57 * provides access to the _byteswap_ intrinsics, they are not actually
58 * optimized into a single x86 BSWAP function, unlike the gcc-style intrinsics
59 * (which both support.) See: https://stackoverflow.com/q/72327906
60 */
61#include <stdlib.h> // For MSVC _byteswap intrinsics
62#define pint_bswap16(x) _byteswap_ushort(x)
63#define pint_bswap32(x) _byteswap_ulong(x)
64/* Hopefully MSVC never decides that a long is 64 bit. */
65#define pint_bswap64(x) _byteswap_uint64(x)
66#elif defined(__INTEL_COMPILER)
67/* The (deprecated) Intel C++ Compiler Classic has these byteswap intrinsics.
68 * It also has the GCC-style intrinsics, though __builtin_bswap16 wasn't
69 * added until some point after icc 13.0 but at least by 16.0, reflecting
70 * that it wasn't added to gcc until 4.8.
71 */
72#define pint_bswap16(x) _bswap16(x)
73#define pint_bswap32(x) _bswap32(x)
74#define pint_bswap64(x) _bswap64(x)
75#else
76/* GCC-style _bswap intrinsics */
77/* The new LLVM-based Intel C++ Compiler doesn't have the above intrinsics,
78 * but it always has all the GCC intrinsics.
79 */
80/* __builtin_bswap32 and __builtin_bswap64 intrinsics have been supported
81 * for a long time on gcc (4.1), and clang (pre 3.0), versions that predate
82 * C11 and C+11 support, which we require, so we could assume we have them.
83 *
84 * __builtin_bswap16 was added a bit later, gcc 4.8, and clang 3.2. While
85 * those versions or later are required for full C11 and C++11 support,
86 * some earlier versions claim to support C11 and C++11 in ways that might
87 * allow them to get past CMake. We don't use this codepath for those
88 * compilers because they heavily optimize the portable versions, though.
89 */
90#define pint_bswap16(x) __builtin_bswap16(x)
91#define pint_bswap32(x) __builtin_bswap32(x)
92#define pint_bswap64(x) __builtin_bswap64(x)
93#endif
94
95 static inline uint16_t pntohu16(const void *p)
96{
97 uint16_t ret;
98 memcpy(&ret, p, sizeof(ret));
99#if G_BYTE_ORDER == G_LITTLE_ENDIAN
100 ret = pint_bswap16(ret);
101#endif
102 return ret;
103}
104
105 static inline uint32_t pntohu32(const void *p)
106{
107 uint32_t ret;
108 memcpy(&ret, p, sizeof(ret));
109#if G_BYTE_ORDER == G_LITTLE_ENDIAN
110 ret = pint_bswap32(ret);
111#endif
112 return ret;
113}
114
115 static inline uint64_t pntohu64(const void *p)
116{
117 uint64_t ret;
118 memcpy(&ret, p, sizeof(ret));
119#if G_BYTE_ORDER == G_LITTLE_ENDIAN
120 ret = pint_bswap64(ret);
121#endif
122 return ret;
123}
124
125 static inline uint16_t pletohu16(const void *p)
126{
127 uint16_t ret;
128 memcpy(&ret, p, sizeof(ret));
129#if G_BYTE_ORDER == G_BIG_ENDIAN
130 ret = pint_bswap16(ret);
131#endif
132 return ret;
133}
134
135 static inline uint32_t pletohu32(const void *p)
136{
137 uint32_t ret;
138 memcpy(&ret, p, sizeof(ret));
139#if G_BYTE_ORDER == G_BIG_ENDIAN
140 ret = pint_bswap32(ret);
141#endif
142 return ret;
143}
144
145 static inline uint64_t pletohu64(const void *p)
146{
147 uint64_t ret;
148 memcpy(&ret, p, sizeof(ret));
149#if G_BYTE_ORDER == G_BIG_ENDIAN
150 ret = pint_bswap64(ret);
151#endif
152 return ret;
153}
154
155 static inline void phtonu16(uint8_t *p, uint16_t v)
156{
157#if G_BYTE_ORDER == G_LITTLE_ENDIAN
158 v = pint_bswap16(v);
159#endif
160 memcpy(p, &v, sizeof(v));
161}
162
163 static inline void phtonu32(uint8_t *p, uint32_t v)
164{
165#if G_BYTE_ORDER == G_LITTLE_ENDIAN
166 v = pint_bswap32(v);
167#endif
168 memcpy(p, &v, sizeof(v));
169}
170
171 static inline void phtonu64(uint8_t *p, uint64_t v) {
172#if G_BYTE_ORDER == G_LITTLE_ENDIAN
173 v = pint_bswap64(v);
174#endif
175 memcpy(p, &v, sizeof(v));
176}
177
178 static inline void phtoleu16(uint8_t *p, uint32_t v)
179{
180#if G_BYTE_ORDER == G_BIG_ENDIAN
181 v = pint_bswap16(v);
182#endif
183 memcpy(p, &v, sizeof(v));
184}
185
186 static inline void phtoleu32(uint8_t *p, uint32_t v)
187{
188#if G_BYTE_ORDER == G_BIG_ENDIAN
189 v = pint_bswap32(v);
190#endif
191 memcpy(p, &v, sizeof(v));
192}
193
194 static inline void phtoleu64(uint8_t *p, uint64_t v) {
195#if G_BYTE_ORDER == G_BIG_ENDIAN
196 v = pint_bswap64(v);
197#endif
198 memcpy(p, &v, sizeof(v));
199}
200
201#else
202/* Portable functions */
203
210 static inline uint16_t pntohu16(const void *p)
211{
212 return (uint16_t)*((const uint8_t *)(p)+0)<<8|
213 (uint16_t)*((const uint8_t *)(p)+1)<<0;
214}
215
216 static inline uint32_t pntohu32(const void *p)
217{
218 return (uint32_t)*((const uint8_t *)(p)+0)<<24|
219 (uint32_t)*((const uint8_t *)(p)+1)<<16|
220 (uint32_t)*((const uint8_t *)(p)+2)<<8|
221 (uint32_t)*((const uint8_t *)(p)+3)<<0;
222}
223
231 static inline uint64_t pntohu64(const void *p)
232{
233 return (uint64_t)*((const uint8_t *)(p)+0)<<56|
234 (uint64_t)*((const uint8_t *)(p)+1)<<48|
235 (uint64_t)*((const uint8_t *)(p)+2)<<40|
236 (uint64_t)*((const uint8_t *)(p)+3)<<32|
237 (uint64_t)*((const uint8_t *)(p)+4)<<24|
238 (uint64_t)*((const uint8_t *)(p)+5)<<16|
239 (uint64_t)*((const uint8_t *)(p)+6)<<8|
240 (uint64_t)*((const uint8_t *)(p)+7)<<0;
241}
242
249 static inline uint16_t pletohu16(const void *p)
250{
251 return (uint16_t)*((const uint8_t *)(p)+1)<<8|
252 (uint16_t)*((const uint8_t *)(p)+0)<<0;
253}
254
261 static inline uint32_t pletohu32(const void *p)
262{
263 return (uint32_t)*((const uint8_t *)(p)+3)<<24|
264 (uint32_t)*((const uint8_t *)(p)+2)<<16|
265 (uint32_t)*((const uint8_t *)(p)+1)<<8|
266 (uint32_t)*((const uint8_t *)(p)+0)<<0;
267}
268
275 static inline uint64_t pletohu64(const void *p)
276{
277 return (uint64_t)*((const uint8_t *)(p)+7)<<56|
278 (uint64_t)*((const uint8_t *)(p)+6)<<48|
279 (uint64_t)*((const uint8_t *)(p)+5)<<40|
280 (uint64_t)*((const uint8_t *)(p)+4)<<32|
281 (uint64_t)*((const uint8_t *)(p)+3)<<24|
282 (uint64_t)*((const uint8_t *)(p)+2)<<16|
283 (uint64_t)*((const uint8_t *)(p)+1)<<8|
284 (uint64_t)*((const uint8_t *)(p)+0)<<0;
285}
286
287/* Pointer routines to put items out in a particular byte order.
288 * These will work regardless of the byte alignment of the pointer.
289 */
290
291 static inline void phtonu16(uint8_t *p, uint16_t v)
292{
293 p[0] = (uint8_t)(v >> 8);
294 p[1] = (uint8_t)(v >> 0);
295}
296
303 static inline void phtonu32(uint8_t *p, uint32_t v)
304{
305 p[0] = (uint8_t)(v >> 24);
306 p[1] = (uint8_t)(v >> 16);
307 p[2] = (uint8_t)(v >> 8);
308 p[3] = (uint8_t)(v >> 0);
309}
310
317 static inline void phtonu64(uint8_t *p, uint64_t v) {
318 p[0] = (uint8_t)(v >> 56);
319 p[1] = (uint8_t)(v >> 48);
320 p[2] = (uint8_t)(v >> 40);
321 p[3] = (uint8_t)(v >> 32);
322 p[4] = (uint8_t)(v >> 24);
323 p[5] = (uint8_t)(v >> 16);
324 p[6] = (uint8_t)(v >> 8);
325 p[7] = (uint8_t)(v >> 0);
326}
327
334 static inline void phtoleu16(uint8_t *p, uint16_t v)
335{
336 p[0] = (uint8_t)(v >> 0);
337 p[1] = (uint8_t)(v >> 8);
338}
339
346 static inline void phtoleu32(uint8_t *p, uint32_t v) {
347 p[0] = (uint8_t)(v >> 0);
348 p[1] = (uint8_t)(v >> 8);
349 p[2] = (uint8_t)(v >> 16);
350 p[3] = (uint8_t)(v >> 24);
351}
352
359 static inline void phtoleu64(uint8_t *p, uint64_t v) {
360 p[0] = (uint8_t)(v >> 0);
361 p[1] = (uint8_t)(v >> 8);
362 p[2] = (uint8_t)(v >> 16);
363 p[3] = (uint8_t)(v >> 24);
364 p[4] = (uint8_t)(v >> 32);
365 p[5] = (uint8_t)(v >> 40);
366 p[6] = (uint8_t)(v >> 48);
367 p[7] = (uint8_t)(v >> 56);
368}
369#endif
370
371/*
372 * Single-byte versions, for completeness.
373*/
374
381 static inline uint8_t pntohu8(const void *p)
382{
383 return *((const uint8_t *)(p)+0)<<0;
384}
385
392 static inline uint8_t pletohu8(const void *p)
393{
394 return *((const uint8_t *)(p)+0)<<0;
395}
396
403 static inline void phtonu8(uint8_t *p, uint8_t v)
404{
405 p[0] = (uint8_t)((v) >> 0);
406}
407
414 static inline void phtoleu8(uint8_t *p, uint8_t v)
415{
416 p[0] = (uint8_t)((v) >> 0);
417}
418
419/*
420 * Non-power-of-2 field sizes; do these a byte at a time, and let the
421 * compiler optimize them to combinations of power-of-2 operations if
422 * possible.
423 */
424 static inline uint32_t pntohu24(const void *p)
425{
426 return (uint32_t)*((const uint8_t *)(p)+0)<<16|
427 (uint32_t)*((const uint8_t *)(p)+1)<<8|
428 (uint32_t)*((const uint8_t *)(p)+2)<<0;
429}
430
440 static inline uint64_t pntohu40(const void *p)
441{
442 return (uint64_t)*((const uint8_t *)(p)+0)<<32|
443 (uint64_t)*((const uint8_t *)(p)+1)<<24|
444 (uint64_t)*((const uint8_t *)(p)+2)<<16|
445 (uint64_t)*((const uint8_t *)(p)+3)<<8|
446 (uint64_t)*((const uint8_t *)(p)+4)<<0;
447}
448
455 static inline uint64_t pntohu48(const void *p)
456{
457 return (uint64_t)*((const uint8_t *)(p)+0)<<40|
458 (uint64_t)*((const uint8_t *)(p)+1)<<32|
459 (uint64_t)*((const uint8_t *)(p)+2)<<24|
460 (uint64_t)*((const uint8_t *)(p)+3)<<16|
461 (uint64_t)*((const uint8_t *)(p)+4)<<8|
462 (uint64_t)*((const uint8_t *)(p)+5)<<0;
463}
464
471 static inline uint64_t pntohu56(const void *p)
472{
473 return (uint64_t)*((const uint8_t *)(p)+0)<<48|
474 (uint64_t)*((const uint8_t *)(p)+1)<<40|
475 (uint64_t)*((const uint8_t *)(p)+2)<<32|
476 (uint64_t)*((const uint8_t *)(p)+3)<<24|
477 (uint64_t)*((const uint8_t *)(p)+4)<<16|
478 (uint64_t)*((const uint8_t *)(p)+5)<<8|
479 (uint64_t)*((const uint8_t *)(p)+6)<<0;
480}
481
488 static inline uint32_t pletohu24(const void *p)
489{
490 return (uint32_t)*((const uint8_t *)(p)+2)<<16|
491 (uint32_t)*((const uint8_t *)(p)+1)<<8|
492 (uint32_t)*((const uint8_t *)(p)+0)<<0;
493}
494
501 static inline uint64_t pletohu40(const void *p)
502{
503 return (uint64_t)*((const uint8_t *)(p)+4)<<32|
504 (uint64_t)*((const uint8_t *)(p)+3)<<24|
505 (uint64_t)*((const uint8_t *)(p)+2)<<16|
506 (uint64_t)*((const uint8_t *)(p)+1)<<8|
507 (uint64_t)*((const uint8_t *)(p)+0)<<0;
508}
509
516 static inline uint64_t pletohu48(const void *p)
517{
518 return (uint64_t)*((const uint8_t *)(p)+5)<<40|
519 (uint64_t)*((const uint8_t *)(p)+4)<<32|
520 (uint64_t)*((const uint8_t *)(p)+3)<<24|
521 (uint64_t)*((const uint8_t *)(p)+2)<<16|
522 (uint64_t)*((const uint8_t *)(p)+1)<<8|
523 (uint64_t)*((const uint8_t *)(p)+0)<<0;
524}
525
533 static inline uint64_t pletohu56(const void *p)
534{
535 return (uint64_t)*((const uint8_t *)(p)+6)<<48|
536 (uint64_t)*((const uint8_t *)(p)+5)<<40|
537 (uint64_t)*((const uint8_t *)(p)+4)<<32|
538 (uint64_t)*((const uint8_t *)(p)+3)<<24|
539 (uint64_t)*((const uint8_t *)(p)+2)<<16|
540 (uint64_t)*((const uint8_t *)(p)+1)<<8|
541 (uint64_t)*((const uint8_t *)(p)+0)<<0;
542}
543
551 static inline void phtonu24(uint8_t *p, uint32_t v)
552{
553 p[0] = (uint8_t)((v) >> 16);
554 p[1] = (uint8_t)((v) >> 8);
555 p[2] = (uint8_t)((v) >> 0);
556}
557
564 static inline void phtonu40(uint8_t *p, uint64_t v)
565{
566 p[0] = (uint8_t)((v) >> 32);
567 p[1] = (uint8_t)((v) >> 24);
568 p[2] = (uint8_t)((v) >> 16);
569 p[3] = (uint8_t)((v) >> 8);
570 p[4] = (uint8_t)((v) >> 0);
571}
572
579 static inline void phtonu48(uint8_t *p, uint64_t v)
580{
581 p[0] = (uint8_t)((v) >> 40);
582 p[1] = (uint8_t)((v) >> 32);
583 p[2] = (uint8_t)((v) >> 24);
584 p[3] = (uint8_t)((v) >> 16);
585 p[4] = (uint8_t)((v) >> 8);
586 p[5] = (uint8_t)((v) >> 0);
587}
588
596 static inline void phtonu56(uint8_t *p, uint64_t v)
597{
598 p[0] = (uint8_t)((v) >> 48);
599 p[1] = (uint8_t)((v) >> 40);
600 p[2] = (uint8_t)((v) >> 32);
601 p[3] = (uint8_t)((v) >> 24);
602 p[4] = (uint8_t)((v) >> 16);
603 p[5] = (uint8_t)((v) >> 8);
604 p[6] = (uint8_t)((v) >> 0);
605}
606
613 static inline void phtoleu24(uint8_t *p, uint32_t v)
614{
615 p[0] = (uint8_t)((v) >> 0);
616 p[1] = (uint8_t)((v) >> 8);
617 p[2] = (uint8_t)((v) >> 16);
618}
619
626 static inline void phtoleu40(uint8_t *p, uint64_t v)
627{
628 p[0] = (uint8_t)((v) >> 0);
629 p[1] = (uint8_t)((v) >> 8);
630 p[2] = (uint8_t)((v) >> 16);
631 p[3] = (uint8_t)((v) >> 24);
632 p[4] = (uint8_t)((v) >> 32);
633}
634
641 static inline void phtoleu48(uint8_t *p, uint64_t v)
642{
643 p[0] = (uint8_t)((v) >> 0);
644 p[1] = (uint8_t)((v) >> 8);
645 p[2] = (uint8_t)((v) >> 16);
646 p[3] = (uint8_t)((v) >> 24);
647 p[4] = (uint8_t)((v) >> 32);
648 p[5] = (uint8_t)((v) >> 40);
649}
650
657 static inline void phtoleu56(uint8_t *p, uint64_t v)
658{
659 p[0] = (uint8_t)((v) >> 0);
660 p[1] = (uint8_t)((v) >> 8);
661 p[2] = (uint8_t)((v) >> 16);
662 p[3] = (uint8_t)((v) >> 24);
663 p[4] = (uint8_t)((v) >> 32);
664 p[5] = (uint8_t)((v) >> 40);
665 p[6] = (uint8_t)((v) >> 48);
666}
667
668#endif /* PINT_H */
669
670/*
671 * Editor modelines - https://www.wireshark.org/tools/modelines.html
672 *
673 * Local Variables:
674 * c-basic-offset: 4
675 * tab-width: 8
676 * indent-tabs-mode: nil
677 * End:
678 *
679 * ex: set shiftwidth=4 tabstop=8 expandtab:
680 * :indentSize=4:tabSize=8:noTabs=true:
681 */