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.

86 lines
1.5 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. #pragma once
  2. #include "gp/containers/array.hpp"
  3. #include <bit>
  4. #include <stddef.h>
  5. #include <stdint.h>
  6. namespace gp {
  7. using endian = std::endian;
  8. template <typename T>
  9. T swap_endian(T value) noexcept {
  10. union {
  11. T v;
  12. uint8_t u8[sizeof(T)];
  13. } src, dest;
  14. src.v = value;
  15. for (size_t idx = 0;idx<sizeof(T);idx++) {
  16. dest.u8[idx] = src.u8[sizeof(T)-idx-1];
  17. }
  18. return dest.v;
  19. }
  20. template<typename T, endian mode = endian::big>
  21. struct endian_wrapper {
  22. T value = 0;
  23. constexpr endian_wrapper() noexcept = default;
  24. endian_wrapper(T v) noexcept
  25. : value{adjust(v)} {}
  26. endian_wrapper& operator=(T v) noexcept {
  27. value = adjust(v);
  28. return *this;
  29. }
  30. operator T() const noexcept {
  31. return adjust(value);
  32. }
  33. auto bytes() const noexcept -> gp::array<uint8_t, sizeof(T)> {
  34. union {
  35. T t;
  36. gp::array<uint8_t, sizeof(T)> bytes;
  37. } tmp {.t = value};
  38. return tmp.bytes;
  39. }
  40. // arithmetic assignment operators
  41. endian_wrapper& operator+=(T rhs) noexcept {
  42. value = adjust(adjust(value) + rhs);
  43. return *this;
  44. }
  45. endian_wrapper& operator+=(endian_wrapper rhs) noexcept {
  46. value = adjust(adjust(value) + adjust(rhs.value));
  47. return *this;
  48. }
  49. endian_wrapper& operator-=(T rhs) noexcept {
  50. value = adjust(adjust(value) - rhs);
  51. return *this;
  52. }
  53. endian_wrapper& operator-=(endian_wrapper rhs) noexcept {
  54. value = adjust(adjust(value) - adjust(rhs.value));
  55. return *this;
  56. }
  57. private:
  58. T adjust(T x) const noexcept {
  59. return (mode == endian::native ? x : swap_endian(x));
  60. }
  61. };
  62. }