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-2019, 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
42pg_bswap16(uint16 x)
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
64pg_bswap32(uint32 x)
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
89pg_bswap64(uint64 x)
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#ifdef WORDS_BIGENDIAN
144#define DatumBigEndianToNative(x) (x)
145#else /* !WORDS_BIGENDIAN */
146#if SIZEOF_DATUM == 8
147#define DatumBigEndianToNative(x) pg_bswap64(x)
148#else /* SIZEOF_DATUM != 8 */
149#define DatumBigEndianToNative(x) pg_bswap32(x)
150#endif /* SIZEOF_DATUM == 8 */
151#endif /* WORDS_BIGENDIAN */
152
153#endif /* PG_BSWAP_H */
154