General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

79 line
1.5 KiB

4 年之前
4 年之前
4 年之前
4 年之前
4 年之前
4 年之前
4 年之前
  1. #pragma once
  2. #include "gp/containers/array.hpp"
  3. #include <stddef.h>
  4. #include <stdint.h>
  5. namespace gp{
  6. namespace _impl{
  7. constexpr uint32_t uint32_ = 0x01020304;
  8. constexpr uint8_t magic_ = (const uint8_t&)uint32_;
  9. }
  10. #pragma clang diagnostic push
  11. #pragma clang diagnostic ignored "-Wfour-char-constants"
  12. #pragma GCC diagnostic push
  13. #pragma GCC diagnostic ignored "-Wmultichar"
  14. enum class endian : uint16_t
  15. {
  16. #ifdef _WIN32
  17. little = 0,
  18. big = 1,
  19. native = little
  20. #elseif defined(__BYTE_ORDER__)
  21. little = __ORDER_LITTLE_ENDIAN__,
  22. big = __ORDER_BIG_ENDIAN__,
  23. native = __BYTE_ORDER__
  24. #else
  25. little = true,
  26. big = false,
  27. native = ('ABCD'==0x41424344UL)
  28. };
  29. #endif
  30. #pragma GCC diagnostic pop
  31. #pragma clang diagnostic pop
  32. template <typename T>
  33. T swap_endian(T value)
  34. {
  35. union
  36. {
  37. T v;
  38. uint8_t u8[sizeof(T)];
  39. } src, dest;
  40. src.v = value;
  41. for (size_t idx = 0;idx<sizeof(T);idx++)
  42. {
  43. dest.u8[idx] = src.u8[sizeof(T)-idx-1];
  44. }
  45. return dest.v;
  46. }
  47. template<typename T, endian mode = endian::big>
  48. struct endian_wrapper {
  49. union{
  50. T value;
  51. gp::array<uint8_t, sizeof(T)> bytes;
  52. };
  53. endian_wrapper(){};
  54. endian_wrapper(T v) : value{
  55. mode == endian::native ? v : swap_endian(v)
  56. }{}
  57. endian_wrapper(endian_wrapper& v) : value{
  58. v.value
  59. }{}
  60. endian_wrapper& operator=(T p) {
  61. value = mode == endian::native ? p : swap_endian(p);
  62. return *this;
  63. }
  64. operator T(){
  65. return mode == endian::native ? value : swap_endian(value);
  66. }
  67. };
  68. }