PostgreSQL Source Code git master
pg_bswap.h
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pg_bswap.h
4 * Byte swapping.
5 *
6 * Macros for reversing the byte order of 16, 32 and 64-bit unsigned integers.
7 * For example, 0xAABBCCDD becomes 0xDDCCBBAA. These are just wrappers for
8 * built-in functions provided by the compiler where support exists.
9 *
10 * Note that all of these functions accept unsigned integers as arguments and
11 * return the same. Use caution when using these wrapper macros with signed
12 * integers.
13 *
14 * Copyright (c) 2015-2025, PostgreSQL Global Development Group
15 *
16 * src/include/port/pg_bswap.h
17 *
18 *-------------------------------------------------------------------------
19 */
20#ifndef PG_BSWAP_H
21#define PG_BSWAP_H
22
23
24/*
25 * In all supported versions msvc provides _byteswap_* functions in stdlib.h,
26 * already included by c.h.
27 */
28
29
30/* implementation of uint16 pg_bswap16(uint16) */
31#if defined(HAVE__BUILTIN_BSWAP16)
32
33#define pg_bswap16(x) __builtin_bswap16(x)
34
35#elif defined(_MSC_VER)
36
37#define pg_bswap16(x) _byteswap_ushort(x)
38
39#else
40
41static inline uint16
43{
44 return
45 ((x << 8) & 0xff00) |
46 ((x >> 8) & 0x00ff);
47}
48
49#endif /* HAVE__BUILTIN_BSWAP16 */
50
51
52/* implementation of uint32 pg_bswap32(uint32) */
53#if defined(HAVE__BUILTIN_BSWAP32)
54
55#define pg_bswap32(x) __builtin_bswap32(x)
56
57#elif defined(_MSC_VER)
58
59#define pg_bswap32(x) _byteswap_ulong(x)
60
61#else
62
63static inline uint32
65{
66 return
67 ((x << 24) & 0xff000000) |
68 ((x << 8) & 0x00ff0000) |
69 ((x >> 8) & 0x0000ff00) |
70 ((x >> 24) & 0x000000ff);
71}
72
73#endif /* HAVE__BUILTIN_BSWAP32 */
74
75
76/* implementation of uint64 pg_bswap64(uint64) */
77#if defined(HAVE__BUILTIN_BSWAP64)
78
79#define pg_bswap64(x) __builtin_bswap64(x)
80
81
82#elif defined(_MSC_VER)
83
84#define pg_bswap64(x) _byteswap_uint64(x)
85
86#else
87
88static inline uint64
90{
91 return
92 ((x << 56) & UINT64CONST(0xff00000000000000)) |
93 ((x << 40) & UINT64CONST(0x00ff000000000000)) |
94 ((x << 24) & UINT64CONST(0x0000ff0000000000)) |
95 ((x << 8) & UINT64CONST(0x000000ff00000000)) |
96 ((x >> 8) & UINT64CONST(0x00000000ff000000)) |
97 ((x >> 24) & UINT64CONST(0x0000000000ff0000)) |
98 ((x >> 40) & UINT64CONST(0x000000000000ff00)) |
99 ((x >> 56) & UINT64CONST(0x00000000000000ff));
100}
101#endif /* HAVE__BUILTIN_BSWAP64 */
102
103
104/*
105 * Portable and fast equivalents for ntohs, ntohl, htons, htonl,
106 * additionally extended to 64 bits.
107 */
108#ifdef WORDS_BIGENDIAN
109
110#define pg_hton16(x) (x)
111#define pg_hton32(x) (x)
112#define pg_hton64(x) (x)
113
114#define pg_ntoh16(x) (x)
115#define pg_ntoh32(x) (x)
116#define pg_ntoh64(x) (x)
117
118#else
119
120#define pg_hton16(x) pg_bswap16(x)
121#define pg_hton32(x) pg_bswap32(x)
122#define pg_hton64(x) pg_bswap64(x)
123
124#define pg_ntoh16(x) pg_bswap16(x)
125#define pg_ntoh32(x) pg_bswap32(x)
126#define pg_ntoh64(x) pg_bswap64(x)
127
128#endif /* WORDS_BIGENDIAN */
129
130
131/*
132 * Rearrange the bytes of a Datum from big-endian order into the native byte
133 * order. On big-endian machines, this does nothing at all. Note that the C
134 * type Datum is an unsigned integer type on all platforms.
135 *
136 * One possible application of the DatumBigEndianToNative() macro is to make
137 * bitwise comparisons cheaper. A simple 3-way comparison of Datums
138 * transformed by the macro (based on native, unsigned comparisons) will return
139 * the same result as a memcmp() of the corresponding original Datums, but can
140 * be much cheaper. It's generally safe to do this on big-endian systems
141 * without any special transformation occurring first.
142 *
143 * If SIZEOF_DATUM is not defined, then postgres.h wasn't included and these
144 * macros probably shouldn't be used, so we define nothing. Note that
145 * SIZEOF_DATUM == 8 would evaluate as 0 == 8 in that case, potentially
146 * leading to the wrong implementation being selected and confusing errors, so
147 * defining nothing is safest.
148 */
149#ifdef SIZEOF_DATUM
150#ifdef WORDS_BIGENDIAN
151#define DatumBigEndianToNative(x) (x)
152#else /* !WORDS_BIGENDIAN */
153#if SIZEOF_DATUM == 8
154#define DatumBigEndianToNative(x) pg_bswap64(x)
155#else /* SIZEOF_DATUM != 8 */
156#define DatumBigEndianToNative(x) pg_bswap32(x)
157#endif /* SIZEOF_DATUM == 8 */
158#endif /* WORDS_BIGENDIAN */
159#endif /* SIZEOF_DATUM */
160
161#endif /* PG_BSWAP_H */
uint64_t uint64
Definition: c.h:489
uint16_t uint16
Definition: c.h:487
uint32_t uint32
Definition: c.h:488
#define UINT64CONST(x)
Definition: c.h:503
int x
Definition: isn.c:70
static uint16 pg_bswap16(uint16 x)
Definition: pg_bswap.h:42
static uint64 pg_bswap64(uint64 x)
Definition: pg_bswap.h:89
static uint32 pg_bswap32(uint32 x)
Definition: pg_bswap.h:64