PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 32-bit 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  * Elsewhere, beware of multiple evaluations of the arguments!
10  *
11  * Note that the GCC built-in functions __builtin_bswap32() and
12  * __builtin_bswap64() are documented as accepting single arguments of type
13  * uint32_t and uint64_t respectively (these are also the respective return
14  * types). Use caution when using these wrapper macros with signed integers.
15  *
16  * Copyright (c) 2015-2017, PostgreSQL Global Development Group
17  *
18  * src/include/port/pg_bswap.h
19  *
20  *-------------------------------------------------------------------------
21  */
22 #ifndef PG_BSWAP_H
23 #define PG_BSWAP_H
24 
25 #ifdef HAVE__BUILTIN_BSWAP32
26 #define BSWAP32(x) __builtin_bswap32(x)
27 #else
28 #define BSWAP32(x) ((((x) << 24) & 0xff000000) | \
29  (((x) << 8) & 0x00ff0000) | \
30  (((x) >> 8) & 0x0000ff00) | \
31  (((x) >> 24) & 0x000000ff))
32 #endif /* HAVE__BUILTIN_BSWAP32 */
33 
34 #ifdef HAVE__BUILTIN_BSWAP64
35 #define BSWAP64(x) __builtin_bswap64(x)
36 #else
37 #define BSWAP64(x) ((((x) << 56) & UINT64CONST(0xff00000000000000)) | \
38  (((x) << 40) & UINT64CONST(0x00ff000000000000)) | \
39  (((x) << 24) & UINT64CONST(0x0000ff0000000000)) | \
40  (((x) << 8) & UINT64CONST(0x000000ff00000000)) | \
41  (((x) >> 8) & UINT64CONST(0x00000000ff000000)) | \
42  (((x) >> 24) & UINT64CONST(0x0000000000ff0000)) | \
43  (((x) >> 40) & UINT64CONST(0x000000000000ff00)) | \
44  (((x) >> 56) & UINT64CONST(0x00000000000000ff)))
45 #endif /* HAVE__BUILTIN_BSWAP64 */
46 
47 /*
48  * Rearrange the bytes of a Datum from big-endian order into the native byte
49  * order. On big-endian machines, this does nothing at all. Note that the C
50  * type Datum is an unsigned integer type on all platforms.
51  *
52  * One possible application of the DatumBigEndianToNative() macro is to make
53  * bitwise comparisons cheaper. A simple 3-way comparison of Datums
54  * transformed by the macro (based on native, unsigned comparisons) will return
55  * the same result as a memcmp() of the corresponding original Datums, but can
56  * be much cheaper. It's generally safe to do this on big-endian systems
57  * without any special transformation occurring first.
58  */
59 #ifdef WORDS_BIGENDIAN
60 #define DatumBigEndianToNative(x) (x)
61 #else /* !WORDS_BIGENDIAN */
62 #if SIZEOF_DATUM == 8
63 #define DatumBigEndianToNative(x) BSWAP64(x)
64 #else /* SIZEOF_DATUM != 8 */
65 #define DatumBigEndianToNative(x) BSWAP32(x)
66 #endif /* SIZEOF_DATUM == 8 */
67 #endif /* WORDS_BIGENDIAN */
68 
69 #endif /* PG_BSWAP_H */