hmbdc
simplify-high-performance-messaging-programming
 All Classes Namespaces Functions Variables Friends Pages
Endian.hpp
1 #include "hmbdc/Copyright.hpp"
2 #pragma once
3 #include <boost/endian/conversion.hpp>
4 #include <iostream>
5 
6 namespace hmbdc {
7 struct Endian {
8 private:
9  static constexpr uint32_t i32 = 0x01020304;
10  static constexpr uint8_t i32_1stbyte = (const uint8_t&)i32;
11  static_assert(i32_1stbyte == 0x04 || i32_1stbyte == 0x01, "Cannot determine endianness!");
12 public:
13  static constexpr bool little = i32_1stbyte == 0x04;
14 #ifdef HMBDC_XMIT_BIG_ENDIAN
15  static constexpr bool match_xmit = !little;
16 #else
17  static constexpr bool match_xmit = little;
18 #endif
19  template <typename iType>
20  static
21  iType toXmit(iType v) {
22  if (match_xmit) {
23  return v;
24  } else {
25  return boost::endian::endian_reverse(v);
26  }
27  }
28  template <typename iType>
29  static
30  iType toNative(iType v) {
31  return toXmit(v);
32  }
33 };
34 
35 template <typename T>
36 struct XmitEndian {
37  using RawType = T;
38  static_assert(sizeof(T) > 1, "not effective or apply");
39  XmitEndian(){}
40  explicit XmitEndian(T v)
41  : vx_(Endian::match_xmit?v:boost::endian::endian_reverse(v)) {
42  }
43 
44  operator T() const {
45  return Endian::match_xmit?vx_:boost::endian::endian_reverse(vx_);
46  }
47 
48  XmitEndian& operator = (T v) {
49  if (Endian::match_xmit) {
50  vx_ = v;
51  } else {
52  vx_ = boost::endian::endian_reverse(v);
53  }
54  return *this;
55  }
56 
57  XmitEndian& operator += (T v) {
58  if (Endian::match_xmit) {
59  vx_ += v;
60  } else {
61  auto tmp = boost::endian::endian_reverse(vx_) + v;
62  vx_ = boost::endian::endian_reverse(tmp);
63  }
64  return *this;
65  }
66 
67 
68  friend std::istream& operator >> (std::istream& is, XmitEndian& t) {
69  T tmp;
70  is >> tmp;
71  t = tmp;
72  return is;
73  }
74 
75 private:
76  T vx_;
77 } __attribute__((packed));
78 
79 template <typename T, size_t N>
81  using RawType = T;
82  static_assert(sizeof(T) >= N, "not effective or apply");
84  explicit XmitEndianByteField(T v) {
85  vx_ = v;
86  if (!Endian::match_xmit) {
87  for (auto i = 0; i < N / 2; ++i)
88  std::swap(vb_[i], vb_[N - i - 1]);
89  }
90  }
91 
92  operator T() const {
93  return Endian::match_xmit?vx_:boost::endian::endian_reverse(
94  vx_ << (sizeof(T) - N) * 8);
95  }
96 
97  XmitEndianByteField& operator = (T v) {
98  vx_ = v;
99  if (!Endian::match_xmit) {
100  for (auto i = 0u; i < N / 2; ++i)
101  std::swap(vb_[i], vb_[N - i - 1]);
102  }
103  return *this;
104  }
105 
106  friend std::istream& operator >> (std::istream& is, XmitEndianByteField& f) {
107  T tmp;
108  is >> tmp;
109  f = tmp;
110  return is;
111  }
112 
113 private:
114  union {
115  uint8_t vb_[N];
116  T vx_ : N*8;
117  } __attribute__((packed));
118 } __attribute__((packed));
119 
120 // template <typename UT, typename T, uint8_t index, uint8_t bits>
121 // struct XmitEndianBitField {
122 // static_assert(sizeof(UT) >= sizeof(T), "UT not big enough");
123 // operator T() const {
124 // return Endian::match_xmit && bits > 8?vx_:boost::endian::endian_reverse(vx_);
125 // }
126 
127 // XmitEndianBitField& operator = (T v) {
128 // if (!Endian::match_xmit && bits > 8) {
129 // v &= (1u << bits) - 1;
130 // auto utv = (UT)(boost::endian::endian_reverse(v));
131 // vx_ = 0;
132 // if (Endian::little) {
133 // *reinterpret_cast<UT*>(this) ^= (utv >> index);
134 // } else {
135 // *reinterpret_cast<UT*>(this) ^= (utv << (sizeof(UT) * 8 - index - bits));
136 // }
137 // } else {
138 // vx_ = (v & ((1u << bits) - 1));
139 // }
140 // return *this;
141 // }
142 
143 // friend std::istream& operator >> (std::istream& is, XmitEndianBitField& f) {
144 // T tmp;
145 // is >> tmp;
146 // f = tmp;
147 // return is;
148 // }
149 
150 // private:
151 // UT : index;
152 // T vx_ : bits;
153 // } __attribute__((packed));
154 }
Definition: Endian.hpp:80
Definition: Endian.hpp:7
Definition: Endian.hpp:36