00001 /* <endian_types.h> 00002 * 00003 * Quick hack to handle endianness and word length issues. 00004 * Defines _le, _be, and _ne variants to standard ISO types 00005 * like int32_t, that are stored in little-endian, big-endian, 00006 * and native-endian byteorder in memory, respectively. 00007 * Caveat: int32_le_t and friends cannot be used in vararg 00008 * functions like printf() without an explicit cast. 00009 * 00010 * Copyright (c) 2003-2007 Daniel Kobras <kobras@debian.org> 00011 * 00012 * This program is free software; you can redistribute it and/or modify 00013 * it under the terms of the GNU General Public License as published by 00014 * the Free Software Foundation; either version 2 of the License, or 00015 * (at your option) any later version. 00016 * 00017 * This program is distributed in the hope that it will be useful, 00018 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 * GNU General Public License for more details. 00021 * 00022 * You should have received a copy of the GNU General Public License 00023 * along with this program; if not, write to the Free Software Foundation, 00024 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00025 */ 00026 00027 #ifndef _ENDIAN_TYPES_H 00028 #define _ENDIAN_TYPES_H 00029 00030 /* Needed for BYTE_ORDER and BIG/LITTLE_ENDIAN macros. */ 00031 #ifndef _BSD_SOURCE 00032 # define _BSD_SOURCE 00033 # include <endian.h> 00034 # undef _BSD_SOURCE 00035 #else 00036 # include <endian.h> 00037 #endif 00038 00039 #include <sys/types.h> 00040 #include <byteswap.h> 00041 00042 static inline int8_t bswap(const int8_t& x) 00043 { 00044 return x; 00045 } 00046 00047 static inline u_int8_t bswap(const u_int8_t& x) 00048 { 00049 return x; 00050 } 00051 00052 static inline int16_t bswap(const int16_t& x) 00053 { 00054 return bswap_16(x); 00055 } 00056 00057 static inline u_int16_t bswap(const u_int16_t& x) 00058 { 00059 return bswap_16(x); 00060 } 00061 00062 static inline int32_t bswap(const int32_t& x) 00063 { 00064 return bswap_32(x); 00065 } 00066 00067 static inline u_int32_t bswap(const u_int32_t& x) 00068 { 00069 return bswap_32(x); 00070 } 00071 00072 static inline int64_t bswap(const int64_t& x) 00073 { 00074 return bswap_64(x); 00075 } 00076 00077 static inline u_int64_t bswap(const u_int64_t& x) 00078 { 00079 return bswap_64(x); 00080 } 00081 00082 #define le_to_cpu cpu_to_le 00083 #define be_to_cpu cpu_to_be 00084 00085 template <class T> static inline T cpu_to_le(const T& x) 00086 { 00087 #if BYTE_ORDER == LITTLE_ENDIAN 00088 return x; 00089 #else 00090 return bswap(x); 00091 #endif 00092 } 00093 00094 template <class T> static inline T cpu_to_be(const T& x) 00095 { 00096 #if BYTE_ORDER == LITTLE_ENDIAN 00097 return bswap(x); 00098 #else 00099 return x; 00100 #endif 00101 } 00102 00103 template <class T> class le_t { 00104 T m; 00105 T read() const { 00106 return le_to_cpu(m); 00107 }; 00108 void write(const T& n) { 00109 m = cpu_to_le(n); 00110 }; 00111 public: 00112 le_t(void) { 00113 m = 0; 00114 }; 00115 le_t(const T& o) { 00116 write(o); 00117 }; 00118 operator T() const { 00119 return read(); 00120 }; 00121 le_t<T> operator++() { 00122 write(read() + 1); 00123 return *this; 00124 }; 00125 le_t<T> operator++(int) { 00126 write(read() + 1); 00127 return *this; 00128 }; 00129 le_t<T> operator--() { 00130 write(read() - 1); 00131 return *this; 00132 }; 00133 le_t<T> operator--(int) { 00134 write(read() - 1); 00135 return *this; 00136 }; 00137 le_t<T>& operator+=(const T& t) { 00138 write(read() + t); 00139 return *this; 00140 }; 00141 le_t<T>& operator-=(const T& t) { 00142 write(read() - t); 00143 return *this; 00144 }; 00145 le_t<T>& operator&=(const le_t<T>& t) { 00146 m &= t.m; 00147 return *this; 00148 }; 00149 le_t<T>& operator|=(const le_t<T>& t) { 00150 m |= t.m; 00151 return *this; 00152 }; 00153 } __attribute__((packed)); 00154 00155 /* Just copy-and-pasted from le_t. Too lazy to do it right. */ 00156 00157 template <class T> class be_t { 00158 T m; 00159 T read() const { 00160 return be_to_cpu(m); 00161 }; 00162 void write(const T& n) { 00163 m = cpu_to_be(n); 00164 }; 00165 public: 00166 be_t(void) { 00167 m = 0; 00168 }; 00169 be_t(const T& o) { 00170 write(o); 00171 }; 00172 operator T() const { 00173 return read(); 00174 }; 00175 be_t<T> operator++() { 00176 write(read() + 1); 00177 return *this; 00178 }; 00179 be_t<T> operator++(int) { 00180 write(read() + 1); 00181 return *this; 00182 }; 00183 be_t<T> operator--() { 00184 write(read() - 1); 00185 return *this; 00186 }; 00187 be_t<T> operator--(int) { 00188 write(read() - 1); 00189 return *this; 00190 }; 00191 be_t<T>& operator+=(const T& t) { 00192 write(read() + t); 00193 return *this; 00194 }; 00195 be_t<T>& operator-=(const T& t) { 00196 write(read() - t); 00197 return *this; 00198 }; 00199 be_t<T>& operator&=(const be_t<T>& t) { 00200 m &= t.m; 00201 return *this; 00202 }; 00203 be_t<T>& operator|=(const be_t<T>& t) { 00204 m |= t.m; 00205 return *this; 00206 }; 00207 } __attribute__((packed)); 00208 00209 /* Define types of native endianness similar to the little and big endian 00210 * versions below. Not really necessary but useful occasionally to emphasize 00211 * endianness of data. 00212 */ 00213 00214 typedef int8_t int8_ne_t; 00215 typedef int16_t int16_ne_t; 00216 typedef int32_t int32_ne_t; 00217 typedef int64_t int64_ne_t; 00218 typedef u_int8_t u_int8_ne_t; 00219 typedef u_int16_t u_int16_ne_t; 00220 typedef u_int32_t u_int32_ne_t; 00221 typedef u_int64_t u_int64_ne_t; 00222 00223 00224 /* The classes work on their native endianness as well, but obviously 00225 * introduce some overhead. Use the faster typedefs to native types 00226 * therefore, unless you're debugging. 00227 */ 00228 00229 #if BYTE_ORDER == LITTLE_ENDIAN 00230 typedef int8_ne_t int8_le_t; 00231 typedef int16_ne_t int16_le_t; 00232 typedef int32_ne_t int32_le_t; 00233 typedef int64_ne_t int64_le_t; 00234 typedef u_int8_ne_t u_int8_le_t; 00235 typedef u_int16_ne_t u_int16_le_t; 00236 typedef u_int32_ne_t u_int32_le_t; 00237 typedef u_int64_ne_t u_int64_le_t; 00238 typedef int8_t int8_be_t; 00239 typedef be_t<int16_t> int16_be_t; 00240 typedef be_t<int32_t> int32_be_t; 00241 typedef be_t<int64_t> int64_be_t; 00242 typedef u_int8_t u_int8_be_t; 00243 typedef be_t<u_int16_t> u_int16_be_t; 00244 typedef be_t<u_int32_t> u_int32_be_t; 00245 typedef be_t<u_int64_t> u_int64_be_t; 00246 #else 00247 typedef int8_ne_t int8_be_t; 00248 typedef int16_ne_t int16_be_t; 00249 typedef int32_ne_t int32_be_t; 00250 typedef int64_ne_t int64_be_t; 00251 typedef u_int8_ne_t u_int8_be_t; 00252 typedef u_int16_ne_t u_int16_be_t; 00253 typedef u_int32_ne_t u_int32_be_t; 00254 typedef u_int64_ne_t u_int64_be_t; 00255 typedef int8_t int8_le_t; 00256 typedef le_t<int16_t> int16_le_t; 00257 typedef le_t<int32_t> int32_le_t; 00258 typedef le_t<int64_t> int64_le_t; 00259 typedef u_int8_t u_int8_le_t; 00260 typedef le_t<u_int16_t> u_int16_le_t; 00261 typedef le_t<u_int32_t> u_int32_le_t; 00262 typedef le_t<u_int64_t> u_int64_le_t; 00263 #endif 00264 00265 #endif
1.4.2