00001 #pragma ident "$Id: BinUtils.hpp 2140 2009-09-26 23:36:27Z ocibu $"
00002
00003
00004
00010 #ifndef BINUTILS_HPP
00011 #define BINUTILS_HPP
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #include "gpstkplatform.h"
00055
00056 #ifdef __sun
00057 #include <arpa/nameser_compat.h>
00058 #elif defined (__CYGWIN__)
00059 #include <sys/param.h>
00060 #elif defined (_AIX)
00061 #include <sys/machine.h>
00062 #endif
00063
00064 #include "Exception.hpp"
00065
00066 #ifndef BYTE_ORDER
00067 #ifdef _MSC_VER
00068 #define LITTLE_ENDIAN 1
00069 #define BIG_ENDIAN 0
00070 #define BYTE_ORDER LITTLE_ENDIAN
00071 #else
00072 #error "Platform doesn't support BYTE_ORDER?"
00073 #endif
00074 #endif
00075
00076 namespace gpstk
00077 {
00084 namespace BinUtils
00085 {
00088
00096 template <class T> void twiddle(T& p)
00097 throw()
00098 {
00099 unsigned char *front = (unsigned char*)&p;
00100 unsigned char *end = front + sizeof(p) - 1;
00101 unsigned char temp;
00102
00103 while (front<end)
00104 {
00105 temp = *front;
00106 *front = *end;
00107 *end = temp;
00108 front++;
00109 end--;
00110 }
00111 }
00112
00118 template <class T> T intelToHost(const T& p)
00119 throw()
00120 {
00121 T temp(p);
00122 #if BYTE_ORDER == BIG_ENDIAN
00123 twiddle(temp);
00124 #endif
00125 return temp;
00126 }
00127
00133 template <class T> T hostToIntel(const T& p)
00134 throw()
00135 {
00136 T temp(p);
00137 #if BYTE_ORDER == BIG_ENDIAN
00138 twiddle(temp);
00139 #endif
00140 return temp;
00141 }
00142
00148 template <class T> T netToHost(const T& p)
00149 throw()
00150 {
00151 T temp(p);
00152 #if BYTE_ORDER == LITTLE_ENDIAN
00153 twiddle(temp);
00154 #endif
00155 return temp;
00156 }
00157
00163 template <class T> T hostToNet(const T& p)
00164 throw()
00165 {
00166 T temp(p);
00167 #if BYTE_ORDER == LITTLE_ENDIAN
00168 twiddle(temp);
00169 #endif
00170 return temp;
00171 }
00172
00181 template <class T>
00182 T decodeVar( std::string& str, std::string::size_type pos = std::string::npos)
00183 {
00184 T t;
00185 char *cp = reinterpret_cast<char*>( &t );
00186
00187 if (pos == std::string::npos)
00188 {
00189 str.copy( cp, sizeof(T) );
00190 t = gpstk::BinUtils::netToHost( t );
00191 str.erase( 0, sizeof(T) );
00192 }
00193 else
00194 {
00195 str.copy( cp, sizeof(T) , pos);
00196 t = gpstk::BinUtils::netToHost( t );
00197 }
00198 return t;
00199 }
00200
00206 template<class T>
00207 std::string encodeVar( const T& v )
00208 {
00209 T tmp = v;
00210 tmp = gpstk::BinUtils::hostToNet( v );
00211 return std::string( reinterpret_cast<char*>( &tmp ), sizeof( tmp ) );
00212 }
00213
00216 NEW_EXCEPTION_CLASS(CRCException, Exception);
00217
00219 inline unsigned long reflect (unsigned long crc,
00220 int bitnum)
00221 {
00222 unsigned long i, j = 1, crcout = 0;
00223
00224 for (i = (unsigned long)1 << (bitnum - 1); i; i >>= 1)
00225 {
00226 if (crc & i)
00227 {
00228 crcout |= j;
00229 }
00230 j <<= 1;
00231 }
00232 return (crcout);
00233 }
00234
00236 class CRCParam
00237 {
00238 public:
00240 CRCParam(int o,
00241 unsigned long p,
00242 unsigned long i,
00243 unsigned long f,
00244 bool d,
00245 bool ri,
00246 bool ro)
00247 : order(o), polynom(p), initial(i), final(f), direct(d),
00248 refin(ri), refout(ro)
00249 {}
00250
00251 int order;
00252 unsigned long polynom;
00253 unsigned long initial;
00254 unsigned long final;
00255 bool direct;
00256 bool refin;
00257 bool refout;
00258 };
00259
00260 extern const CRCParam CRCCCITT;
00261 extern const CRCParam CRC16;
00262 extern const CRCParam CRC32;
00263 extern const CRCParam CRC24Q;
00264
00265
00282
00283
00284
00285 inline unsigned long computeCRC(const unsigned char *data,
00286 unsigned long len,
00287 const CRCParam& params)
00288 {
00289 unsigned long i, j, c, bit;
00290 unsigned long crc = params.initial;
00291
00292
00293
00294 unsigned long crcmask =
00295 ((((unsigned long)1 << (params.order - 1)) - 1) << 1) | 1;
00296 unsigned long crchighbit = (unsigned long)1 << (params.order - 1);
00297
00298 if (crc && params.direct)
00299 {
00300 for (i = 0; i < (unsigned long)params.order; i++)
00301 {
00302 bit = crc & 1;
00303 if (bit)
00304 {
00305 crc ^= params.polynom;
00306 }
00307 crc >>= 1;
00308 if (bit)
00309 {
00310 crc |= crchighbit;
00311 }
00312 }
00313 }
00314
00315
00316 for (i = 0; i < len; i++)
00317 {
00318 c = (unsigned long) * data++;
00319 if (params.refin)
00320 {
00321 c = reflect(c, 8);
00322 }
00323
00324 for (j = 0x80; j; j >>= 1)
00325 {
00326 bit = crc & crchighbit;
00327 crc <<= 1;
00328 if (c & j)
00329 {
00330 crc |= 1;
00331 }
00332 if (bit)
00333 {
00334 crc ^= params.polynom;
00335 }
00336 }
00337 }
00338
00339 for (i = 0; i < (unsigned long)params.order; i++)
00340 {
00341 bit = crc & crchighbit;
00342 crc <<= 1;
00343 if (bit)
00344 {
00345 crc ^= params.polynom;
00346 }
00347 }
00348
00349 if (params.refout)
00350 {
00351 crc = reflect(crc, params.order);
00352 }
00353 crc ^= params.final;
00354 crc &= crcmask;
00355
00356 return crc;
00357 }
00358
00365 template<class X>
00366 X xorChecksum(const std::string& str)
00367 throw(gpstk::InvalidParameter)
00368 {
00369 short wordSize = sizeof(X);
00370 short strSize = str.size();
00371
00372 if(strSize % wordSize != 0)
00373 {
00374 gpstk::Exception ip("Incomplete word in string.");
00375 GPSTK_THROW(ip);
00376 }
00377
00378 X temp, xc = 0;
00379
00380 for(short i = 0; (i + wordSize - 1) < strSize; i += wordSize)
00381 {
00382 memcpy(&temp, &str[i], wordSize);
00383 xc ^= temp;
00384 }
00385
00386 return xc;
00387 }
00389
00394 static unsigned short countBits(uint32_t v)
00395 {
00396
00397 uint32_t c;
00398 const int S[] = {1, 2, 4, 8, 16};
00399 const uint32_t B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF,
00400 0x0000FFFF};
00401
00402
00403
00404
00405 c = v;
00406 c = ((c >> S[0]) & B[0]) + (c & B[0]);
00407 c = ((c >> S[1]) & B[1]) + (c & B[1]);
00408 c = ((c >> S[2]) & B[2]) + (c & B[2]);
00409 c = ((c >> S[3]) & B[3]) + (c & B[3]);
00410 c = ((c >> S[4]) & B[4]) + (c & B[4]);
00411
00412 return c;
00413 }
00414
00415 }
00416 }
00417
00418 #endif