summaryrefslogtreecommitdiff
path: root/src/common/utils2.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/utils2.hpp')
-rw-r--r--src/common/utils2.hpp230
1 files changed, 230 insertions, 0 deletions
diff --git a/src/common/utils2.hpp b/src/common/utils2.hpp
new file mode 100644
index 0000000..5f02beb
--- /dev/null
+++ b/src/common/utils2.hpp
@@ -0,0 +1,230 @@
+#ifndef UTILS2_HPP
+#define UTILS2_HPP
+
+#include "sanity.hpp"
+
+#include <functional>
+#include <iterator>
+#include <memory>
+#include <type_traits>
+
+#ifdef __clang__
+# define FALLTHROUGH [[clang::fallthrough]]
+#else
+# define FALLTHROUGH /* fallthrough */
+#endif
+
+template<class T, class E, E max>
+struct earray
+{
+ // no ctor/dtor and one public member variable for easy initialization
+ T _data[size_t(max)];
+
+ T& operator[](E v)
+ {
+ return _data[size_t(v)];
+ }
+
+ const T& operator[](E v) const
+ {
+ return _data[size_t(v)];
+ }
+
+ T *begin()
+ {
+ return _data;
+ }
+
+ T *end()
+ {
+ return _data + size_t(max);
+ }
+};
+
+template<class T, class E>
+class eptr
+{
+ T *_data;
+public:
+ eptr(decltype(nullptr)=nullptr)
+ : _data(nullptr)
+ {}
+
+ template<E max>
+ eptr(earray<T, E, max>& arr)
+ : _data(arr._data)
+ {}
+
+ T& operator [](E v)
+ {
+ return _data[size_t(v)];
+ }
+
+ explicit operator bool()
+ {
+ return _data;
+ }
+
+ bool operator not()
+ {
+ return not _data;
+ }
+};
+
+template<class It>
+class IteratorPair
+{
+ It _b, _e;
+public:
+ IteratorPair(It b, It e)
+ : _b(b), _e(e)
+ {}
+
+ It begin() { return _b; }
+ It end() { return _e; }
+};
+
+template<class It>
+IteratorPair<It> iterator_pair(It b, It e)
+{
+ return {b, e};
+}
+
+// std::underlying_type isn't supported until gcc 4.7
+// this is a poor man's emulation
+template<class E>
+struct underlying_type
+{
+ static_assert(std::is_enum<E>::value, "Only enums have underlying type!");
+ typedef typename std::conditional<
+ std::is_signed<E>::value,
+ typename std::make_signed<E>::type,
+ typename std::make_unsigned<E>::type
+ >::type type;
+};
+
+template<class E, bool=std::is_enum<E>::value>
+struct remove_enum
+{
+ typedef E type;
+};
+template<class E>
+struct remove_enum<E, true>
+{
+ typedef typename underlying_type<E>::type type;
+};
+
+
+#define ENUM_BITWISE_OPERATORS(E) \
+inline \
+E operator & (E l, E r) \
+{ \
+ typedef underlying_type<E>::type U; \
+ return E(U(l) & U(r)); \
+} \
+inline \
+E operator | (E l, E r) \
+{ \
+ typedef underlying_type<E>::type U; \
+ return E(U(l) | U(r)); \
+} \
+inline \
+E operator ^ (E l, E r) \
+{ \
+ typedef underlying_type<E>::type U; \
+ return E(U(l) ^ U(r)); \
+} \
+inline \
+E& operator &= (E& l, E r) \
+{ \
+ return l = l & r; \
+} \
+inline \
+E& operator |= (E& l, E r) \
+{ \
+ return l = l | r; \
+} \
+inline \
+E& operator ^= (E& l, E r) \
+{ \
+ return l = l ^ r; \
+} \
+inline \
+E operator ~ (E r) \
+{ \
+ return E(-1) ^ r; \
+}
+
+template<class E>
+class EnumValueIterator
+{
+ typedef typename underlying_type<E>::type U;
+ E value;
+public:
+ EnumValueIterator(E v)
+ : value(v)
+ {}
+
+ E operator *()
+ {
+ return value;
+ }
+ EnumValueIterator& operator++ ()
+ {
+ value = E(U(value) + 1);
+ return *this;
+ }
+ EnumValueIterator& operator-- ()
+ {
+ value = E(U(value) - 1);
+ return *this;
+ }
+ friend bool operator == (EnumValueIterator l, EnumValueIterator r)
+ {
+ return l.value == r.value;
+ }
+ friend bool operator != (EnumValueIterator l, EnumValueIterator r)
+ {
+ return !(l == r);
+ }
+};
+
+template<class E>
+IteratorPair<EnumValueIterator<E>> erange(E b, E e)
+{
+ return {b, e};
+}
+
+namespace ph = std::placeholders;
+
+template<class A, class B>
+typename std::common_type<A, B>::type min(A a, B b)
+{
+ return a < b ? a : b;
+}
+
+template<class A, class B>
+typename std::common_type<A, B>::type max(A a, B b)
+{
+ return b < a ? a : b;
+}
+
+template<class T>
+struct is_array_of_unknown_bound
+: std::is_same<T, typename std::remove_extent<T>::type[]>
+{};
+
+template<class T, class... A>
+typename std::enable_if<!is_array_of_unknown_bound<T>::value, std::unique_ptr<T>>::type make_unique(A&&... a)
+{
+ return std::unique_ptr<T>(new T(a...));
+}
+
+template<class T>
+typename std::enable_if<is_array_of_unknown_bound<T>::value, std::unique_ptr<T>>::type make_unique(size_t sz)
+{
+ typedef typename std::remove_extent<T>::type E;
+ return std::unique_ptr<E[]>(new E[sz]);
+}
+
+#endif // UTILS2_HPP