BinexData.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: BinexData.cpp 1895 2009-05-12 19:34:29Z afarris $"
00002 
00003 //============================================================================
00004 //
00005 //  This file is part of GPSTk, the GPS Toolkit.
00006 //
00007 //  The GPSTk is free software; you can redistribute it and/or modify
00008 //  it under the terms of the GNU Lesser General Public License as published
00009 //  by the Free Software Foundation; either version 2.1 of the License, or
00010 //  any later version.
00011 //
00012 //  The GPSTk is distributed in the hope that it will be useful,
00013 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //  GNU Lesser General Public License for more details.
00016 //
00017 //  You should have received a copy of the GNU Lesser General Public
00018 //  License along with GPSTk; if not, write to the Free Software Foundation,
00019 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //
00021 //  Copyright 2008, The University of Texas at Austin
00022 //
00023 //============================================================================
00024 
00030 #include <cstring>
00031  
00032 #include "DayTime.hpp"
00033 #include "BinexData.hpp"
00034 #include "BinexStream.hpp"
00035 
00036 using namespace std;
00037 
00038 namespace gpstk
00039 {
00040    // =========================================================================
00041    // BinexData::UBNXI Methods 
00042    // =========================================================================
00043 
00044    // -------------------------------------------------------------------------
00045    BinexData::UBNXI::UBNXI()
00046    {
00047       value = 0;
00048       size  = 1;
00049    }
00050 
00051    // -------------------------------------------------------------------------
00052    BinexData::UBNXI::UBNXI(unsigned long ul)
00053       throw(FFStreamError)
00054    {
00055       if (ul < 128)
00056       {
00057          size = 1;
00058       }
00059       else if (ul < 16384)
00060       {
00061          size = 2;
00062       }
00063       else if (ul < 2097152)
00064       {
00065          size = 3;
00066       }
00067       else if (ul < 536870912)
00068       {
00069          size = 4;
00070       }
00071       else
00072       {
00073          value = 0;
00074          size  = 0;
00075 
00076          std::ostringstream errStrm;
00077          errStrm << "BINEX UBNXI overflow: " << ul;
00078          FFStreamError err(errStrm.str() );
00079          GPSTK_THROW(err);
00080       }
00081 
00082       value = ul;
00083    }
00084 
00085 
00086    // -------------------------------------------------------------------------
00087    size_t
00088    BinexData::UBNXI::decode(
00089       const std::string&  inBuffer,
00090       size_t              offset,
00091       bool                littleEndian)
00092          throw(FFStreamError)
00093    {
00094       if (offset > inBuffer.size() )
00095       {
00096          std::ostringstream errStrm;
00097          errStrm << "Invalid offset into BINEX UBNXI input buffer: " << offset;
00098          FFStreamError err(errStrm.str() );
00099          GPSTK_THROW(err);
00100       }
00101       bool more = true;
00102       for (size = 0, value = 0L; (size < MAX_BYTES) && more; size++)
00103       {
00104          unsigned char mask = (size < 3) ? 0x7f : 0xff;
00105          if (littleEndian)
00106          {
00107             value |= ( (unsigned long)inBuffer[offset + size] & mask) << (7 * size);
00108          }
00109          else
00110          {
00111             value <<= (size < 3) ? 7 : 8;
00112             value |= ( (unsigned long)inBuffer[offset + size] & mask);
00113          }
00114          if ( (inBuffer[offset + size] & 0x80) != 0x80)
00115          {
00116             more = false;
00117          }
00118       }
00119       return size;
00120    }
00121 
00122 
00123    // -------------------------------------------------------------------------
00124    size_t
00125    BinexData::UBNXI::encode(
00126       std::string&  outBuffer,
00127       size_t        offset,
00128       bool          littleEndian) const
00129    {
00130       unsigned char  uc;
00131       unsigned short us, us1;
00132       unsigned long  ul, ul1, ul2, ul3;
00133 
00134       if (offset > outBuffer.size() )
00135       {
00136          std::ostringstream errStrm;
00137          errStrm << "Invalid offset into BINEX UBNXI output buffer: " << offset;
00138          FFStreamError err(errStrm.str() );
00139          GPSTK_THROW(err);
00140       }
00141       switch (size)
00142       {
00143          case 1:
00144             uc   = (unsigned char)value;
00145             outBuffer.replace(offset, size, reinterpret_cast<char*>(&uc), size);
00146             break;
00147 
00148          case 2:
00149             us   = (unsigned short)value;
00150             us1  = 0x7f00 & (us << 1);
00151             us  &= 0x007f;
00152             us  |= us1;
00153 
00154             if (littleEndian != nativeLittleEndian)
00155             {
00156                   // Allow encoding to non-native byte ordering
00157                reverseBuffer((unsigned char*)&us, 2);
00158             }
00159             us  |= nativeLittleEndian ? 0x0080 : 0x8000;
00160 
00161             outBuffer.replace(offset, size, reinterpret_cast<char*>(&us), size);
00162             break;
00163 
00164          case 3:
00165             ul   = (unsigned long)value;
00166             ul2  = 0x007f0000 & (ul << 2);
00167             ul1  = 0x00007f00 & (ul << 1);
00168             ul  &= 0x0000007f;
00169             ul  |= ul1 | ul2;
00170             
00171             if (littleEndian != nativeLittleEndian)
00172             {
00173                   // Allow encoding to non-native byte ordering
00174                reverseBuffer((unsigned char*)&ul, 4);
00175                ul >>= 8;
00176             }
00177             if (nativeLittleEndian)
00178             {
00179                ul  |= 0x00008080;
00180             }
00181             else
00182             {
00183                ul  |= 0x00808000;
00184                ul <<= 8;
00185             }
00186 
00187             outBuffer.replace(offset, size, reinterpret_cast<char*>(&ul), size);
00188             break;
00189 
00190          case 4:
00191             if (littleEndian)
00192             {
00193                ul   = (unsigned long)value;
00194                ul3  = 0xff000000 & (ul << 3);
00195                ul2  = 0x007f0000 & (ul << 2);
00196                ul1  = 0x00007f00 & (ul << 1);
00197                ul  &= 0x0000007f;
00198                ul  |= ul1 | ul2 | ul3;
00199 
00200                if (!nativeLittleEndian)
00201                {
00202                      // Allow encoding to non-native byte ordering
00203                   reverseBuffer((unsigned char*)&ul, 4);
00204                }
00205             }
00206             else
00207             {
00208                ul   = (unsigned long)value;
00209                ul2  = 0x7f000000 & (ul << 2);
00210                ul1  = 0x007f0000 & (ul << 1);
00211                ul  &= 0x00007fff;
00212                ul  |= ul1 | ul2;
00213    
00214                if (nativeLittleEndian)
00215                {
00216                      // Allow encoding to non-native byte ordering
00217                   reverseBuffer((unsigned char*)&ul, 4);
00218                }
00219             }
00220             ul  |= nativeLittleEndian ? 0x00808080 : 0x80808000;
00221 
00222             outBuffer.replace(offset, size, reinterpret_cast<char*>(&ul), size);
00223             break;
00224 
00225          default:
00226             std::ostringstream errStrm;
00227             errStrm << "BINEX UBNXI invalid size: " << size;
00228             FFStreamError err(errStrm.str() );
00229             GPSTK_THROW(err);
00230             break;
00231       }      
00232       return size;
00233    }
00234 
00235 
00236    // -------------------------------------------------------------------------
00237    size_t
00238    BinexData::UBNXI::read(
00239       istream&      strm,
00240       std::string   *outBuffer,
00241       size_t        offset,
00242       bool          reverseBytes,
00243       bool          littleEndian)
00244          throw(FFStreamError)
00245    {
00246       unsigned char mask = 0;
00247       char          buffer [MAX_BYTES];
00248 
00249       if (reverseBytes)
00250       {
00252       }
00253       else
00254       {
00255          bool more = true;
00256          for (size = 0, value = 0L; (size < MAX_BYTES) && more; size++)
00257          {
00258             mask = (size < 3) ? 0x7f : 0xff;
00259             
00260             strm.read(&buffer[size], 1);
00261             if (!strm.good() )
00262             {
00263                FFStreamError err("Error reading BINEX UBNXI");
00264                GPSTK_THROW(err);
00265             }            
00266             if (littleEndian)
00267             {
00268                value  |= ( (unsigned long)buffer[size] & mask) << (size * 7);
00269             }
00270             else
00271             {
00272                value <<= (size < 3) ? 7 : 8;
00273                value  |= (unsigned long)buffer[size] & mask;
00274             }
00275             if ( (buffer[size] & 0x80) != 0x80)
00276             {
00277                more = false;   // End of UBNXI detected - exit loop
00278             }
00279          }
00280          if (outBuffer)
00281          {
00282                // Store the as-read bytes
00283             if (offset <= outBuffer->size() )
00284             {
00285                outBuffer->replace(offset, size, buffer, size);
00286             }
00287             else
00288             {
00289                std::ostringstream errStrm;
00290                errStrm << "Invalid offset into BINEX UBNXI output buffer: " << offset;
00291                FFStreamError err(errStrm.str() );
00292                GPSTK_THROW(err);
00293             }
00294          }
00295       }
00296       return size;
00297    }
00298 
00299 
00300    // -------------------------------------------------------------------------
00301    size_t
00302    BinexData::UBNXI::write(
00303       ostream&       strm,
00304       std::string    *outBuffer,
00305       size_t         offset,
00306       bool           reverseBytes,
00307       bool           littleEndian) const
00308          throw(FFStreamError)
00309    {
00310       std::string  buffer;
00311       encode(buffer, 0, littleEndian);
00312       if (outBuffer)
00313       {
00314          if (offset <= outBuffer->size() )
00315          {
00316                // Store the as written bytes
00317             outBuffer->replace(offset, size, buffer);
00318          }
00319          else
00320          {
00321             std::ostringstream errStrm;
00322             errStrm << "Invalid offset into BINEX UBNXI output buffer: " << offset;
00323             FFStreamError err(errStrm.str() );
00324             GPSTK_THROW(err);
00325          }
00326       }
00327       if (reverseBytes)
00328       {
00329          reverseBuffer(buffer);
00330       }
00331       strm.write(buffer.data(), size);
00332       if (!strm.good() )
00333       {
00334          FFStreamError err("Error writing BINEX UBNXI");
00335          GPSTK_THROW(err);
00336       }
00337       return size;
00338    }
00339 
00340    // =========================================================================
00341    // BinexData::MGFZI Methods 
00342    // =========================================================================
00343 
00344    // -------------------------------------------------------------------------
00345    BinexData::MGFZI::MGFZI()
00346    {
00347       value = 0;
00348       size  = 1;
00349    }
00350 
00351 
00352    // -------------------------------------------------------------------------
00353    BinexData::MGFZI::MGFZI(long long ll)
00354       throw(FFStreamError)
00355    {
00356 
00357       value = ll;
00358       long long absValue = value;
00359       if (absValue < 0)
00360       {
00361          absValue = absValue*(-1);
00362       } 
00363 
00364       
00365       if (absValue < 16LL)
00366       {
00367          size = 1;
00368       }
00369       else if (absValue < 4110LL)
00370       {
00371          size = 2;
00372       }
00373       else if (absValue < 1052685LL)
00374       {
00375          size = 3;
00376       }
00377       else if (absValue < 269488140LL)
00378       {
00379          size = 4;
00380       }
00381       else if (absValue < 68988964875LL)
00382       {
00383          size = 5;
00384       }
00385       else if (absValue < 17661175009290LL)
00386       {
00387          size = 6;
00388       }
00389       else if (absValue < 4521260802379785LL)
00390       {
00391          size = 7;
00392       }
00393       else if (absValue <= BinexData::MGFZI::MAX_VALUE)
00394       {
00395          size = 8;
00396       }
00397       else
00398       {
00399          value = 0LL;
00400          size  = 0;
00401 
00402          std::ostringstream errStrm;
00403          errStrm << "BINEX MGFZI overflow: " << ll;
00404          FFStreamError err(errStrm.str() );
00405          GPSTK_THROW(err);
00406       }
00407    }
00408 
00409 
00410    // -------------------------------------------------------------------------
00411    size_t
00412    BinexData::MGFZI::decode(
00413       const std::string&  inBuffer,
00414       size_t              offset,
00415       bool                littleEndian)
00416          throw(FFStreamError)
00417    {
00418       long long          absValue = 0;
00419       unsigned char      flags;
00420       unsigned long long ull;
00421       short              sign;
00422 
00423       if (offset > inBuffer.size() )
00424       {
00425          std::ostringstream errStrm;
00426          errStrm << "Invalid offset into BINEX MGFZI input buffer: " << offset;
00427          FFStreamError err(errStrm.str() );
00428          GPSTK_THROW(err);
00429       }
00430 
00431       if (inBuffer.size() == 0)
00432       {
00433             // Nothing to decode
00434          size  = 0;
00435          value = 0;
00436          return 0;
00437       }
00438          // Isolate sign and byte-length flags
00439       flags = littleEndian
00440             ? inBuffer[offset] & 0x0f
00441             : (inBuffer[offset] >> 4) & 0x0f;
00442 
00443          // Determine whether the final value is positive or negative.
00444       sign = (flags & 0x08) ? -1 : 1;
00445 
00446          // Handle varying byte lengths
00447       size = (flags & 0x07) + 1;
00448       if (size > inBuffer.size() )
00449       {
00450          std::ostringstream errStrm;
00451          errStrm << "BINEX MGFZI is too large for the supplied decode buffer: "
00452                  << "MGFZI size = " << size << " , buffer size = " << inBuffer.size();
00453          FFStreamError err(errStrm.str() );
00454          GPSTK_THROW(err);
00455       }
00456 
00457       switch (size)
00458       {
00459          case 0x01:
00460             // Use 1 byte:
00461             //
00462             ull = parseBuffer(inBuffer, offset, 1);
00463             absValue = littleEndian
00464                      ? ull >> 4
00465                      : ull & 0x0000000fULL;
00466             if (sign == -1 && absValue == 0)
00467             {
00468                // "-0" reserved for "no data" indicator
00469                size = 0;
00470                // TODO - throw
00471             }
00472             else
00473             {
00474                value = sign * absValue;
00475             }
00476             break;
00477 
00478          case 0x02:
00479             // Use 2 bytes:
00480             //
00481             ull = parseBuffer(inBuffer, offset, 2);
00482             if (littleEndian != nativeLittleEndian)
00483             {
00484                reverseBuffer( (unsigned char*)&ull, 8);
00485                ull >>= 48;
00486             }
00487             absValue = littleEndian
00488                      ? ull >> 4
00489                      : ull & 0x0000000000000fffULL;
00490             value = sign * (14ULL + absValue);
00491             break;
00492 
00493          case 0x03:
00494             // Use 3 bytes:
00495             //
00496             ull = parseBuffer(inBuffer, offset, 3);
00497             if (littleEndian != nativeLittleEndian)
00498             {
00499                reverseBuffer( (unsigned char*)&ull, 8);
00500                ull >>= 40;
00501             }
00502             absValue = littleEndian
00503                      ? ull >> 4
00504                      : ull & 0x00000000000fffffULL;
00505             value = sign * (4109ULL + absValue);
00506             break;
00507 
00508          case 0x04:
00509             // Use 4 bytes:
00510             //
00511             ull = parseBuffer(inBuffer, offset, 4);
00512             if (littleEndian != nativeLittleEndian)
00513             {
00514                reverseBuffer( (unsigned char*)&ull, 8);
00515                ull >>= 32;
00516             }
00517             absValue = littleEndian
00518                      ? ull >> 4
00519                      : ull & 0x000000000fffffffULL;
00520             value = sign * (1052684ULL + absValue);
00521             break;
00522 
00523          case 0x05:
00524             // Use 5 bytes:
00525             //
00526             ull = parseBuffer(inBuffer, offset, 5);
00527             if (littleEndian != nativeLittleEndian)
00528             {
00529                reverseBuffer( (unsigned char*)&ull, 8);
00530                ull >>= 24;
00531             }
00532             absValue = littleEndian
00533                      ? ull >> 4
00534                      : ull & 0x0000000fffffffffULL;
00535             value = sign * (269488139ULL + absValue);
00536             break;
00537 
00538          case 0x06:
00539             // Use 6 bytes:
00540             //
00541             ull = parseBuffer(inBuffer, offset, 6);
00542             if (littleEndian != nativeLittleEndian)
00543             {
00544                reverseBuffer( (unsigned char*)&ull, 8);
00545                ull >>= 16;
00546             }                  
00547             absValue = littleEndian
00548                      ? ull >> 4
00549                      : ull & 0x00000fffffffffffULL;
00550             value = sign * (68988964874ULL + absValue);
00551             break;
00552 
00553          case 0x07:
00554             // Use 7 bytes:
00555             //
00556             ull = parseBuffer(inBuffer, offset, 7);
00557             if (littleEndian != nativeLittleEndian)
00558             {
00559                reverseBuffer( (unsigned char*)&ull, 8);
00560                ull >>= 8;
00561             }
00562             absValue = littleEndian
00563                      ? ull >> 4
00564                      : ull & 0x000fffffffffffffULL;
00565             value = sign * (17661175009289ULL + absValue);
00566             break;
00567 
00568          case 0x08:
00569             // Use 8 bytes:
00570             //
00571             ull = parseBuffer(inBuffer, offset, 8);
00572             if (littleEndian != nativeLittleEndian)
00573             {
00574                reverseBuffer( (unsigned char*)&ull, 8);
00575             }
00576             absValue = littleEndian
00577                      ? ull >> 4
00578                      : ull & 0x0fffffffffffffffULL;
00579             value = sign * (4521260802379784ULL + absValue);
00580             break;
00581 
00582          default:
00583                // Internal error
00584             std::ostringstream errStrm;
00585             errStrm << "BINEX MGFZI invalid size: " << size;
00586             FFStreamError err(errStrm.str() );
00587             size  = 0;
00588             GPSTK_THROW(err);
00589             break;
00590 
00591       } // switch (flag)
00592       return size;
00593    }
00594 
00595 
00596    // -------------------------------------------------------------------------
00597    size_t
00598    BinexData::MGFZI::encode(
00599       std::string&  outBuffer,
00600       size_t        offset,
00601       bool          littleEndian) const
00602    {
00603       char               buffer[MAX_BYTES];
00604       unsigned char      uc;
00605       unsigned short     us;
00606       unsigned long      ul;
00607       unsigned long long ull;
00608 
00609       if (offset > outBuffer.size() )
00610       {
00611          std::ostringstream errStrm;
00612          errStrm << "Invalid offset into BINEX MGFZI output buffer: " << offset;
00613          FFStreamError err(errStrm.str() );
00614          GPSTK_THROW(err);
00615       }
00616       
00617       long long absValue = value;
00618       if (absValue < 0)
00619       {
00620          absValue = absValue*(-1);
00621       } 
00622       
00623       unsigned char  signBit  = (value < 0) ? 0x01 : 0x00;
00624 
00625       size_t result = size;  // Default
00626       switch (size)
00627       {
00628          case 1:
00629             if (!littleEndian)
00630             {
00631                uc = (signBit << 7) | (0x0f & (unsigned char)absValue);
00632             }
00633             else
00634             {
00635                uc = (signBit << 3) | (0xf0 & ( (unsigned char)absValue << 4) );
00636             }
00637             if (uc == 0x08)
00638             {
00639                   // A valid value has been rounded to "-0"; convert to "+0".
00640                uc = 0x00;
00641             }
00642             buffer[0] = uc;
00643             break;
00644 
00645          case 2:
00646             absValue -= 14LL;
00647             if (littleEndian)
00648             {
00649                us = ( (unsigned short)signBit <<  3) | 0xfff1
00650                   & (0x0001 | (unsigned short)absValue << 4);
00651             }
00652             else
00653             {
00654                us = ((unsigned short)signBit << 15) | 0x1fff
00655                   & (0x1000 | (unsigned short)absValue);
00656             }
00657             if (littleEndian != nativeLittleEndian)
00658             {
00659                reverseBuffer( (unsigned char*)&us, 2);
00660             }
00661             std::memcpy((void*)buffer, (const void*)&us, 2);
00662             break;
00663 
00664          case 3:
00665             absValue -= 4109LL;   
00666             if (littleEndian)
00667             {
00668                ul = ((unsigned long)signBit << 3) | 0x00fffff2
00669                   & (0x00000002 | (unsigned long)absValue << 4);
00670             }
00671             else
00672             {
00673                ul = ((unsigned long)signBit << 31) | 0x2fffff00
00674                   & (0x20000000 | (unsigned long)absValue << 8);
00675             }
00676             if (littleEndian != nativeLittleEndian)
00677             {
00678                reverseBuffer( (unsigned char*)&ul, 4);
00679             }
00680             std::memcpy((void*)buffer, (const void*)&ul, 3);
00681             break;
00682 
00683          case 4:
00684             absValue -= 1052684LL;
00685             if (littleEndian)
00686             {
00687                ul = ((unsigned long)signBit << 3) | 0xfffffff3
00688                   & (0x00000003 | (unsigned long)absValue << 4);
00689             }
00690             else
00691             {
00692                ul = ((unsigned long)signBit << 31) | 0x3fffffff
00693                   & (0x30000000 | (unsigned long)absValue);
00694             }
00695             if (littleEndian != nativeLittleEndian)
00696             {
00697                reverseBuffer( (unsigned char*)&ul, 4);
00698             }
00699             memcpy((void*)buffer, (const void*)&ul, 4);
00700             break;
00701 
00702          case 5:
00703             absValue -= 269488139LL;
00704             if (littleEndian)
00705             {
00706                ull = ((unsigned long long)signBit << 3) | 0x000000fffffffff4ULL
00707                   & (0x0000000000000004ULL | (unsigned long long)absValue << 4);
00708             }
00709             else
00710             {
00711                ull = ((unsigned long long)signBit << 63) | 0x4fffffffff000000ULL
00712                   & (0x4000000000000000ULL | (unsigned long long)absValue << 24);
00713             }
00714             if (littleEndian != nativeLittleEndian)
00715             {
00716                reverseBuffer( (unsigned char*)&ull, 8);
00717             }
00718             memcpy((void*)buffer, (const void*)&ull, 5);
00719             break;
00720 
00721          case 6:
00722             absValue -= 68988964874LL;
00723             if (littleEndian)
00724             {
00725                ull = ((unsigned long long)signBit << 3) | 0x0000fffffffffff5ULL
00726                   & (0x0000000000000005ULL| (unsigned long long)absValue << 4);
00727             }
00728             else
00729             {
00730                ull = ((unsigned long long)signBit << 63) | 0x5fffffffffff0000ULL
00731                   & (0x5000000000000000ULL | (unsigned long long)absValue << 16);
00732             }
00733             if (littleEndian != nativeLittleEndian)
00734             {
00735                reverseBuffer( (unsigned char*)&ull, 8);
00736             }
00737             memcpy((void*)buffer, (const void*)&ull, 6);
00738             break;
00739 
00740          case 7:
00741             absValue -= 17661175009289LL;
00742             if (littleEndian)
00743             {
00744                ull = ((unsigned long long)signBit << 3) | 0x00fffffffffffff6ULL
00745                   & (0x0000000000000006ULL | (unsigned long long)absValue << 4);
00746             }
00747             else
00748             {
00749                ull = ((unsigned long long)signBit << 63) | 0x6fffffffffffff00ULL
00750                   & (0x6000000000000000ULL | (unsigned long long)absValue << 8);
00751             }
00752             if (littleEndian != nativeLittleEndian)
00753             {
00754                reverseBuffer( (unsigned char*)&ull, 8);
00755             }
00756             memcpy((void*)buffer, (const void*)&ull, 7);
00757             break;
00758 
00759          case 8:
00760             absValue -= 4521260802379784LL;
00761             if (littleEndian)
00762             {
00763                ull = ((unsigned long long)signBit << 3) | 0xfffffffffffffff7ULL
00764                   & (0x0000000000000007ULL | (unsigned long long)absValue << 4);
00765             }
00766             else
00767             {
00768                ull = ((unsigned long long)signBit << 63) | 0x7fffffffffffffffULL
00769                   & (0x7000000000000000ULL | (unsigned long long)absValue);
00770             }
00771             if (littleEndian != nativeLittleEndian)
00772             {
00773                reverseBuffer( (unsigned char*)&ull, 8);
00774             }
00775             memcpy((void*)buffer, (const void*)&ull, 8);
00776             break;
00777 
00778          default:
00779                // If the byte count is 0, store "no value"
00780             result    = 1;
00781             buffer[0] = 0x80;
00782 
00783       } // switch
00784       outBuffer.replace(offset, size, buffer, size);
00785       return result;
00786    }
00787 
00788 
00789    // -------------------------------------------------------------------------
00790    size_t
00791    BinexData::MGFZI::read(
00792       istream&      strm,
00793       std::string   *outBuffer,
00794       size_t        offset,
00795       bool          reverseBytes,
00796       bool          littleEndian)
00797          throw(FFStreamError)
00798    {
00799       unsigned char  buffer   [MAX_BYTES];
00800       unsigned char  flags;
00801       short          sign;
00802 
00803          // Read the flags byte
00804       strm.read((char*)&buffer[0], 1);
00805 
00806          // Isolate sign and byte-length flags
00807       flags = reverseBytes
00808             ? buffer[0] & 0x0f
00809             : (buffer[0] >> 4) & 0x0f;
00810 
00811          // Determine whether the final value is positive or negative
00812          // and determine the number of bytes comprising the MGFZI.
00813       sign = (flags & 0x08) ? -1 : 1;      
00814       size = (flags & 0x07) + 1;
00815 
00816       if (size > 1)
00817       {
00818          strm.read((char*)&buffer[1], size - 1);
00819          if (!strm.good() || strm.gcount() != size - 1)
00820          {
00821             FFStreamError err("Error reading BINEX MGFZI");
00822             GPSTK_THROW(err);
00823          }
00824       }
00825       if (reverseBytes)
00826       {
00827          reverseBuffer(buffer, size);
00828       }
00829       if (outBuffer)
00830       {
00831             // Store the as-read bytes
00832          if (offset <= outBuffer->size() )
00833          {
00834             outBuffer->replace(offset, size, (char*)&buffer[0], size);
00835          }
00836          else
00837          {
00838             std::ostringstream errStrm;
00839             errStrm << "Invalid offset into BINEX MGFZI output buffer: " << offset;
00840             FFStreamError err(errStrm.str() );
00841             GPSTK_THROW(err);
00842          }
00843       }
00844 
00845          // Decode the entire buffer
00846       std::string  tmp((const char*)&buffer[0], size);
00847       decode(tmp, size, littleEndian);
00848 
00849       return size;
00850    }
00851 
00852 
00853    // -------------------------------------------------------------------------
00854    size_t
00855    BinexData::MGFZI::write(
00856       ostream&      strm,
00857       std::string   *outBuffer,
00858       size_t        offset,
00859       bool          reverseBytes,
00860       bool          littleEndian) const
00861          throw(FFStreamError)
00862    {
00863       std::string  buffer;
00864       encode(buffer, 0, littleEndian);
00865       if (outBuffer)
00866       {
00867             // Store the as-written bytes
00868          //memcpy(outBuffer, buffer, bufferSize);
00869          if (offset <= outBuffer->size() )
00870          {
00871             outBuffer->replace(offset, size, buffer);
00872          }
00873          else
00874          {
00875             std::ostringstream errStrm;
00876             errStrm << "Invalid offset into BINEX MGFZI output buffer: " << offset;
00877             FFStreamError err(errStrm.str() );
00878             GPSTK_THROW(err);
00879          }
00880       }
00881       if (reverseBytes)
00882       {
00883          reverseBuffer(buffer);
00884       }
00885       strm.write(buffer.data(), size);
00886       if (!strm.good() )
00887       {
00888          FFStreamError err("Error writing BINEX MGFZI");
00889          GPSTK_THROW(err);             
00890       }
00891       return size;
00892    }
00893 
00894 
00895    // =========================================================================
00896    // BinexData Methods 
00897    // =========================================================================
00898 
00899    // -------------------------------------------------------------------------
00900    BinexData::BinexData()
00901    {
00902       setRecordFlags();  // Establish defaults
00903       recID = INVALID_RECORD_ID;
00904    }
00905 
00906 
00907    // -------------------------------------------------------------------------
00908    BinexData::BinexData(const BinexData& other)
00909    {
00910       *this = other;
00911    }
00912 
00913 
00914    // -------------------------------------------------------------------------
00915    BinexData::BinexData(unsigned long recordID,
00916                         unsigned char recordFlags)
00917       throw()
00918    {
00919       setRecordFlags(recordFlags);
00920       setRecordID(recordID);
00921    }
00922 
00923 
00924    // -------------------------------------------------------------------------
00925    BinexData&
00926    BinexData::operator=(const BinexData& right)
00927    {
00928       recID    = right.recID;
00929       syncByte = right.syncByte;
00930       msg      = right.msg;
00931       return *this;
00932    }
00933 
00934    // -------------------------------------------------------------------------
00935    bool BinexData::operator==(const BinexData& b) const
00936    {
00937       return (  (recID     == b.recID)
00938              && (syncByte  == b.syncByte)
00939              && (msg.compare(b.msg) == 0) );
00940    }
00941 
00942 
00943    // -------------------------------------------------------------------------
00944    BinexData&
00945    BinexData::setRecordID(unsigned long id)
00946       throw(FFStreamError)
00947    {
00948       if (id > UBNXI::MAX_VALUE)
00949       {
00950          FFStreamError err("BINEX record ID overflow");
00951          GPSTK_THROW(err);
00952       }
00953          
00954       recID = id;
00955       return *this;
00956       
00957    } // BinexData::setRecordID()
00958 
00959 
00960    // -------------------------------------------------------------------------
00961    BinexData&
00962    BinexData::setRecordFlags(unsigned char flags)
00963    {
00964          // Set all unsupported bits to 0.
00965       syncByte = flags & VALID_RECORD_FLAGS;
00966       
00967          // Set "regular CRC" bit (0x02) to the opposite of the enhanced CRC bit
00968          // and set the two leading always-on bits (0xC0).
00969       syncByte |= (flags & eEnhancedCRC) ? 0xC0 : 0xC2;
00970       
00971       return *this;
00972    }
00973 
00974    
00975    // -------------------------------------------------------------------------
00976    size_t
00977    BinexData::getRecordSize() const
00978    {
00979       size_t recSize = 1;  // Start with sync byte
00980       
00981       UBNXI r(recID);             // Add record ID
00982       recSize += r.getSize();        
00983       UBNXI m(msg.size() );       // Add message length
00984       recSize += m.getSize();        
00985       recSize += msg.size();      // Add message
00986 
00987       size_t crcLen = getCRCLength(recSize - 1);
00988 
00989       recSize += crcLen;          // Add CRC length
00990 
00991       if (syncByte & eReverseReadable)
00992       {
00993          UBNXI t(1 + r.getSize() + m.getSize() + msg.size() + crcLen);
00994          
00995          recSize += t.getSize();  // Add total reverse length
00996          
00997          recSize += 1;            // Add sync byte
00998       }
00999 
01000       return recSize;
01001    }
01002 
01003 
01004    // -------------------------------------------------------------------------
01005    BinexData&
01006    BinexData::clearMessage()
01007    {
01008       msg.resize(0);
01009       return *this;
01010 
01011    } // BinexData::clearMessage()
01012 
01013    // -------------------------------------------------------------------------
01014    BinexData&
01015    BinexData::ensureMessageCapacity(size_t cap)
01016       throw(FFStreamError)
01017    {
01018       if (cap > UBNXI::MAX_VALUE)
01019       {
01020          std::ostringstream errStrm;
01021          errStrm << "Requested message length exceeds allowable maximum: " << cap;
01022          InvalidParameter ip(errStrm.str() );
01023          GPSTK_THROW(ip);
01024       }
01025       msg.reserve(cap);
01026       return *this;
01027 
01028    }  // BinexData::ensureMessageCapacity()
01029 
01030    // -------------------------------------------------------------------------
01031    BinexData&
01032    BinexData::updateMessageData(
01033       size_t&      offset,
01034       const UBNXI& data)
01035          throw(FFStreamError, InvalidParameter)
01036    {
01037       bool   littleEndian  = ( (syncByte & eBigEndian) == 0) ? true : false;
01038       ensureMessageCapacity(offset + data.getSize() );
01039       offset += data.encode(msg, offset, littleEndian);
01040       return *this;
01041 
01042    }  // BinexData::updateMessageData()
01043 
01044    // -------------------------------------------------------------------------
01045    BinexData&
01046    BinexData::updateMessageData(
01047       size_t&      offset,
01048       const MGFZI& data)
01049          throw(FFStreamError, InvalidParameter)
01050    {
01051       bool   littleEndian  = ( (syncByte & eBigEndian) == 0) ? true : false;
01052       ensureMessageCapacity(offset + data.getSize() );
01053       offset += data.encode(msg, offset, littleEndian);
01054       return *this;
01055 
01056    }  // BinexData::updateMessageData()
01057 
01058    // -------------------------------------------------------------------------
01059    BinexData&
01060    BinexData::updateMessageData(
01061       size_t&            offset,
01062       const std::string& data,
01063       size_t             size)
01064          throw(FFStreamError, InvalidParameter)
01065    {
01066       ensureMessageCapacity(offset + size);
01067       if (size > data.size() )
01068       {
01069          std::ostringstream errStrm;
01070          errStrm << "Invalid data size: " << size;
01071          InvalidParameter ip(errStrm.str() );
01072          GPSTK_THROW(ip);
01073       }
01074       msg.replace(offset, size, data, 0, size);
01075       offset += size;
01076       return *this;
01077 
01078    }  // BinexData::updateMessageData()
01079 
01080    // -------------------------------------------------------------------------
01081    BinexData&
01082    BinexData::updateMessageData(
01083       size_t&     offset,
01084       const char  *data,
01085       size_t      size)
01086          throw(FFStreamError, InvalidParameter)
01087    {
01088       ensureMessageCapacity(offset + size);
01089       msg.replace(offset, size, data, size);
01090       offset += size;
01091       return *this;
01092    }
01093 
01094    // -------------------------------------------------------------------------
01095    void
01096    BinexData::extractMessageData(
01097       size_t& offset,
01098       UBNXI&  data)
01099          throw(FFStreamError, InvalidParameter)
01100    {
01101       if (offset > msg.size() )
01102       {
01103          std::ostringstream errStrm;
01104          errStrm << "Message buffer offset invalid: " << offset;
01105          InvalidParameter ip(errStrm.str() );
01106          GPSTK_THROW(ip);
01107       }
01108       bool littleEndian  = ( (syncByte & eBigEndian) == 0) ? true : false;
01109       offset += data.decode(msg, offset, littleEndian);
01110 
01111    }  // BinexData::extractMessageData()
01112 
01113    // -------------------------------------------------------------------------
01114    void
01115    BinexData::extractMessageData(
01116       size_t& offset,
01117       MGFZI&  data)
01118          throw(FFStreamError, InvalidParameter)
01119    {
01120       if (offset > msg.size() )
01121       {
01122          std::ostringstream errStrm;
01123          errStrm << "Message buffer offset invalid: " << offset;
01124          InvalidParameter ip(errStrm.str() );
01125          GPSTK_THROW(ip);
01126       }
01127       bool littleEndian  = ( (syncByte & eBigEndian) == 0) ? true : false;
01128       offset += data.decode(msg, offset, littleEndian);
01129 
01130    }  // BinexData::extractMessageData()
01131 
01132    // -------------------------------------------------------------------------
01133    void
01134    BinexData::extractMessageData(
01135       size_t&      offset,
01136       std::string& data,
01137       size_t       size) const
01138          throw(InvalidParameter)
01139    {
01140       if (offset + size > msg.size() )
01141       {
01142          std::ostringstream errStrm;
01143          errStrm << "Message buffer offset invalid: " << offset;
01144          InvalidParameter ip(errStrm.str() );
01145          GPSTK_THROW(ip);
01146       } 
01147       data.assign(msg, offset, size);
01148       offset += size;
01149 
01150    }  // BinexData::extractMessageData()
01151 
01152    // -------------------------------------------------------------------------
01153    void
01154    BinexData::reallyPutRecord(FFStream& ffs) const
01155       throw(std::exception, FFStreamError, 
01156             StringUtils::StringException)
01157    {
01158       //std::cout << "BinexData::reallyPutRecord: ENTER" << std::endl;
01159 
01160       BinexStream* strm = dynamic_cast<BinexStream*>(&ffs);
01161       if (NULL == strm)
01162       {
01163          FFStreamError e("Attempt to read a BinexData object"
01164                          " from a non-BinexStream FFStream.");
01165          GPSTK_THROW(e);
01166       }
01167 
01168       try
01169       {
01170          unsigned char syncTail;
01171          if (!isHeadSyncByteValid(syncByte, syncTail) )
01172          {
01173             std::ostringstream errStrm;
01174             errStrm << "Invalid BINEX synchronization byte: "
01175                     << static_cast<uint16_t>(syncByte);
01176             FFStreamError err(errStrm.str() );
01177             GPSTK_THROW(err);
01178          }
01179             // Buffer, etc. for non-msg data
01180          std::string    headBuf;
01181          size_t         bufLen = 0;  // Total buffer data length
01182          size_t         crcLen = 0;  // Length of calculated CRC
01183 
01184          bool    littleEndian = (syncByte&eBigEndian)==0 ? true : false;
01185 
01186          headBuf.reserve(9);  // 1+4+4
01187 
01188             // Copy sync byte to header buffer
01189          headBuf.append(1, syncByte);
01190          bufLen += 1;
01191 
01192             // Copy record ID to header buffer
01193          UBNXI r(recID);
01194          bufLen += r.encode(headBuf, bufLen, littleEndian);
01195 
01196             // Copy message length to header buffer
01197          UBNXI m(msg.size() );
01198          bufLen += m.encode(headBuf, bufLen, littleEndian);
01199 
01200             // Write header buffer and message to the output stream
01201          strm->write(headBuf.data(), headBuf.size() );
01202          strm->write(msg.data(), msg.size() );
01203 
01204             // Calculate CRC and store it in the tail buffer
01205          std::string  tailBuf;
01206          tailBuf.reserve(21);  // 16+4+1
01207          headBuf.erase(0, 1);  // Exclude sync byte from CRC calculation
01208          getCRC(headBuf, msg, tailBuf);
01209          crcLen = tailBuf.size();
01210 
01211             // Copy enhanced CRC record items into the tail buffer
01212          if (syncByte & eReverseReadable)
01213          {
01214             UBNXI recLen(1 + r.getSize() + m.getSize() + msg.size() + crcLen);
01215             recLen.encode(tailBuf, crcLen, littleEndian);
01216             reverseBuffer(tailBuf, crcLen);
01217             tailBuf.append(1, syncTail);
01218          }
01219 
01220             // Write the tail buffer to the output stream.
01221          strm->write(tailBuf.data(), tailBuf.size() );
01222       }
01223       catch(std::exception& exc)
01224       {
01225          FFStreamError err(exc.what());
01226          GPSTK_THROW(err);
01227       }
01228       catch(...)
01229       {
01230          FFStreamError err("Unknown exception");
01231          GPSTK_THROW(err);
01232       }
01233 
01234       if (strm->fail() || strm->bad())
01235       {
01236          FFStreamError err("Error writing data");
01237          GPSTK_THROW(err);
01238       }
01239 
01240       //std::cout << "BinexData::reallyPutRecord: EXIT" << std::endl;
01241    }
01242 
01243    // -------------------------------------------------------------------------
01244    void BinexData::reallyGetRecord(FFStream& ffs) 
01245       throw(std::exception, FFStreamError, StringUtils::StringException)
01246    {
01247       //std::cout << "BinexData::reallyGetRecord: ENTER" << std::endl;
01248 
01249       BinexStream* strm = dynamic_cast<BinexStream*>(&ffs);
01250       if (NULL == strm)
01251       {
01252          FFStreamError e("Attempt to read a BinexData object"
01253                                 " from a non-BinexStream FFStream.");
01254          GPSTK_THROW(e);
01255       }
01256 
01257       size_t        offset            = 0;
01258       
01259       std::string   crcBuf;
01260       size_t        crcBufLen = 0;
01261       
01262       unsigned char expectedSyncByte;
01263       std::string   expectedCrc;
01264       unsigned char crc               [16];
01265       size_t        crcLen            = 0;
01266       unsigned char syncBuf;
01267 
01268       try
01269       {
01270          strm->read((char*)&syncBuf, 1);  // Read synchronization byte
01271       }
01272       catch (std::exception &e)
01273       {
01274          if ( (strm->gcount() == 0) && strm->eof() )
01275          {
01276                // Process as EOF
01277             EndOfFile err("EOF encountered");
01278             GPSTK_THROW(err);
01279          }
01280          else
01281          {
01282                // Rethrow if not EOF
01283             FFStreamError err(e.what() );
01284             GPSTK_THROW(err);
01285          }
01286       }
01287 
01288       try
01289       {
01290          if (isHeadSyncByteValid(syncBuf, expectedSyncByte) )
01291          {
01292             syncByte = syncBuf;
01293 
01294                // Process the BINEX record forward (not in reverse)
01295             bool littleEndian = (syncByte & eBigEndian) == 0 ? true : false;
01296 
01297             UBNXI uRecID;
01298             crcBufLen += uRecID.read(*strm, &crcBuf, crcBufLen, false, littleEndian);
01299             setRecordID((unsigned long)uRecID);
01300 
01301             UBNXI uMsgLen;
01302             crcBufLen += uMsgLen.read(*strm, &crcBuf, crcBufLen, false, littleEndian);
01303 
01304             unsigned long msgLen  = (unsigned long)uMsgLen;
01305 
01306                // Read directly into the memory buffer of a vector.  This is OK
01307                // because, unlike a string, a vector is stored contiguously.
01308                // The vector's memory will be reclaimed in all exit conditions
01309                // since the vector is allocated on the stack.
01310             std::vector<char>  msgBuf(msgLen);
01311             strm->read((char*)&msgBuf[0], msgLen);
01312             if (!strm->good() || (strm->gcount() != msgLen) )
01313             {
01314                FFStreamError err("Incomplete BINEX record message");
01315                GPSTK_THROW(err);
01316             }
01317             msg.assign((char*)&msgBuf[0], msgLen);
01318 
01319                // Check CRC - first calculate expected, then read actual,
01320                // then compare.
01321             getCRC(crcBuf, msg, expectedCrc);
01322             crcLen = expectedCrc.size();
01323 
01324             strm->read( (char*)crc, crcLen);
01325             if (!strm->good() || (strm->gcount() != crcLen) )
01326             {
01327                FFStreamError err("Error reading BINEX CRC");
01328                GPSTK_THROW(err);
01329             }
01330             if (std::memcmp(crc, expectedCrc.data(), crcLen) )
01331             {
01332                FFStreamError err("Bad BINEX CRC");
01333                GPSTK_THROW(err);
01334             }
01335          }
01336          else if (isTailSyncByteValid(syncBuf, expectedSyncByte) )
01337          {
01338                // Process the BINEX record in reverse
01339             bool littleEndian = (expectedSyncByte & eBigEndian) == 0 ? true : false;
01340 
01341             UBNXI r, m, b;
01342             b.read(*strm, NULL, 0, false, littleEndian);
01343             unsigned long revRecSize = (unsigned long)b;
01344 
01345                // Read the entire remainder of the record into memory
01346             std::vector<char>  revRecVec(revRecSize);
01347             strm->read( (char*)&revRecVec[0], revRecSize);
01348             if (!strm->good() || (strm->gcount() != revRecSize) )
01349             {
01350                FFStreamError err("Incomplete BINEX record message");
01351                GPSTK_THROW(err);
01352             }
01353             std::string revRecBuf( (char*)&revRecVec[0], revRecSize);
01354             reverseBuffer(revRecBuf, revRecSize);
01355 
01356             if (revRecBuf[0] != expectedSyncByte)
01357             {
01358                FFStreamError err("BINEX head/tail synchronization byte mismatch");
01359                GPSTK_THROW(err);
01360             }
01361             syncByte = expectedSyncByte;
01362             offset += 1;
01363 
01364             offset += r.decode(revRecBuf, offset, littleEndian);
01365             setRecordID((unsigned long)r);
01366             // @TODO - Check against revRecSize
01367             offset += m.decode(revRecBuf, offset, littleEndian);
01368             // @TODO - Check against revRecSize
01369 
01370             msg.assign(revRecBuf, offset, (unsigned long)m);
01371             offset += msg.size();
01372 
01373                // Check CRC - first calculate expected, then compare to actual.
01374             getCRC(revRecBuf.substr(1, r.getSize() + m.getSize() ), msg, expectedCrc);
01375             crcLen = expectedCrc.size();
01376             
01377             if ( (offset + crcLen != revRecSize)
01378                || expectedCrc.compare(revRecBuf.substr(offset, crcLen) ) )
01379             {
01380                FFStreamError err("Bad BINEX CRC");
01381                GPSTK_THROW(err);
01382             }
01383          }
01384          else
01385          {
01386             std::ostringstream errStrm;
01387             errStrm << "Invalid BINEX synchronization byte: "
01388                     << static_cast<uint16_t>(syncBuf);
01389             FFStreamError err(errStrm.str() );
01390             GPSTK_THROW(err);
01391          }
01392 
01393       }
01394       catch(FFStreamError& exc)
01395       {
01396          GPSTK_RETHROW(exc);
01397       }
01398       catch(std::exception& exc)
01399       {
01400          FFStreamError err(exc.what() );
01401          GPSTK_THROW(err);
01402       }
01403       catch(...)
01404       {
01405          FFStreamError err("Unknown exception");
01406          GPSTK_THROW(err);
01407       }
01408 
01409       //std::cout << "BinexData::reallyGetRecord: EXIT" << std::endl;
01410    }
01411 
01412    void
01413    BinexData::getCRC(const std::string&  head,
01414                      const std::string&  message,
01415                      std::string&        crc) const
01416    {
01417       size_t crcDataLen = head.size() + message.size();
01418       size_t crcLen     = 0;
01419       unsigned long crcTmp = 0;
01420 
01421       if (crcDataLen >= 1048576)
01422       {
01423             // @TODO - Use 16-byte CRC (128-bit MD5 checksum)
01424          crcLen  = 16;
01425       }
01426       else // (crcLen < 1048576)
01427       {
01428          if (syncByte & eEnhancedCRC)
01429          {
01430             if (crcDataLen < 128)
01431             {
01432                   // Use 2-byte CRC (CRC16)
01433                BinUtils::CRCParam params(BinUtils::CRC16);
01434                crcTmp = BinUtils::computeCRC((const unsigned char*)head.data(),
01435                                              head.size(),
01436                                              params);
01437                params.initial = crcTmp;
01438                crcTmp = BinUtils::computeCRC((const unsigned char*)message.data(),
01439                                              message.size(),
01440                                              params);
01441                crcLen = 2;
01442             }
01443             else
01444             {
01445                   // Use 4-byte CRC (CRC32)
01446                BinUtils::CRCParam params(BinUtils::CRC32);
01447                crcTmp = BinUtils::computeCRC((const unsigned char*)head.data(),
01448                                              head.size(),
01449                                              params);
01450                params.initial = crcTmp;
01451                crcTmp = BinUtils::computeCRC((const unsigned char*)message.data(),
01452                                              message.size(),
01453                                              params);
01454                crcLen = 4;
01455             }
01456          }
01457          else // Regular CRC
01458          {
01459             if (crcDataLen < 128)
01460             {
01461                   // Use 1-byte checksum: 8-bit XOR of all bytes
01462                size_t b;
01463                const char *ptr;
01464                ptr = head.data();
01465                for (b = head.size(); b > 0 ; b--, ptr++)
01466                {
01467                   crcTmp ^= *ptr;
01468                }
01469                ptr = message.data();
01470                for (b = message.size(); b > 0 ; b--, ptr++)
01471                {
01472                   crcTmp ^= *ptr;
01473                }
01474                crcLen = 1;
01475             }
01476             else if (crcDataLen < 4096)
01477             {
01478                   // Use 2-byte CRC (CRC16)
01479                BinUtils::CRCParam params(BinUtils::CRC16);
01480                crcTmp = BinUtils::computeCRC((const unsigned char*)head.data(),
01481                                              head.size(),
01482                                              params);
01483                params.initial = crcTmp;
01484                crcTmp = BinUtils::computeCRC((const unsigned char*)message.data(),
01485                                              message.size(),
01486                                              params);
01487                crcLen = 2;
01488             }
01489             else
01490             {
01491                   // Use 4-byte CRC (CRC32)
01492                BinUtils::CRCParam params(BinUtils::CRC32);
01493                crcTmp = BinUtils::computeCRC((const unsigned char*)head.data(),
01494                                              head.size(),
01495                                              params);
01496                params.initial = crcTmp;
01497                crcTmp = BinUtils::computeCRC((const unsigned char*)message.data(),
01498                                              message.size(),
01499                                              params);
01500                crcLen = 4;
01501             }
01502          } // Regular CRC
01503          
01504             // Copy the CRC into the output
01505          if (!nativeLittleEndian)
01506          {
01507             BinUtils::twiddle(crcTmp);
01508          }
01509          crc.assign( (const char*)&crcTmp, crcLen);
01510 
01511       } // (crcLen < 1048576)
01512 
01513    }  // BinexData::getCRC()
01514 
01515    // -------------------------------------------------------------------------
01516    size_t
01517    BinexData::getCRCLength(size_t crcDataLen) const
01518    {
01519       size_t crcLen = 0;
01520 
01521       if (crcDataLen >= 1048576)
01522       {
01523          crcLen  = 16;
01524       }
01525       else // (crcLen < 1048576)
01526       {
01527          if (syncByte & eEnhancedCRC)
01528          {
01529             if (crcDataLen < 128)
01530             {
01531                crcLen = 2;
01532             }
01533             else
01534             {
01535                crcLen = 4;
01536             }
01537          }
01538          else // Regular CRC
01539          {
01540             if (crcDataLen < 128)
01541             {
01542                crcLen = 1;
01543             }
01544             else if (crcDataLen < 4096)
01545             {
01546                crcLen = 2;
01547             }
01548             else
01549             {
01550                crcLen = 4;
01551             }
01552 
01553          } // Regular CRC
01554          
01555       } // (crcLen < 1048576)
01556 
01557       return crcLen;
01558    }
01559 
01560    // -------------------------------------------------------------------------
01561    bool
01562    BinexData::isHeadSyncByteValid(unsigned char  headSync,
01563                                   unsigned char& expectedTailSync) const
01564    {
01565       switch (headSync)
01566       {
01567          case 0xC2: // Fall through ...
01568          case 0xE2: // Fall through ...
01569          case 0xC8: // Fall through ...
01570          case 0xE8:
01571             expectedTailSync = 0x00; // No tail sync byte
01572             break;
01573 
01574          case 0xD2:
01575             expectedTailSync = 0xB4;
01576             break;
01577 
01578          case 0xF2:
01579             expectedTailSync = 0xB0;
01580             break;
01581 
01582          case 0xD8:
01583             expectedTailSync = 0xE4;
01584             break;
01585 
01586          case 0xF8:
01587             expectedTailSync = 0xE0;
01588             break;
01589 
01590          default:
01591             return false; // Invalid head synchronization byte
01592       }
01593       return true;
01594    }
01595 
01596    // -------------------------------------------------------------------------
01597    bool
01598    BinexData::isTailSyncByteValid(unsigned char  tailSync,
01599                                   unsigned char& expectedHeadSync) const
01600    {
01601       switch (tailSync)
01602       {
01603          case 0xB4:
01604             expectedHeadSync = 0xD2;
01605             break;
01606 
01607          case 0xB0:
01608             expectedHeadSync = 0xF2;
01609             break;
01610 
01611          case 0xE4:
01612             expectedHeadSync = 0xD8;
01613             break;
01614 
01615          case 0xE0:
01616             expectedHeadSync = 0xF8;
01617             break;
01618 
01619          default:
01620             return false; // Invalid tail synchronization byte
01621       }
01622       return true;
01623    }
01624 
01625    // -------------------------------------------------------------------------
01626    unsigned long long
01627    BinexData::parseBuffer(const std::string&  buffer,
01628                           size_t              offset,
01629                           size_t              size)
01630       throw(FFStreamError)
01631    {
01632       unsigned long long value = 0;
01633       if (size > sizeof(value) )
01634       {
01635          FFStreamError err("Invalid data size parsing BINEX data buffer");
01636          GPSTK_THROW(err);
01637       }
01638       if (offset + size > buffer.size() )
01639       {
01640          FFStreamError err("Invalid offset parsing BINEX data buffer");
01641          GPSTK_THROW(err);
01642       }
01643       char* valp = (char*)&value;
01644       for (size_t i = 0; i < size; i++, valp++)
01645       {
01646          *valp = buffer[offset + i];
01647       }
01648       if (!nativeLittleEndian)
01649       {
01650          value >>= ( (sizeof(value) - size) << 3);
01651       }
01652       return value;
01653    }
01654 
01655    // -------------------------------------------------------------------------
01656    void
01657    BinexData::reverseBuffer(unsigned char  *buffer,
01658                             size_t         bufferLength)
01659    {
01660       unsigned char tmp;
01661       for (size_t i = 1; i <= (bufferLength >> 1); i++)
01662       {
01663          tmp = buffer[i - 1];
01664          buffer[i - 1] = buffer[bufferLength - i];
01665          buffer[bufferLength - i] = tmp;
01666       }
01667    }
01668 
01669    // -------------------------------------------------------------------------
01670    void
01671    BinexData::reverseBuffer(std::string& buffer, size_t offset, size_t n)
01672    {
01673       if ( (offset < 0) || (offset > buffer.size() ) )
01674       {
01675          FFStreamError err("Invalid offset reversing BINEX data buffer");
01676          GPSTK_THROW(err);
01677       }
01678       size_t back = (n == std::string::npos) ? buffer.size() : offset + n;
01679       if ( (back < 0) || (back > buffer.size() ) )
01680       {
01681          FFStreamError err("Invalid size reversing BINEX data buffer");
01682          GPSTK_THROW(err);
01683       }
01684       --back;
01685       unsigned char tmp;
01686       while (offset < back)
01687       {
01688          tmp            = buffer[offset];
01689          buffer[offset] = buffer[back];
01690          buffer[back]   = tmp;
01691          ++offset;
01692          --back;
01693       }
01694    }
01695 
01696    // -------------------------------------------------------------------------
01697    void BinexData::dump(ostream& s) const
01698    {
01699       std::cout << "RecordID:    " << recID     << std::endl;
01700       std::cout << "SyncByte:    " << (unsigned short)syncByte << std::endl;
01701       std::cout << "MessageLen:  " << msg.size() << std::endl;
01702       std::cout << "MessageData: " << std::endl;
01703       for (size_t i = 0; i < msg.size(); i++)
01704       {
01705          unsigned short s = msg[i];
01706          std::cout << s << " ";
01707       }
01708       std::cout << std::endl;
01709    }
01710 
01711 
01712 }  // namespace gpstk

Generated on Wed Feb 8 03:30:57 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1