00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef __CSENDIAN_H__
00020 #define __CSENDIAN_H__
00021
00022 #include <math.h>
00023 #include "cstypes.h"
00024 #include "qint.h"
00025
00026
00027
00028
00029
00030
00031 #if !defined (PROC_X86)
00032 # define PROC_NEEDS_STRICT_ALIGNMENT
00033 #endif
00034
00035 struct swap_4
00036 {
00037 unsigned char b1, b2, b3, b4;
00038 };
00039
00040 #ifdef CS_BIG_ENDIAN
00041 # define big_endian_long(x) x
00042 # define big_endian_short(x) x
00043 # define big_endian_float(x) x
00044 #else
00045
00047 static inline ULong big_endian_long (ULong l)
00048 { return (l >> 24) | ((l >> 8) & 0xff00) | ((l << 8) & 0xff0000) | (l << 24); }
00049
00051 static inline UShort big_endian_short (UShort s)
00052 { return (s >> 8) | (s << 8); }
00053
00055
00056 static inline float big_endian_float (float f)
00057 {
00058 unsigned char tmp;
00059 swap_4 *pf = (swap_4 *)&f;
00060 tmp = pf->b1; pf->b1 = pf->b4; pf->b4 = tmp;
00061 tmp = pf->b2; pf->b2 = pf->b3; pf->b3 = tmp;
00062 return f;
00063 }
00064
00065 #endif // CS_BIG_ENDIAN
00066
00067 #ifdef CS_LITTLE_ENDIAN
00068 # define little_endian_long(x) x
00069 # define little_endian_short(x) x
00070 # define little_endian_float(x) x
00071 #else
00072
00074 static inline ULong little_endian_long (ULong l)
00075 { return (l >> 24) | ((l >> 8) & 0xff00) | ((l << 8) & 0xff0000) | (l << 24); }
00076
00078 static inline UShort little_endian_short (UShort s)
00079 { return (s >> 8) | (s << 8); }
00080
00082 static inline float little_endian_float (float f)
00083 {
00084 unsigned char tmp;
00085 swap_4 *pf = (swap_4 *)&f;
00086 tmp = pf->b1; pf->b1 = pf->b4; pf->b4 = tmp;
00087 tmp = pf->b2; pf->b2 = pf->b3; pf->b3 = tmp;
00088 return f;
00089 }
00090
00091 #endif // CS_LITTLE_ENDIAN
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00108 static inline long float2long (float f)
00109 {
00110 int exp;
00111 long mant = QRound (frexp (f, &exp) * 0x1000000);
00112 long sign = mant & 0x80000000;
00113 if (mant < 0) mant = -mant;
00114 if (exp > 63) exp = 63; else if (exp < -64) exp = -64;
00115 return sign | ((exp & 0x7f) << 24) | (mant & 0xffffff);
00116 }
00117
00119 static inline float long2float (long l)
00120 {
00121 int exp = (l >> 24) & 0x7f;
00122 if (exp & 0x40) exp = exp | ~0x7f;
00123 float mant = float (l & 0x00ffffff) / 0x1000000;
00124 if (l & 0x80000000) mant = -mant;
00125 return ldexp (mant, exp);
00126 }
00127
00136
00137 static inline short float2short (float f)
00138 {
00139 int exp;
00140 long mant = QRound (frexp (f, &exp) * 0x1000);
00141 long sign = mant & 0x8000;
00142 if (mant < 0) mant = -mant;
00143 if (exp > 7) mant = 0x7ff, exp = 7; else if (exp < -8) mant = 0, exp = -8;
00144 return sign | ((exp & 0xf) << 11) | (mant & 0x7ff);
00145 }
00146
00148 static inline float short2float (short s)
00149 {
00150 int exp = (s >> 11) & 0xf;
00151 if (exp & 0x8) exp = exp | ~0xf;
00152 float mant = float ((s & 0x07ff) | 0x0800) / 0x1000;
00153 if (s & 0x8000) mant = -mant;
00154 return ldexp (mant, exp);
00155 }
00156
00158 static inline ULong convert_endian (ULong l)
00159 { return little_endian_long (l); }
00160
00162 static inline long convert_endian (long l)
00163 { return little_endian_long (l); }
00164
00166 static inline int convert_endian (int i)
00167 { return little_endian_long (i); }
00168
00170 static inline UShort convert_endian (UShort s)
00171 { return little_endian_short (s); }
00172
00174 static inline float convert_endian (float f)
00175 { return little_endian_float (f); }
00176
00178 inline UShort get_le_short (void *buff)
00179 {
00180 #ifdef PROC_NEEDS_STRICT_ALIGNMENT
00181 UShort s; memcpy (&s, buff, sizeof (s));
00182 return little_endian_short (s);
00183 #else
00184 return little_endian_short (*(UShort *)buff);
00185 #endif
00186 }
00187
00189 inline ULong get_le_long (void *buff)
00190 {
00191 #ifdef PROC_NEEDS_STRICT_ALIGNMENT
00192 ULong l; memcpy (&l, buff, sizeof (l));
00193 return little_endian_long (l);
00194 #else
00195 return little_endian_long (*(ULong *)buff);
00196 #endif
00197 }
00198
00200 inline float get_le_float32 (void *buff)
00201 { ULong l = get_le_long (buff); return long2float (l); }
00202
00204 inline float get_le_float16 (void *buff)
00205 { UShort s = get_le_short (buff); return short2float (s); }
00206
00208 inline void set_le_short (void *buff, UShort s)
00209 {
00210 #ifdef PROC_NEEDS_STRICT_ALIGNMENT
00211 s = little_endian_short (s);
00212 memcpy (buff, &s, sizeof (s));
00213 #else
00214 *((UShort *)buff) = little_endian_short (s);
00215 #endif
00216 }
00217
00219 inline void set_le_long (void *buff, ULong l)
00220 {
00221 #ifdef PROC_NEEDS_STRICT_ALIGNMENT
00222 l = little_endian_long (l);
00223 memcpy (buff, &l, sizeof (l));
00224 #else
00225 *((ULong *)buff) = little_endian_long (l);
00226 #endif
00227 }
00228
00230 inline void set_le_float32 (void *buff, float f)
00231 { set_le_long (buff, float2long (f)); }
00232
00234 inline void set_le_float16 (void *buff, float f)
00235 { set_le_short (buff, float2short (f)); }
00236
00237 #endif // __CSENDIAN_H__