Alchemy  1.0
A framework to robustly process network messages and structured data
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
byte_order.h
Go to the documentation of this file.
1 /// @file Pb/byte_order.h
2 ///
3 /// Defines constructs that help manage byte-order conversion.
4 ///
5 /// This file contains definitions, utilities and policy implementations
6 /// to deal with byte-order characteristics for different machine architectures.
7 ///
8 /// The final structure of byte-order conversion is an aggregate of two concepts
9 /// into a set of user classes that can be used indiscriminately for the conversion
10 /// of all data:\n
11 ///
12 /// 1) **EndianSwap<T>** This is a generic function that contains specializations
13 /// for each type that may require byte-order management.
14 /// The generic version performs no operations. Calling
15 /// this function a second time with the result of the
16 /// first call, will result with a value equal to the
17 /// input of the first call.\n
18 ///
19 /// 2) **EndianType<>** This structure allows a discriminating ID to be
20 /// associated with endian swap operations.
21 /// Two ID's are specified to discriminate between
22 /// Big-Endian and Little-Endian byte-orders. This
23 /// structure provides a function **swap_order**, which
24 /// will swap the byte-order of a value type according
25 /// to the appropriate context.\n
26 ///
27 /// The user classes, **HostByteOrderT** and **NetByteOrderT**, provide the
28 /// appropriate context for converting between byte-orders. Both of these
29 /// collectors provide the same interfaces with two functions:\n
30 /// - **to_host**\n Converts the value to host order for NetByteOrderT and a no-op for HostByteOrderT\n
31 /// - **to_network**\n Converts the value to network order for HostByteOrderT and a no-op for NetByteOrderT\n
32 ///
33 /// Users should use these constructs for byte-order conversion:
34 /// - Hg::HostByteOrder\n
35 /// - Hg::NetByteOrder
36 /// - Hg::BigEndian
37 /// - Hg::LittleEndian
38 ///
39 /// The MIT License(MIT)
40 /// @copyright 2014 Paul M Watt
41 // ****************************************************************************
42 #ifndef BYTE_ORDER_H_INCLUDED
43 #define BYTE_ORDER_H_INCLUDED
44 // Includes *******************************************************************
45 #include <Pb/detail/endianess.h>
46 
47 namespace Hg
48 {
49 
50 ///< Constant indicates machine endianess.
51 const Endianess k_endianess = Endianess(ALCHEMY_ENDIANESS);
52 
53 namespace convert
54 {
55 
56 // Constants ******************************************************************
57 const size_t k_64bits = 64; ///< Bit-shift constant, 8-bytes
58 const size_t k_56bits = 56; ///< Bit-shift constant, 7-bytes
59 const size_t k_48bits = 48; ///< Bit-shift constant, 6-bytes
60 const size_t k_40bits = 40; ///< Bit-shift constant, 5-bytes
61 const size_t k_32bits = 32; ///< Bit-shift constant, 4-bytes
62 const size_t k_24bits = 24; ///< Bit-shift constant, 3-bytes
63 const size_t k_16bits = 16; ///< Bit-shift constant, 2-bytes
64 const size_t k_8bits = 8; ///< Bit-shift constant, 1-byte
65 
66 } // namespace convert
67 
68 // ****************************************************************************
69 /// A generic implementation that performs no action.
70 ///
71 /// No change is required the for generic case of EndianSwap.
72 /// Specialized definitions of this function will perform endian swap operations.
73 ///
74 /// @param input Input value to perform endian-swap operation.
75 /// @return Simply return the input value.
76 ///
77 ///
78 template <typename T>
79 T EndianSwap(T input)
80 {
81  return input;
82 }
83 
84 // ****************************************************************************
85 /// Endian Swap (Specialization, uint16_t)
86 ///
87 /// Swaps the current byte order between endian formats for a 16-bit value.
88 ///
89 template <>
90 inline
91 uint16_t EndianSwap(uint16_t input)
92 {
93  return (input >> convert::k_8bits)
94  | (input << convert::k_8bits);
95 }
96 
97 // ****************************************************************************
98 /// Endian Swap (Specialization, int16_t)
99 ///
100 /// Swaps the current byte order between endian formats for a 16-bit value.
101 ///
102 template <>
103 inline
104 int16_t EndianSwap(int16_t input)
105 {
106  return static_cast<int32_t> (
107  EndianSwap(static_cast<uint16_t>(input))
108  );
109 }
110 
111 // ****************************************************************************
112 /// Endian Swap (Specialization, uint32_t)
113 ///
114 /// Swaps the current byte order between endian formats for a 32-bit value.
115 ///
116 template <>
117 inline
118 uint32_t EndianSwap(uint32_t input)
119 {
120  return (input >> convert::k_24bits)
121  | ((input << convert::k_8bits) & 0x00FF0000)
122  | ((input >> convert::k_8bits) & 0x0000FF00)
123  | (input << convert::k_24bits);
124 }
125 
126 // ****************************************************************************
127 /// Endian Swap (Specialization, int32_t)
128 ///
129 /// Swaps the current byte order between endian formats for a 32-bit value.
130 ///
131 template <>
132 inline
133 int32_t EndianSwap(int32_t input)
134 {
135  return static_cast<int32_t> (
136  EndianSwap(static_cast<uint32_t>(input))
137  );
138 }
139 
140 // ****************************************************************************
141 /// Endian Swap (Specialization, uint64_t)
142 ///
143 /// Swaps the current byte order between endian formats for a 64-bit value.
144 ///
145 template <>
146 inline
147 uint64_t EndianSwap(uint64_t input)
148 {
149  return (input >> (convert::k_56bits))
150  | (input >> (convert::k_40bits) & 0x000000000000FF00LL)
151  | (input >> (convert::k_24bits) & 0x0000000000FF0000LL)
152  | (input >> (convert::k_8bits) & 0x00000000FF000000LL)
153  | (input << (convert::k_8bits) & 0x000000FF00000000LL)
154  | (input << (convert::k_24bits) & 0x0000FF0000000000LL)
155  | (input << (convert::k_40bits) & 0x00FF000000000000LL)
156  | (input << (convert::k_56bits));
157 }
158 
159 // ****************************************************************************
160 /// Endian Swap (Specialization, int64_t)
161 ///
162 /// Swaps the current byte order between endian formats for a 64-bit value.
163 ///
164 template <>
165 inline
166 int64_t EndianSwap(int64_t input)
167 {
168  return static_cast<int64_t> (
169  EndianSwap(static_cast<uint64_t>(input))
170  );
171 }
172 
173 
174 #if defined(_WIN32) && defined(_HAS_TR1)
175 // ****************************************************************************
176 /// Endian Swap (Specialization, compiler does not recognize int as long)
177 ///
178 template <>
179 inline
180 unsigned int EndianSwap(unsigned int input)
181 {
182  return EndianSwap<unsigned long>(input);
183 }
184 #endif
185 
186 // ****************************************************************************
187 /// Policy class used to perform byte-order operations.
188 ///
189 /// The EndianType struct is a policy class that provides the swap function.
190 /// The swap capability is indicated by t0he isSwap template parameter.
191 ///
192 /// @param <typename T> The type of variable to perform the swap upon.
193 /// @param <bool isSwap> Indicates if the swap should be performed for
194 /// this EndianType.
195 /// - **true:** Indicates a swap is required.
196 /// - **false:** Will not swap byte-order.
197 ///
198 template <typename T, bool isSwap>
200 {
201  // **************************************************************************
202  /// Swaps the byte-order of value T based on platform endianess.
203  ///
204  /// This swap function will instantiate the proper version of EndianSwap based
205  /// on the current EndianType and input value type T. If T does not contain
206  /// a EndianSwap specialization, no operation will be performed.
207  ///
208  /// @param value The value whose byte-order will be swapped.
209  /// @return The input parameter **value**
210  /// with a swapped byte-order.
211  ///
212  static T swap_order(const T& value)
213  {
214  return EndianSwap(value);
215  }
216 };
217 
218 // ****************************************************************************
219 /// Policy class used to perform byte-order operations.
220 ///
221 /// This type specialization that uses a swap operation that performs
222 /// a no-op on the input value.
223 ///
224 template <typename T>
225 struct EndianType<T, false>
226 {
227  // **************************************************************************
228  /// A no-op version of swap.
229  /// This EndianType matches the target byte-order type.
230  ///
231  static T swap_order(const T& value)
232  {
233  return value;
234  }
235 };
236 
237 // ****************************************************************************
238 /// Byte-order management policy for network data transfers.
239 ///
240 /// This class represents the host byte-order behavior and
241 /// provides the capability to convert to a value type in network byte-order.\n
242 /// Host Byte-Order is determined by the platform byte-order.
243 ///
244 /// Usage:
245 /// ~~~{.cpp}
246 /// using std::cout;
247 /// using std::hex;
248 ///
249 /// long hostInput = 0x12345678;
250 ///
251 /// cout << hex << "HostByteOrder: " << netInput << "\n";
252 /// cout << "to_host(): " << Hg::HostByteOrder::to_host(hostInput) << "\n";
253 /// cout << "to_network(): " << Hg::HostByteOrder::to_network(hostInput)<< "\n";
254 ///
255 /// // Prints to the console:
256 /// // HostByteOrder: 12345678
257 /// // to_host: 12345678
258 /// // to_network: 78563412
259 /// ~~~
260 ///
261 template <Endianess E>
263 {
264  static const
265  Endianess order = E;
266 
267  static const
268  bool is_host = true;
269 
270  template <typename T>
271  static
272  T to_host(const T &input)
273  {
274  return input;
275  }
276 
277  template <typename T>
278  static
279  T to_network(const T& input)
280  {
281  // Swapping will be required if the host format is not Big Endian.
283  }
284 
285 protected:
286  // Protected Destructor prevents the deletion of an object from the policy ***
287  ~HostByteOrderT() {}
288 };
289 
290 // ****************************************************************************
291 /// Byte-order management policy for network data transfers.
292 ///
293 /// This class represents the network byte-order behavior and
294 /// provides the capability to convert to a value type in host byte-order.\n
295 /// Network Byte-Order is defined as Big Endian.
296 ///
297 /// Usage:
298 /// ~~~{.cpp}
299 /// using std::cout;
300 /// using std::hex;
301 ///
302 /// long netInput = 0x12345678;
303 ///
304 /// cout << hex << "NetByteOrder: " << netInput << "\n";
305 /// cout << "to_host(): " << Hg::NetByteOrder::to_host(netInput) << "\n";
306 /// cout << "to_network(): " << Hg::NetByteOrder::to_network(netInput)<< "\n";
307 ///
308 /// // Prints to the console:
309 /// // NetByteOrder: 12345678
310 /// // to_host: 78563412
311 /// // to_network: 12345678
312 /// ~~~
313 ///
314 template <Endianess E>
316 {
317  static const
318  Endianess order = E;
319 
320  static const
321  bool is_host = false;
322 
323  template <typename T>
324  static
325  T to_host(const T &input)
326  {
327  // Swapping will be required if the native format is not Big Endian.
329  }
330 
331  template <typename T>
332  static
333  T to_network(const T &input)
334  {
335  return input;
336  }
337 
338 protected:
339  // Protected Destructor prevents the deletion of an object from the policy ***
340  ~NetByteOrderT() {}
341 };
342 
343 // Pre-defined types to represent Host, Network, big and little byte order
344 // for the current platform.
347 
348 #if (ALCHEMY_BIG_ENDIAN == ALCHEMY_ENDIANESS)
351 #else
354 #endif
355 
356 } // namespace Hg
357 
358 #endif