summaryrefslogtreecommitdiff
path: root/include/libHX/endian.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/libHX/endian.h')
-rw-r--r--include/libHX/endian.h202
1 files changed, 202 insertions, 0 deletions
diff --git a/include/libHX/endian.h b/include/libHX/endian.h
new file mode 100644
index 0000000..b1a4b6a
--- /dev/null
+++ b/include/libHX/endian.h
@@ -0,0 +1,202 @@
+#ifndef _LIBHX_ENDIAN_H
+#define _LIBHX_ENDIAN_H 1
+/*
+ * See <https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html>.
+ *
+ * be16p_to_cpu not optimized on LE before gcc-10.
+ * le16p_to_cpu not optimized away on LE before gcc-10.
+ * cpu_to_be{16,32,64}p not optimized on LE before gcc-8.
+ * cpu_to_le{16,32,64}p not optimized away on LE before gcc-8.
+ * cpu_to_le{16,32,64} not optimized away on LE before gcc-8.
+ * cpu_to_be16 not optimized on LE before gcc-9.
+ * cpu_to_be{32,64} not optimized on LE before gcc-8.
+ * be64_to_cpu not optimized on LE before gcc-10.
+ */
+#include <stdint.h>
+#ifndef LIBHX_DBG_INLINE
+# define LIBHX_DBG_INLINE static inline
+#endif
+#if !defined(LIBHX_OPT_O2) && defined(__GNUC__) && !defined(__clang__) && !defined(__llvm__)
+# define LIBHX_OPT_O2 __attribute__((optimize("-O2")))
+#else
+# define LIBHX_OPT_O2
+#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBHX_DBG_INLINE uint16_t LIBHX_OPT_O2 be16p_to_cpu(const void *p)
+{
+ const uint8_t *q = (const uint8_t *)p;
+ typedef uint16_t T;
+ return (T)q[1] | ((T)q[0] << 8);
+}
+
+LIBHX_DBG_INLINE uint16_t LIBHX_OPT_O2 le16p_to_cpu(const void *p)
+{
+ const uint8_t *q = (const uint8_t *)p;
+ typedef uint16_t T;
+ return (T)q[0] | ((T)q[1] << 8);
+}
+
+LIBHX_DBG_INLINE uint32_t LIBHX_OPT_O2 be32p_to_cpu(const void *p)
+{
+ const uint8_t *q = (const uint8_t *)p;
+ typedef uint32_t T;
+ return (T)q[3] | ((T)q[2] << 8) | ((T)q[1] << 16) | ((T)q[0] << 24);
+}
+
+LIBHX_DBG_INLINE uint32_t LIBHX_OPT_O2 le32p_to_cpu(const void *p)
+{
+ const uint8_t *q = (const uint8_t *)p;
+ typedef uint32_t T;
+ return (T)q[0] | ((T)q[1] << 8) | ((T)q[2] << 16) | ((T)q[3] << 24);
+}
+
+LIBHX_DBG_INLINE uint64_t LIBHX_OPT_O2 be64p_to_cpu(const void *p)
+{
+ const uint8_t *q = (const uint8_t *)p;
+ typedef uint64_t T;
+ return (T)q[7] | ((T)q[6] << 8) | ((T)q[5] << 16) | ((T)q[4] << 24) | ((T)q[3] << 32) |
+ ((T)q[2] << 40) | ((T)q[1] << 48) | ((T)q[0] << 56);
+}
+
+LIBHX_DBG_INLINE uint64_t LIBHX_OPT_O2 le64p_to_cpu(const void *p)
+{
+ const uint8_t *q = (const uint8_t *)p;
+ typedef uint64_t T;
+ return (T)q[0] | ((T)q[1] << 8) | ((T)q[2] << 16) | ((T)q[3] << 24) | ((T)q[4] << 32) |
+ ((T)q[5] << 40) | ((T)q[6] << 48) | ((T)q[7] << 56);
+}
+
+LIBHX_DBG_INLINE void LIBHX_OPT_O2 cpu_to_be16p(void *p, uint16_t v)
+{
+ uint8_t *q = (uint8_t *)p;
+ q[1] = v;
+ q[0] = v >> 8;
+}
+
+LIBHX_DBG_INLINE void LIBHX_OPT_O2 cpu_to_le16p(void *p, uint16_t v)
+{
+ uint8_t *q = (uint8_t *)p;
+ q[0] = v;
+ q[1] = v >> 8;
+}
+
+LIBHX_DBG_INLINE void LIBHX_OPT_O2 cpu_to_be32p(void *p, uint32_t v)
+{
+ uint8_t *q = (uint8_t *)p;
+ q[3] = v;
+ q[2] = v >> 8;
+ q[1] = v >> 16;
+ q[0] = v >> 24;
+}
+
+LIBHX_DBG_INLINE void LIBHX_OPT_O2 cpu_to_le32p(void *p, uint32_t v)
+{
+ uint8_t *q = (uint8_t *)p;
+ q[0] = v;
+ q[1] = v >> 8;
+ q[2] = v >> 16;
+ q[3] = v >> 24;
+}
+
+LIBHX_DBG_INLINE void LIBHX_OPT_O2 cpu_to_be64p(void *p, uint64_t v)
+{
+ uint8_t *q = (uint8_t *)p;
+ q[7] = v;
+ q[6] = v >> 8;
+ q[5] = v >> 16;
+ q[4] = v >> 24;
+ q[3] = v >> 32;
+ q[2] = v >> 40;
+ q[1] = v >> 48;
+ q[0] = v >> 56;
+}
+
+LIBHX_DBG_INLINE void LIBHX_OPT_O2 cpu_to_le64p(void *p, uint64_t v)
+{
+ uint8_t *q = (uint8_t *)p;
+ q[0] = v;
+ q[1] = v >> 8;
+ q[2] = v >> 16;
+ q[3] = v >> 24;
+ q[4] = v >> 32;
+ q[5] = v >> 40;
+ q[6] = v >> 48;
+ q[7] = v >> 56;
+}
+
+/* This is in essence the same as htons/htonl/htonll/htonq */
+/* [Do we need to worry about trap representations?] */
+LIBHX_DBG_INLINE uint16_t LIBHX_OPT_O2 be16_to_cpu(uint16_t v)
+{
+ return be16p_to_cpu(&v);
+}
+
+LIBHX_DBG_INLINE uint32_t LIBHX_OPT_O2 be32_to_cpu(uint32_t v)
+{
+ return be32p_to_cpu(&v);
+}
+
+LIBHX_DBG_INLINE uint64_t LIBHX_OPT_O2 be64_to_cpu(uint64_t v)
+{
+ return be64p_to_cpu(&v);
+}
+
+LIBHX_DBG_INLINE uint16_t LIBHX_OPT_O2 le16_to_cpu(uint16_t v)
+{
+ return le16p_to_cpu(&v);
+}
+
+LIBHX_DBG_INLINE uint32_t LIBHX_OPT_O2 le32_to_cpu(uint32_t v)
+{
+ return le32p_to_cpu(&v);
+}
+
+LIBHX_DBG_INLINE uint64_t LIBHX_OPT_O2 le64_to_cpu(uint64_t v)
+{
+ return le64p_to_cpu(&v);
+}
+
+LIBHX_DBG_INLINE uint16_t LIBHX_OPT_O2 cpu_to_be16(uint16_t v)
+{
+ cpu_to_be16p(&v, v);
+ return v;
+}
+
+LIBHX_DBG_INLINE uint32_t LIBHX_OPT_O2 cpu_to_be32(uint32_t v)
+{
+ cpu_to_be32p(&v, v);
+ return v;
+}
+
+LIBHX_DBG_INLINE uint64_t LIBHX_OPT_O2 cpu_to_be64(uint64_t v)
+{
+ cpu_to_be64p(&v, v);
+ return v;
+}
+
+LIBHX_DBG_INLINE uint16_t LIBHX_OPT_O2 cpu_to_le16(uint16_t v)
+{
+ cpu_to_le16p(&v, v);
+ return v;
+}
+
+LIBHX_DBG_INLINE uint32_t LIBHX_OPT_O2 cpu_to_le32(uint32_t v)
+{
+ cpu_to_le32p(&v, v);
+ return v;
+}
+
+LIBHX_DBG_INLINE uint64_t LIBHX_OPT_O2 cpu_to_le64(uint64_t v)
+{
+ cpu_to_le64p(&v, v);
+ return v;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBHX_ENDIAN_H */