00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef __CS_CSENDIAN_H__
00020 #define __CS_CSENDIAN_H__
00021
00031 #include <math.h>
00032 #include "cstypes.h"
00033 #include "qint.h"
00034
00035 struct swap_4
00036 {
00037 unsigned char b1, b2, b3, b4;
00038 };
00039
00040 struct swap_8
00041 {
00042 unsigned char b1, b2, b3, b4,
00043 b5, b6, b7, b8;
00044 };
00045
00046 #ifdef CS_BIG_ENDIAN
00047 # define big_endian_longlong(x) x
00048 # define big_endian_long(x) x
00049 # define big_endian_short(x) x
00050 # define big_endian_float(x) x
00051 #else
00052
00054 static inline uint64 big_endian_longlong (uint64 l)
00055 {
00056 uint64 r;
00057 swap_8 *p1 = (swap_8 *)&l;
00058 swap_8 *p2 = (swap_8 *)&r;
00059 p2->b1 = p1->b8;
00060 p2->b2 = p1->b7;
00061 p2->b3 = p1->b6;
00062 p2->b4 = p1->b5;
00063 p2->b5 = p1->b4;
00064 p2->b6 = p1->b3;
00065 p2->b7 = p1->b2;
00066 p2->b8 = p1->b1;
00067 return r;
00068 }
00069
00070
00072 static inline uint32 big_endian_long (uint32 l)
00073 { return (l >> 24) | ((l >> 8) & 0xff00) | ((l << 8) & 0xff0000) | (l << 24); }
00074
00076 static inline uint16 big_endian_short (uint16 s)
00077 { return uint16((s >> 8) | (s << 8)); }
00078
00080
00081 static inline float big_endian_float (float f)
00082 {
00083 unsigned char tmp;
00084 swap_4 *pf = (swap_4 *)&f;
00085 tmp = pf->b1; pf->b1 = pf->b4; pf->b4 = tmp;
00086 tmp = pf->b2; pf->b2 = pf->b3; pf->b3 = tmp;
00087 return f;
00088 }
00089
00090 #endif // CS_BIG_ENDIAN
00091
00092 #ifdef CS_LITTLE_ENDIAN
00093 # define little_endian_longlong(x) x
00094 # define little_endian_long(x) x
00095 # define little_endian_short(x) x
00096 # define little_endian_float(x) x
00097 #else
00098
00100 static inline uint64 little_endian_longlong (uint64 l)
00101 {
00102 uint64 r;
00103 swap_8 *p1 = (swap_8 *)&l;
00104 swap_8 *p2 = (swap_8 *)&r;
00105 p2->b1 = p1->b8;
00106 p2->b2 = p1->b7;
00107 p2->b3 = p1->b6;
00108 p2->b4 = p1->b5;
00109 p2->b5 = p1->b4;
00110 p2->b6 = p1->b3;
00111 p2->b7 = p1->b2;
00112 p2->b8 = p1->b1;
00113 return r;
00114 }
00115
00117 static inline uint32 little_endian_long (uint32 l)
00118 { return (l >> 24) | ((l >> 8) & 0xff00) | ((l << 8) & 0xff0000) | (l << 24); }
00119
00121 static inline uint16 little_endian_short (uint16 s)
00122 { return (s >> 8) | (s << 8); }
00123
00125 static inline float little_endian_float (float f)
00126 {
00127 unsigned char tmp;
00128 swap_4 *pf = (swap_4 *)&f;
00129 tmp = pf->b1; pf->b1 = pf->b4; pf->b4 = tmp;
00130 tmp = pf->b2; pf->b2 = pf->b3; pf->b3 = tmp;
00131 return f;
00132 }
00133
00134 #endif // CS_LITTLE_ENDIAN
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00153 static inline int32 float2long (float f)
00154 {
00155 int exp;
00156 int32 mant = QRound (frexp (f, &exp) * 0x1000000);
00157 int32 sign = mant & 0x80000000;
00158 if (mant < 0) mant = -mant;
00159 if (exp > 63) exp = 63; else if (exp < -64) exp = -64;
00160 return sign | ((exp & 0x7f) << 24) | (mant & 0xffffff);
00161 }
00162
00164 static inline float long2float (int32 l)
00165 {
00166 int exp = (l >> 24) & 0x7f;
00167 if (exp & 0x40) exp = exp | ~0x7f;
00168 float mant = float (l & 0x00ffffff) / 0x1000000;
00169 if (l & 0x80000000) mant = -mant;
00170 return (float) ldexp (mant, exp);
00171 }
00172
00174 static inline int64 double2longlong (double d)
00175 {
00176 int exp;
00177 int64 mant = (int64) (frexp (d, &exp) * CONST_INT64(0x1000000000000));
00178 int64 sign = mant & CONST_INT64(0x800000000000000);
00179 if (mant < 0) mant = -mant;
00180 if (exp > 32767) exp = 32767; else if (exp < -32768) exp = -32768;
00181 return sign | ((int64 (exp) & 0x7fff) << 48) | (mant & CONST_INT64(0xffffffffffff));
00182 }
00183
00185 static inline double longlong2double (int64 i)
00186 {
00187 int64 exp = (i >> 48) & 0x7fff;
00188 if (exp & 0x4000) exp = exp | ~0x7fff;
00189 double mant = double (i & CONST_INT64(0xffffffffffff)) / CONST_INT64(0x1000000000000);
00190 if (i & CONST_INT64(0x8000000000000000)) mant = -mant;
00191 return ldexp (mant, exp);
00192 }
00193
00202
00203 static inline short float2short (float f)
00204 {
00205 int exp;
00206 long mant = QRound (frexp (f, &exp) * 0x1000);
00207 long sign = mant & 0x8000;
00208 if (mant < 0) mant = -mant;
00209 if (exp > 7) mant = 0x7ff, exp = 7; else if (exp < -8) mant = 0, exp = -8;
00210 return short(sign | ((exp & 0xf) << 11) | (mant & 0x7ff));
00211 }
00212
00214 static inline float short2float (short s)
00215 {
00216 int exp = (s >> 11) & 0xf;
00217 if (exp & 0x8) exp = exp | ~0xf;
00218 float mant = float ((s & 0x07ff) | 0x0800) / 0x1000;
00219 if (s & 0x8000) mant = -mant;
00220 return (float) ldexp (mant, exp);
00221 }
00222
00224 static inline uint64 convert_endian (uint64 l)
00225 { return little_endian_long (l); }
00226
00228 static inline int64 convert_endian (int64 l)
00229 { return little_endian_long (l); }
00230
00232 static inline uint32 convert_endian (uint32 l)
00233 { return little_endian_long (l); }
00234
00236 static inline int32 convert_endian (int32 l)
00237 { return little_endian_long (l); }
00238
00240 static inline int16 convert_endian (int16 s)
00241 { return little_endian_short (s); }
00242
00244 static inline uint16 convert_endian (uint16 s)
00245 { return little_endian_short (s); }
00246
00248 static inline float convert_endian (float f)
00249 { return little_endian_float (f); }
00250
00252 inline uint16 get_le_short (void *buff)
00253 {
00254 #ifdef CS_STRICT_ALIGNMENT
00255 uint16 s; memcpy (&s, buff, sizeof (s));
00256 return little_endian_short (s);
00257 #else
00258 return little_endian_short (*(uint16 *)buff);
00259 #endif
00260 }
00261
00263 inline uint32 get_le_long (void *buff)
00264 {
00265 #ifdef CS_STRICT_ALIGNMENT
00266 uint32 l; memcpy (&l, buff, sizeof (l));
00267 return little_endian_long (l);
00268 #else
00269 return little_endian_long (*(uint32 *)buff);
00270 #endif
00271 }
00272
00274 inline float get_le_float32 (void *buff)
00275 { uint32 l = get_le_long (buff); return long2float (l); }
00276
00278 inline float get_le_float16 (void *buff)
00279 { uint16 s = get_le_short (buff); return short2float (s); }
00280
00282 inline void set_le_short (void *buff, uint16 s)
00283 {
00284 #ifdef CS_STRICT_ALIGNMENT
00285 s = little_endian_short (s);
00286 memcpy (buff, &s, sizeof (s));
00287 #else
00288 *((uint16 *)buff) = little_endian_short (s);
00289 #endif
00290 }
00291
00293 inline void set_le_long (void *buff, uint32 l)
00294 {
00295 #ifdef CS_STRICT_ALIGNMENT
00296 l = little_endian_long (l);
00297 memcpy (buff, &l, sizeof (l));
00298 #else
00299 *((uint32 *)buff) = little_endian_long (l);
00300 #endif
00301 }
00302
00304 inline void set_le_float32 (void *buff, float f)
00305 { set_le_long (buff, float2long (f)); }
00306
00308 inline void set_le_float16 (void *buff, float f)
00309 { set_le_short (buff, float2short (f)); }
00310
00315 #endif // __CS_CSENDIAN_H__