1 // Copyright (C) 2006  Davis E. King (davis@dlib.net)
2 // License: Boost Software License   See LICENSE.txt for the full license.
3 #ifndef DLIB_BYTE_ORDEREr_KERNEL_1_
4 #define DLIB_BYTE_ORDEREr_KERNEL_1_
5 
6 #include "byte_orderer_kernel_abstract.h"
7 #include "../algs.h"
8 #include "../assert.h"
9 
10 namespace dlib
11 {
12 
13     class byte_orderer
14     {
15         /*!
16             INITIAL VALUE
17                 - if (this machine is little endian) then
18                     - little_endian == true
19                 - else
20                     - little_endian == false
21 
22             CONVENTION
23                 - host_is_big_endian() == !little_endian
24                 - host_is_little_endian() == little_endian
25 
26                 - if (this machine is little endian) then
27                     - little_endian == true
28                 - else
29                     - little_endian == false
30 
31 
32         !*/
33 
34 
35     public:
36 
37         // this is here for backwards compatibility with older versions of dlib.
38         typedef byte_orderer kernel_1a;
39 
byte_orderer()40         byte_orderer (
41         )
42         {
43             // This will probably never be false but if it is then it means chars are not 8bits
44             // on this system.  Which is a problem for this object.
45             COMPILE_TIME_ASSERT(sizeof(short) >= 2);
46 
47             unsigned long temp = 1;
48             unsigned char* ptr = reinterpret_cast<unsigned char*>(&temp);
49             if (*ptr == 1)
50                 little_endian = true;
51             else
52                 little_endian = false;
53         }
54 
~byte_orderer()55         virtual ~byte_orderer (
56         ){}
57 
host_is_big_endian()58         bool host_is_big_endian (
59         ) const { return !little_endian; }
60 
host_is_little_endian()61         bool host_is_little_endian (
62         ) const { return little_endian; }
63 
64         template <
65             typename T
66             >
host_to_network(T & item)67         inline void host_to_network (
68             T& item
69         ) const
70         { if (little_endian) flip(item); }
71 
72         template <
73             typename T
74             >
network_to_host(T & item)75         inline void network_to_host (
76             T& item
77         ) const { if (little_endian) flip(item); }
78 
79         template <
80             typename T
81             >
host_to_big(T & item)82         void host_to_big (
83             T& item
84         ) const { if (little_endian) flip(item); }
85 
86         template <
87             typename T
88             >
big_to_host(T & item)89         void big_to_host (
90             T& item
91         ) const { if (little_endian) flip(item); }
92 
93         template <
94             typename T
95             >
host_to_little(T & item)96         void host_to_little (
97             T& item
98         ) const { if (!little_endian) flip(item); }
99 
100         template <
101             typename T
102             >
little_to_host(T & item)103         void little_to_host (
104             T& item
105         ) const { if (!little_endian) flip(item); }
106 
107 
108     private:
109 
110         template <
111             typename T,
112             size_t size
113             >
flip(T (& array)[size])114         inline void flip (
115             T (&array)[size]
116         ) const
117         /*!
118             ensures
119                 - flips the bytes in every element of this array
120         !*/
121         {
122             for (size_t i = 0; i < size; ++i)
123             {
124                 flip(array[i]);
125             }
126         }
127 
128         template <
129             typename T
130             >
flip(T & item)131         inline void flip (
132             T& item
133         ) const
134         /*!
135             ensures
136                 - reverses the byte ordering in item
137         !*/
138         {
139             DLIB_ASSERT_HAS_STANDARD_LAYOUT(T);
140 
141             T value;
142 
143             // If you are getting this as an error then you are probably using
144             // this object wrong.  If you think you aren't then send me (Davis) an
145             // email and I'll either set you straight or change/remove this check so
146             // your stuff works :)
147             COMPILE_TIME_ASSERT(sizeof(T) <= sizeof(long double));
148 
149             // If you are getting a compile error on this line then it means T is
150             // a pointer type.  It doesn't make any sense to byte swap pointers
151             // since they have no meaning outside the context of their own process.
152             // So you probably just forgot to dereference that pointer before passing
153             // it to this function  :)
154             COMPILE_TIME_ASSERT(is_pointer_type<T>::value == false);
155 
156 
157             const size_t size = sizeof(T);
158             unsigned char* const ptr = reinterpret_cast<unsigned char*>(&item);
159             unsigned char* const ptr_temp = reinterpret_cast<unsigned char*>(&value);
160             for (size_t i = 0; i < size; ++i)
161                 ptr_temp[size-i-1] = ptr[i];
162 
163             item = value;
164         }
165 
166         bool little_endian;
167     };
168 
169     // make flip not do anything at all for chars
170     template <> inline void byte_orderer::flip<char> ( char& ) const {}
171     template <> inline void byte_orderer::flip<unsigned char> ( unsigned char& ) const {}
172     template <> inline void byte_orderer::flip<signed char> ( signed char& ) const {}
173 }
174 
175 #endif // DLIB_BYTE_ORDEREr_KERNEL_1_
176 
177