pg_bswap.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  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-2016, 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. #ifdef HAVE__BUILTIN_BSWAP32
  25. #define BSWAP32(x) __builtin_bswap32(x)
  26. #else
  27. #define BSWAP32(x) ((((x) << 24) & 0xff000000) | \
  28. (((x) << 8) & 0x00ff0000) | \
  29. (((x) >> 8) & 0x0000ff00) | \
  30. (((x) >> 24) & 0x000000ff))
  31. #endif /* HAVE__BUILTIN_BSWAP32 */
  32. #ifdef HAVE__BUILTIN_BSWAP64
  33. #define BSWAP64(x) __builtin_bswap64(x)
  34. #else
  35. #define BSWAP64(x) ((((x) << 56) & UINT64CONST(0xff00000000000000)) | \
  36. (((x) << 40) & UINT64CONST(0x00ff000000000000)) | \
  37. (((x) << 24) & UINT64CONST(0x0000ff0000000000)) | \
  38. (((x) << 8) & UINT64CONST(0x000000ff00000000)) | \
  39. (((x) >> 8) & UINT64CONST(0x00000000ff000000)) | \
  40. (((x) >> 24) & UINT64CONST(0x0000000000ff0000)) | \
  41. (((x) >> 40) & UINT64CONST(0x000000000000ff00)) | \
  42. (((x) >> 56) & UINT64CONST(0x00000000000000ff)))
  43. #endif /* HAVE__BUILTIN_BSWAP64 */
  44. /*
  45. * Rearrange the bytes of a Datum from big-endian order into the native byte
  46. * order. On big-endian machines, this does nothing at all. Note that the C
  47. * type Datum is an unsigned integer type on all platforms.
  48. *
  49. * One possible application of the DatumBigEndianToNative() macro is to make
  50. * bitwise comparisons cheaper. A simple 3-way comparison of Datums
  51. * transformed by the macro (based on native, unsigned comparisons) will return
  52. * the same result as a memcmp() of the corresponding original Datums, but can
  53. * be much cheaper. It's generally safe to do this on big-endian systems
  54. * without any special transformation occurring first.
  55. */
  56. #ifdef WORDS_BIGENDIAN
  57. #define DatumBigEndianToNative(x) (x)
  58. #else /* !WORDS_BIGENDIAN */
  59. #if SIZEOF_DATUM == 8
  60. #define DatumBigEndianToNative(x) BSWAP64(x)
  61. #else /* SIZEOF_DATUM != 8 */
  62. #define DatumBigEndianToNative(x) BSWAP32(x)
  63. #endif /* SIZEOF_DATUM == 8 */
  64. #endif /* WORDS_BIGENDIAN */
  65. #endif /* PG_BSWAP_H */