Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

endian_types.h

Go to the documentation of this file.
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

Generated on Sun Mar 11 22:11:45 2007 for Kino by  doxygen 1.4.2