aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZyX <kp-pav@yandex.ru>2015-04-26 03:36:06 +0300
committerZyX <kp-pav@yandex.ru>2015-10-08 21:59:51 +0300
commit38c688d7be52439ae5d610ff6deb22a0bff732e7 (patch)
treebcbf34e4257c34c1ef01e59f7eb550ab4a78568f
parent244dbe3a77bf548f73d8781da7327f30e818b08a (diff)
downloadrneovim-38c688d7be52439ae5d610ff6deb22a0bff732e7.tar.gz
rneovim-38c688d7be52439ae5d610ff6deb22a0bff732e7.tar.bz2
rneovim-38c688d7be52439ae5d610ff6deb22a0bff732e7.zip
shada: Use glibc functions to convert from big endian, add a fallback
-rw-r--r--src/nvim/shada.c73
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;
}