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
100static inline uint16_t pntohu16(const void *p)
101{
102 uint16_t ret;
103 memcpy(&ret, p, sizeof(ret));
104#if G_BYTE_ORDER == G_LITTLE_ENDIAN
105 ret = pint_bswap16(ret);
106#endif
107 return ret;
108}
109
115static inline uint32_t pntohu32(const void *p)
116{
117 uint32_t ret;
118 memcpy(&ret, p, sizeof(ret));
119#if G_BYTE_ORDER == G_LITTLE_ENDIAN
120 ret = pint_bswap32(ret);
121#endif
122 return ret;
123}
124
130static inline uint64_t pntohu64(const void *p)
131{
132 uint64_t ret;
133 memcpy(&ret, p, sizeof(ret));
134#if G_BYTE_ORDER == G_LITTLE_ENDIAN
135 ret = pint_bswap64(ret);
136#endif
137 return ret;
138}
139
145static inline uint16_t pletohu16(const void *p)
146{
147 uint16_t ret;
148 memcpy(&ret, p, sizeof(ret));
149#if G_BYTE_ORDER == G_BIG_ENDIAN
150 ret = pint_bswap16(ret);
151#endif
152 return ret;
153}
154
160static inline uint32_t pletohu32(const void *p)
161{
162 uint32_t ret;
163 memcpy(&ret, p, sizeof(ret));
164#if G_BYTE_ORDER == G_BIG_ENDIAN
165 ret = pint_bswap32(ret);
166#endif
167 return ret;
168}
169
175static inline uint64_t pletohu64(const void *p)
176{
177 uint64_t ret;
178 memcpy(&ret, p, sizeof(ret));
179#if G_BYTE_ORDER == G_BIG_ENDIAN
180 ret = pint_bswap64(ret);
181#endif
182 return ret;
183}
184
190static inline void phtonu16(uint8_t *p, uint16_t v)
191{
192#if G_BYTE_ORDER == G_LITTLE_ENDIAN
193 v = pint_bswap16(v);
194#endif
195 memcpy(p, &v, sizeof(v));
196}
197
203static inline void phtonu32(uint8_t *p, uint32_t v)
204{
205#if G_BYTE_ORDER == G_LITTLE_ENDIAN
206 v = pint_bswap32(v);
207#endif
208 memcpy(p, &v, sizeof(v));
209}
210
216static inline void phtonu64(uint8_t *p, uint64_t v)
217{
218#if G_BYTE_ORDER == G_LITTLE_ENDIAN
219 v = pint_bswap64(v);
220#endif
221 memcpy(p, &v, sizeof(v));
222}
223
229static inline void phtoleu16(uint8_t *p, uint32_t v)
230{
231#if G_BYTE_ORDER == G_BIG_ENDIAN
232 v = pint_bswap16(v);
233#endif
234 memcpy(p, &v, sizeof(v));
235}
236
242static inline void phtoleu32(uint8_t *p, uint32_t v)
243{
244#if G_BYTE_ORDER == G_BIG_ENDIAN
245 v = pint_bswap32(v);
246#endif
247 memcpy(p, &v, sizeof(v));
248}
249
255static inline void phtoleu64(uint8_t *p, uint64_t v)
256{
257#if G_BYTE_ORDER == G_BIG_ENDIAN
258 v = pint_bswap64(v);
259#endif
260 memcpy(p, &v, sizeof(v));
261}
262
263#else
264/* Portable functions */
265
272static inline uint16_t pntohu16(const void *p)
273{
274 return (uint16_t)*((const uint8_t *)(p)+0)<<8|
275 (uint16_t)*((const uint8_t *)(p)+1)<<0;
276}
277
284static inline uint32_t pntohu32(const void *p)
285{
286 return (uint32_t)*((const uint8_t *)(p)+0)<<24|
287 (uint32_t)*((const uint8_t *)(p)+1)<<16|
288 (uint32_t)*((const uint8_t *)(p)+2)<<8|
289 (uint32_t)*((const uint8_t *)(p)+3)<<0;
290}
291
299static inline uint64_t pntohu64(const void *p)
300{
301 return (uint64_t)*((const uint8_t *)(p)+0)<<56|
302 (uint64_t)*((const uint8_t *)(p)+1)<<48|
303 (uint64_t)*((const uint8_t *)(p)+2)<<40|
304 (uint64_t)*((const uint8_t *)(p)+3)<<32|
305 (uint64_t)*((const uint8_t *)(p)+4)<<24|
306 (uint64_t)*((const uint8_t *)(p)+5)<<16|
307 (uint64_t)*((const uint8_t *)(p)+6)<<8|
308 (uint64_t)*((const uint8_t *)(p)+7)<<0;
309}
310
317static inline uint16_t pletohu16(const void *p)
318{
319 return (uint16_t)*((const uint8_t *)(p)+1)<<8|
320 (uint16_t)*((const uint8_t *)(p)+0)<<0;
321}
322
329static inline uint32_t pletohu32(const void *p)
330{
331 return (uint32_t)*((const uint8_t *)(p)+3)<<24|
332 (uint32_t)*((const uint8_t *)(p)+2)<<16|
333 (uint32_t)*((const uint8_t *)(p)+1)<<8|
334 (uint32_t)*((const uint8_t *)(p)+0)<<0;
335}
336
343static inline uint64_t pletohu64(const void *p)
344{
345 return (uint64_t)*((const uint8_t *)(p)+7)<<56|
346 (uint64_t)*((const uint8_t *)(p)+6)<<48|
347 (uint64_t)*((const uint8_t *)(p)+5)<<40|
348 (uint64_t)*((const uint8_t *)(p)+4)<<32|
349 (uint64_t)*((const uint8_t *)(p)+3)<<24|
350 (uint64_t)*((const uint8_t *)(p)+2)<<16|
351 (uint64_t)*((const uint8_t *)(p)+1)<<8|
352 (uint64_t)*((const uint8_t *)(p)+0)<<0;
353}
354
360static inline void phtonu16(uint8_t *p, uint16_t v)
361{
362 p[0] = (uint8_t)(v >> 8);
363 p[1] = (uint8_t)(v >> 0);
364}
365
372static inline void phtonu32(uint8_t *p, uint32_t v)
373{
374 p[0] = (uint8_t)(v >> 24);
375 p[1] = (uint8_t)(v >> 16);
376 p[2] = (uint8_t)(v >> 8);
377 p[3] = (uint8_t)(v >> 0);
378}
379
386static inline void phtonu64(uint8_t *p, uint64_t v) {
387 p[0] = (uint8_t)(v >> 56);
388 p[1] = (uint8_t)(v >> 48);
389 p[2] = (uint8_t)(v >> 40);
390 p[3] = (uint8_t)(v >> 32);
391 p[4] = (uint8_t)(v >> 24);
392 p[5] = (uint8_t)(v >> 16);
393 p[6] = (uint8_t)(v >> 8);
394 p[7] = (uint8_t)(v >> 0);
395}
396
403static inline void phtoleu16(uint8_t *p, uint16_t v)
404{
405 p[0] = (uint8_t)(v >> 0);
406 p[1] = (uint8_t)(v >> 8);
407}
408
415static inline void phtoleu32(uint8_t *p, uint32_t v) {
416 p[0] = (uint8_t)(v >> 0);
417 p[1] = (uint8_t)(v >> 8);
418 p[2] = (uint8_t)(v >> 16);
419 p[3] = (uint8_t)(v >> 24);
420}
421
428static inline void phtoleu64(uint8_t *p, uint64_t v) {
429 p[0] = (uint8_t)(v >> 0);
430 p[1] = (uint8_t)(v >> 8);
431 p[2] = (uint8_t)(v >> 16);
432 p[3] = (uint8_t)(v >> 24);
433 p[4] = (uint8_t)(v >> 32);
434 p[5] = (uint8_t)(v >> 40);
435 p[6] = (uint8_t)(v >> 48);
436 p[7] = (uint8_t)(v >> 56);
437}
438#endif
439
440/*
441 * Single-byte versions, for completeness.
442*/
443
450static inline uint8_t pntohu8(const void *p)
451{
452 return *((const uint8_t *)(p)+0)<<0;
453}
454
461static inline uint8_t pletohu8(const void *p)
462{
463 return *((const uint8_t *)(p)+0)<<0;
464}
465
472static inline void phtonu8(uint8_t *p, uint8_t v)
473{
474 p[0] = (uint8_t)((v) >> 0);
475}
476
483static inline void phtoleu8(uint8_t *p, uint8_t v)
484{
485 p[0] = (uint8_t)((v) >> 0);
486}
487
497static inline uint32_t pntohu24(const void *p)
498{
499 return (uint32_t)*((const uint8_t *)(p)+0)<<16|
500 (uint32_t)*((const uint8_t *)(p)+1)<<8|
501 (uint32_t)*((const uint8_t *)(p)+2)<<0;
502}
503
513static inline uint64_t pntohu40(const void *p)
514{
515 return (uint64_t)*((const uint8_t *)(p)+0)<<32|
516 (uint64_t)*((const uint8_t *)(p)+1)<<24|
517 (uint64_t)*((const uint8_t *)(p)+2)<<16|
518 (uint64_t)*((const uint8_t *)(p)+3)<<8|
519 (uint64_t)*((const uint8_t *)(p)+4)<<0;
520}
521
528static inline uint64_t pntohu48(const void *p)
529{
530 return (uint64_t)*((const uint8_t *)(p)+0)<<40|
531 (uint64_t)*((const uint8_t *)(p)+1)<<32|
532 (uint64_t)*((const uint8_t *)(p)+2)<<24|
533 (uint64_t)*((const uint8_t *)(p)+3)<<16|
534 (uint64_t)*((const uint8_t *)(p)+4)<<8|
535 (uint64_t)*((const uint8_t *)(p)+5)<<0;
536}
537
544static inline uint64_t pntohu56(const void *p)
545{
546 return (uint64_t)*((const uint8_t *)(p)+0)<<48|
547 (uint64_t)*((const uint8_t *)(p)+1)<<40|
548 (uint64_t)*((const uint8_t *)(p)+2)<<32|
549 (uint64_t)*((const uint8_t *)(p)+3)<<24|
550 (uint64_t)*((const uint8_t *)(p)+4)<<16|
551 (uint64_t)*((const uint8_t *)(p)+5)<<8|
552 (uint64_t)*((const uint8_t *)(p)+6)<<0;
553}
554
561static inline uint32_t pletohu24(const void *p)
562{
563 return (uint32_t)*((const uint8_t *)(p)+2)<<16|
564 (uint32_t)*((const uint8_t *)(p)+1)<<8|
565 (uint32_t)*((const uint8_t *)(p)+0)<<0;
566}
567
574static inline uint64_t pletohu40(const void *p)
575{
576 return (uint64_t)*((const uint8_t *)(p)+4)<<32|
577 (uint64_t)*((const uint8_t *)(p)+3)<<24|
578 (uint64_t)*((const uint8_t *)(p)+2)<<16|
579 (uint64_t)*((const uint8_t *)(p)+1)<<8|
580 (uint64_t)*((const uint8_t *)(p)+0)<<0;
581}
582
589static inline uint64_t pletohu48(const void *p)
590{
591 return (uint64_t)*((const uint8_t *)(p)+5)<<40|
592 (uint64_t)*((const uint8_t *)(p)+4)<<32|
593 (uint64_t)*((const uint8_t *)(p)+3)<<24|
594 (uint64_t)*((const uint8_t *)(p)+2)<<16|
595 (uint64_t)*((const uint8_t *)(p)+1)<<8|
596 (uint64_t)*((const uint8_t *)(p)+0)<<0;
597}
598
606static inline uint64_t pletohu56(const void *p)
607{
608 return (uint64_t)*((const uint8_t *)(p)+6)<<48|
609 (uint64_t)*((const uint8_t *)(p)+5)<<40|
610 (uint64_t)*((const uint8_t *)(p)+4)<<32|
611 (uint64_t)*((const uint8_t *)(p)+3)<<24|
612 (uint64_t)*((const uint8_t *)(p)+2)<<16|
613 (uint64_t)*((const uint8_t *)(p)+1)<<8|
614 (uint64_t)*((const uint8_t *)(p)+0)<<0;
615}
616
624static inline void phtonu24(uint8_t *p, uint32_t v)
625{
626 p[0] = (uint8_t)((v) >> 16);
627 p[1] = (uint8_t)((v) >> 8);
628 p[2] = (uint8_t)((v) >> 0);
629}
630
637static inline void phtonu40(uint8_t *p, uint64_t v)
638{
639 p[0] = (uint8_t)((v) >> 32);
640 p[1] = (uint8_t)((v) >> 24);
641 p[2] = (uint8_t)((v) >> 16);
642 p[3] = (uint8_t)((v) >> 8);
643 p[4] = (uint8_t)((v) >> 0);
644}
645
652static inline void phtonu48(uint8_t *p, uint64_t v)
653{
654 p[0] = (uint8_t)((v) >> 40);
655 p[1] = (uint8_t)((v) >> 32);
656 p[2] = (uint8_t)((v) >> 24);
657 p[3] = (uint8_t)((v) >> 16);
658 p[4] = (uint8_t)((v) >> 8);
659 p[5] = (uint8_t)((v) >> 0);
660}
661
669static inline void phtonu56(uint8_t *p, uint64_t v)
670{
671 p[0] = (uint8_t)((v) >> 48);
672 p[1] = (uint8_t)((v) >> 40);
673 p[2] = (uint8_t)((v) >> 32);
674 p[3] = (uint8_t)((v) >> 24);
675 p[4] = (uint8_t)((v) >> 16);
676 p[5] = (uint8_t)((v) >> 8);
677 p[6] = (uint8_t)((v) >> 0);
678}
679
686static inline void phtoleu24(uint8_t *p, uint32_t v)
687{
688 p[0] = (uint8_t)((v) >> 0);
689 p[1] = (uint8_t)((v) >> 8);
690 p[2] = (uint8_t)((v) >> 16);
691}
692
699static inline void phtoleu40(uint8_t *p, uint64_t v)
700{
701 p[0] = (uint8_t)((v) >> 0);
702 p[1] = (uint8_t)((v) >> 8);
703 p[2] = (uint8_t)((v) >> 16);
704 p[3] = (uint8_t)((v) >> 24);
705 p[4] = (uint8_t)((v) >> 32);
706}
707
714static inline void phtoleu48(uint8_t *p, uint64_t v)
715{
716 p[0] = (uint8_t)((v) >> 0);
717 p[1] = (uint8_t)((v) >> 8);
718 p[2] = (uint8_t)((v) >> 16);
719 p[3] = (uint8_t)((v) >> 24);
720 p[4] = (uint8_t)((v) >> 32);
721 p[5] = (uint8_t)((v) >> 40);
722}
723
730static inline void phtoleu56(uint8_t *p, uint64_t v)
731{
732 p[0] = (uint8_t)((v) >> 0);
733 p[1] = (uint8_t)((v) >> 8);
734 p[2] = (uint8_t)((v) >> 16);
735 p[3] = (uint8_t)((v) >> 24);
736 p[4] = (uint8_t)((v) >> 32);
737 p[5] = (uint8_t)((v) >> 40);
738 p[6] = (uint8_t)((v) >> 48);
739}
740
741#endif /* PINT_H */
742
743/*
744 * Editor modelines - https://www.wireshark.org/tools/modelines.html
745 *
746 * Local Variables:
747 * c-basic-offset: 4
748 * tab-width: 8
749 * indent-tabs-mode: nil
750 * End:
751 *
752 * ex: set shiftwidth=4 tabstop=8 expandtab:
753 * :indentSize=4:tabSize=8:noTabs=true:
754 */