Просмотр исходного кода

common/swap: add swap template for enum

Weiyi Wang 7 лет назад
Родитель
Сommit
94bc48dd78
1 измененных файлов с 52 добавлено и 0 удалено
  1. 52 0
      src/common/swap.h

+ 52 - 0
src/common/swap.h

@@ -17,6 +17,8 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <type_traits>
+
 #if defined(_MSC_VER)
 #if defined(_MSC_VER)
 #include <cstdlib>
 #include <cstdlib>
 #elif defined(__linux__)
 #elif defined(__linux__)
@@ -605,6 +607,44 @@ struct swap_double_t {
     }
     }
 };
 };
 
 
+template <typename T>
+struct swap_enum_t {
+    static_assert(std::is_enum_v<T>);
+    using base = std::underlying_type_t<T>;
+
+public:
+    swap_enum_t() = default;
+    swap_enum_t(const T& v) : value(swap(v)) {}
+
+    swap_enum_t& operator=(const T& v) {
+        value = swap(v);
+        return *this;
+    }
+
+    operator T() const {
+        return swap(value);
+    }
+
+    explicit operator base() const {
+        return static_cast<base>(swap(value));
+    }
+
+protected:
+    T value{};
+    // clang-format off
+    using swap_t = std::conditional_t<
+        std::is_same_v<base, u16>, swap_16_t<u16>, std::conditional_t<
+        std::is_same_v<base, s16>, swap_16_t<s16>, std::conditional_t<
+        std::is_same_v<base, u32>, swap_32_t<u32>, std::conditional_t<
+        std::is_same_v<base, s32>, swap_32_t<s32>, std::conditional_t<
+        std::is_same_v<base, u64>, swap_64_t<u64>, std::conditional_t<
+        std::is_same_v<base, s64>, swap_64_t<s64>, void>>>>>>;
+    // clang-format on
+    static T swap(T x) {
+        return static_cast<T>(swap_t::swap(static_cast<base>(x)));
+    }
+};
+
 #if COMMON_LITTLE_ENDIAN
 #if COMMON_LITTLE_ENDIAN
 using u16_le = u16;
 using u16_le = u16;
 using u32_le = u32;
 using u32_le = u32;
@@ -614,6 +654,9 @@ using s16_le = s16;
 using s32_le = s32;
 using s32_le = s32;
 using s64_le = s64;
 using s64_le = s64;
 
 
+template <typename T>
+using enum_le = std::enable_if_t<std::is_enum_v<T>, T>;
+
 using float_le = float;
 using float_le = float;
 using double_le = double;
 using double_le = double;
 
 
@@ -626,6 +669,9 @@ using s32_be = swap_struct_t<s32, swap_32_t<s32>>;
 using u16_be = swap_struct_t<u16, swap_16_t<u16>>;
 using u16_be = swap_struct_t<u16, swap_16_t<u16>>;
 using s16_be = swap_struct_t<s16, swap_16_t<s16>>;
 using s16_be = swap_struct_t<s16, swap_16_t<s16>>;
 
 
+template <typename T>
+using enum_be = swap_enum_t<T>;
+
 using float_be = swap_struct_t<float, swap_float_t<float>>;
 using float_be = swap_struct_t<float, swap_float_t<float>>;
 using double_be = swap_struct_t<double, swap_double_t<double>>;
 using double_be = swap_struct_t<double, swap_double_t<double>>;
 #else
 #else
@@ -639,6 +685,9 @@ using s32_le = swap_struct_t<s32, swap_32_t<s32>>;
 using u16_le = swap_struct_t<u16, swap_16_t<u16>>;
 using u16_le = swap_struct_t<u16, swap_16_t<u16>>;
 using s16_le = swap_struct_t<s16, swap_16_t<s16>>;
 using s16_le = swap_struct_t<s16, swap_16_t<s16>>;
 
 
+template <typename T>
+using enum_le = swap_enum_t<T>;
+
 using float_le = swap_struct_t<float, swap_float_t<float>>;
 using float_le = swap_struct_t<float, swap_float_t<float>>;
 using double_le = swap_struct_t<double, swap_double_t<double>>;
 using double_le = swap_struct_t<double, swap_double_t<double>>;
 
 
@@ -650,6 +699,9 @@ using s16_be = s16;
 using s32_be = s32;
 using s32_be = s32;
 using s64_be = s64;
 using s64_be = s64;
 
 
+template <typename T>
+using enum_be = std::enable_if_t<std::is_enum_v<T>, T>;
+
 using float_be = float;
 using float_be = float;
 using double_be = double;
 using double_be = double;