#error GCC required
#endif
+#include "folly/folly-config.h"
#include "folly/detail/BitsDetail.h"
#include "folly/detail/BitIteratorDetail.h"
#include "folly/Likely.h"
-#include <byteswap.h>
+#if FOLLY_HAVE_BYTESWAP_H
+# include <byteswap.h>
+#endif
+
#include <cassert>
#include <cinttypes>
#include <endian.h>
static T swap(T x);
};
+/**
+ * If we have the bswap_16 macro from byteswap.h, use it; otherwise, provide our
+ * own definition.
+ */
+#ifdef bswap_16
+# define our_bswap16 bswap_16
+#else
+
+template<class Int16>
+inline constexpr typename std::enable_if<
+ sizeof(Int16) == 2,
+ Int16>::type
+our_bswap16(Int16 x) {
+ return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
+}
+#endif
+
#define FB_GEN(t, fn) \
template<> inline t EndianIntBase<t>::swap(t x) { return fn(x); }
// fn(x) expands to (x) if the second argument is empty, which is exactly
-// what we want for [u]int8_t
+// what we want for [u]int8_t. Also, gcc 4.7 on Intel doesn't have
+// __builtin_bswap16 for some reason, so we have to provide our own.
FB_GEN( int8_t,)
FB_GEN(uint8_t,)
-FB_GEN( int64_t, bswap_64)
-FB_GEN(uint64_t, bswap_64)
-FB_GEN( int32_t, bswap_32)
-FB_GEN(uint32_t, bswap_32)
-FB_GEN( int16_t, bswap_16)
-FB_GEN(uint16_t, bswap_16)
+FB_GEN( int64_t, __builtin_bswap64)
+FB_GEN(uint64_t, __builtin_bswap64)
+FB_GEN( int32_t, __builtin_bswap32)
+FB_GEN(uint32_t, __builtin_bswap32)
+FB_GEN( int16_t, our_bswap16)
+FB_GEN(uint16_t, our_bswap16)
#undef FB_GEN
# Checks for header files.
AC_HEADER_STDC
-AC_CHECK_HEADERS([fcntl.h inttypes.h limits.h stdint.h stdlib.h string.h sys/time.h unistd.h mutex.h malloc.h emmintrin.h])
+AC_CHECK_HEADERS([fcntl.h inttypes.h limits.h stdint.h stdlib.h string.h sys/time.h unistd.h mutex.h malloc.h emmintrin.h byteswap.h])
AC_CHECK_HEADER(double-conversion.h, [], [AC_MSG_ERROR(
[Couldn't find double-conversion.h, please download from \
TEST(Endian, Basic) {
uint8_t v8 = 0x12;
- uint8_t v8s = v8;
+ uint8_t v8s = 0x12;
uint16_t v16 = 0x1234;
- uint16_t v16s = bswap_16(v16);
+ uint16_t v16s = 0x3412;
uint32_t v32 = 0x12345678;
- uint32_t v32s = bswap_32(v32);
+ uint32_t v32s = 0x78563412;
uint64_t v64 = 0x123456789abcdef0ULL;
- uint64_t v64s = bswap_64(v64);
+ uint64_t v64s = 0xf0debc9a78563412ULL;
#if __BYTE_ORDER == __LITTLE_ENDIAN