summaryrefslogtreecommitdiff
path: root/include/libHX
diff options
context:
space:
mode:
Diffstat (limited to 'include/libHX')
-rw-r--r--include/libHX/ctype_helper.h5
-rw-r--r--include/libHX/defs.h12
-rw-r--r--include/libHX/endian.h202
-rw-r--r--include/libHX/scope.hpp35
4 files changed, 253 insertions, 1 deletions
diff --git a/include/libHX/ctype_helper.h b/include/libHX/ctype_helper.h
index 2ba0a7a..0f42c4f 100644
--- a/include/libHX/ctype_helper.h
+++ b/include/libHX/ctype_helper.h
@@ -39,6 +39,11 @@ static __inline__ bool HX_isalpha(unsigned char c)
return isalpha(c);
}
+static __inline__ bool HX_isascii(unsigned char c)
+{
+ return isascii(c);
+}
+
static __inline__ bool HX_isdigit(unsigned char c)
{
return isdigit(c);
diff --git a/include/libHX/defs.h b/include/libHX/defs.h
index ba84b37..2ef5769 100644
--- a/include/libHX/defs.h
+++ b/include/libHX/defs.h
@@ -12,7 +12,16 @@
# ifndef containerof
# include <cstddef>
# include <type_traits>
-# define containerof(var, T, member) reinterpret_cast<std::conditional<std::is_const<std::remove_pointer<decltype(var)>::type>::value, std::add_const<T>::type, T>::type *>(reinterpret_cast<std::conditional<std::is_const<std::remove_pointer<decltype(var)>::type>::value, const char, char>::type *>(var) - offsetof(T, member))
+namespace {
+template<typename Dst, typename Src> static inline auto containerof_cxx(Src *var, size_t ofs)
+{
+ using K = typename std::is_const<typename std::remove_pointer<Src>::type>;
+ using Ch = typename std::conditional<K::value, const char, char>::type;
+ using D2 = typename std::conditional<K::value, const Dst, Dst>::type;
+ return reinterpret_cast<D2 *>(reinterpret_cast<Ch *>(var) + ofs);
+}
+}
+# define containerof(var, D1, member) containerof_cxx<D1>(var, -offsetof(D1, member))
# endif
#else
# define HXsizeof_member(type, member) sizeof(((type *)NULL)->member)
@@ -86,6 +95,7 @@
#define HXSIZEOF_Z32 sizeof("-4294967296")
/* 2^64 and -2^63 have same length */
#define HXSIZEOF_Z64 sizeof("18446744073709551616")
+#define HXSIZEOF_UNITSEC64 sizeof("584542046089y11months2weeks2d23h59min59s")
#define __HX_STRINGIFY_EXPAND(s) #s
#define HX_STRINGIFY(s) __HX_STRINGIFY_EXPAND(s)
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 */
diff --git a/include/libHX/scope.hpp b/include/libHX/scope.hpp
new file mode 100644
index 0000000..0c0c70d
--- /dev/null
+++ b/include/libHX/scope.hpp
@@ -0,0 +1,35 @@
+#pragma once
+#include <exception>
+#include <utility>
+
+namespace HX {
+
+/*
+ * Modeled upon the C++ standards proposal P0052r10 / Library Fundamentals v3.
+ * Not yet present in GNU stdlibc++ or clang libc++.
+ */
+template<typename F> class scope_exit {
+ private:
+ F m_func;
+ bool m_eod = false;
+
+ public:
+ explicit scope_exit(F &&f) : m_func(std::move(f)), m_eod(true) {}
+ scope_exit(scope_exit &&o) : m_func(std::move(o.m_func)), m_eod(o.m_eod) {
+ o.m_eod = false;
+ }
+ ~scope_exit() try {
+ if (m_eod)
+ m_func();
+ } catch (...) {
+ }
+ void operator=(scope_exit &&) = delete;
+ void release() noexcept { m_eod = false; }
+};
+
+template<typename F> scope_exit<F> make_scope_exit(F &&f)
+{
+ return scope_exit<F>(std::move(f));
+}
+
+} /* namespace */