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