BinexData.cpp

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

Generated on Fri May 24 03:31:03 2013 for GPS ToolKit Software Library by  doxygen 1.3.9.1