BinUtils.hpp

Go to the documentation of this file.
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 //  This file is part of GPSTk, the GPS Toolkit.
00016 //
00017 //  The GPSTk is free software; you can redistribute it and/or modify
00018 //  it under the terms of the GNU Lesser General Public License as published
00019 //  by the Free Software Foundation; either version 2.1 of the License, or
00020 //  any later version.
00021 //
00022 //  The GPSTk is distributed in the hope that it will be useful,
00023 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025 //  GNU Lesser General Public License for more details.
00026 //
00027 //  You should have received a copy of the GNU Lesser General Public
00028 //  License along with GPSTk; if not, write to the Free Software Foundation,
00029 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00030 //  
00031 //  Copyright 2004, The University of Texas at Austin
00032 //
00033 //============================================================================
00034 
00035 //============================================================================
00036 //
00037 //This software developed by Applied Research Laboratories at the University of
00038 //Texas at Austin, under contract to an agency or agencies within the U.S. 
00039 //Department of Defense. The U.S. Government retains all rights to use,
00040 //duplicate, distribute, disclose, or release this software. 
00041 //
00042 //Pursuant to DoD Directive 523024 
00043 //
00044 // DISTRIBUTION STATEMENT A: This software has been approved for public 
00045 //                           release, distribution is unlimited.
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          // This code "stolen" from Sven Reifegerste (zorci@gmx.de).
00283          // Found at http://rcswww.urz.tu-dresden.de/~sr21/crctester.c
00284          // from link at http://rcswww.urz.tu-dresden.de/~sr21/crc.html
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             // at first, compute constant bit masks for whole CRC and
00293             // CRC high bit
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             // Stolen from http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
00397          uint32_t c; // store the total here
00398          const int S[] = {1, 2, 4, 8, 16}; // Magic Binary Numbers
00399          const uint32_t B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF,
00400                                0x0000FFFF};
00401 
00402             // ...and if we were to turn this into a loop, it would
00403             // totally defeat the purpose.  The point here is to be
00404             // FAST.
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    } // end namespace BinUtils
00416 } // end namespace gpstk
00417 
00418 #endif

Generated on Fri Feb 3 03:30:58 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1