diff options
-rw-r--r-- | src/nvim/shada.c | 73 |
1 files changed, 66 insertions, 7 deletions
diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 73aaa311b4..881e613114 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -5,6 +5,15 @@ #include <inttypes.h> #include <errno.h> #include <assert.h> +#if defined (__GLIBC__) +# ifndef _BSD_SOURCE +# define _BSD_SOURCE 1 +# endif +# ifndef _DEFAULT_SOURCE +# define _DEFAULT_SOURCE 1 +# endif +# include <endian.h> +#endif #include <msgpack.h> @@ -45,6 +54,43 @@ #define home_replace_save(a, b) \ ((char *)home_replace_save(a, (char_u *)b)) +// From http://www.boost.org/doc/libs/1_43_0/boost/detail/endian.hpp + some +// additional checks done after examining `{compiler} -dM -E - < /dev/null` +// output. +#if defined (__GLIBC__) +# if (__BYTE_ORDER == __BIG_ENDIAN) +# define SHADA_BIG_ENDIAN +# endif +#elif defined(_BIG_ENDIAN) || defined(_LITTLE_ENDIAN) +# if defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) +# define SHADA_BIG_ENDIAN +# endif +// clang-specific +#elif defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__) +# if defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) +# define SHADA_BIG_ENDIAN +# endif +// pcc-, gcc- and clang-specific +#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) +# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define SHADA_BIG_ENDIAN +# endif +#elif defined(__sparc) || defined(__sparc__) \ + || defined(_POWER) || defined(__powerpc__) \ + || defined(__ppc__) || defined(__hpux) || defined(__hppa) \ + || defined(_MIPSEB) || defined(_POWER) \ + || defined(__s390__) +# define SHADA_BIG_ENDIAN +#elif defined(__i386__) || defined(__alpha__) \ + || defined(__ia64) || defined(__ia64__) \ + || defined(_M_IX86) || defined(_M_IA64) \ + || defined(_M_ALPHA) || defined(__amd64) \ + || defined(__amd64__) || defined(_M_AMD64) \ + || defined(__x86_64) || defined(__x86_64__) \ + || defined(_M_X64) || defined(__bfin__) +// Define nothing +#endif + /// Possible ShaDa entry types /// /// @warning Enum values are part of the API and must not be altered. @@ -1027,6 +1073,22 @@ static void shada_free_shada_entry(ShadaEntry *const entry) } } +#ifndef __GLIBC__ +static inline uint64_t be64toh(uint64_t big_endian_64_bits) +{ +#ifdef SHADA_BIG_ENDIAN + return big_endian_64_bits; +#else + uint8_t *buf = &big_endian_64_bits; + uint64_t ret = 0; + for (size_t i = 8; i; i--) { + ret |= ((uint64_t) buf[i - 1]) << ((8 - i) * 8); + } + return ret; +#endif +} +#endif + /// Read next unsigned integer from file /// /// Errors out if the result is not an unsigned integer. @@ -1088,8 +1150,9 @@ static int msgpack_read_uint64(FILE *const fp, const int first_char, return FAIL; } } - uint8_t buf[8]; - size_t read_bytes = fread((char *) &(buf[0]), 1, length, fp); + uint8_t buf[sizeof(uint64_t)] = {0, 0, 0, 0, 0, 0, 0, 0}; + size_t read_bytes = fread((char *) &(buf[sizeof(uint64_t)-length]), 1, + length, fp); if (ferror(fp)) { emsg2("System error while reading ShaDa file: %s", strerror(errno)); @@ -1100,11 +1163,7 @@ static int msgpack_read_uint64(FILE *const fp, const int first_char, (int64_t) fpos); return FAIL; } - // TODO(ZyX-I): Just cast if current platform is big-endian. - *result = 0; - for (size_t i = length; i; i--) { - *result |= ((uint64_t) buf[i - 1]) << ((length - i) * 8); - } + *result = be64toh(*((uint64_t *) &(buf[0]))); } return OK; } |