diff options
Diffstat (limited to 'src/common/utils2.hpp')
-rw-r--r-- | src/common/utils2.hpp | 230 |
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 |