00001 #pragma ident "$Id: BinexData.cpp 1895 2009-05-12 19:34:29Z afarris $"
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
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
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
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
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;
00278 }
00279 }
00280 if (outBuffer)
00281 {
00282
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
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
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
00434 size = 0;
00435 value = 0;
00436 return 0;
00437 }
00438
00439 flags = littleEndian
00440 ? inBuffer[offset] & 0x0f
00441 : (inBuffer[offset] >> 4) & 0x0f;
00442
00443
00444 sign = (flags & 0x08) ? -1 : 1;
00445
00446
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
00461
00462 ull = parseBuffer(inBuffer, offset, 1);
00463 absValue = littleEndian
00464 ? ull >> 4
00465 : ull & 0x0000000fULL;
00466 if (sign == -1 && absValue == 0)
00467 {
00468
00469 size = 0;
00470
00471 }
00472 else
00473 {
00474 value = sign * absValue;
00475 }
00476 break;
00477
00478 case 0x02:
00479
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
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
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
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
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
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
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
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 }
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;
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
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
00780 result = 1;
00781 buffer[0] = 0x80;
00782
00783 }
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
00804 strm.read((char*)&buffer[0], 1);
00805
00806
00807 flags = reverseBytes
00808 ? buffer[0] & 0x0f
00809 : (buffer[0] >> 4) & 0x0f;
00810
00811
00812
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
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
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
00868
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
00897
00898
00899
00900 BinexData::BinexData()
00901 {
00902 setRecordFlags();
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 }
00958
00959
00960
00961 BinexData&
00962 BinexData::setRecordFlags(unsigned char flags)
00963 {
00964
00965 syncByte = flags & VALID_RECORD_FLAGS;
00966
00967
00968
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;
00980
00981 UBNXI r(recID);
00982 recSize += r.getSize();
00983 UBNXI m(msg.size() );
00984 recSize += m.getSize();
00985 recSize += msg.size();
00986
00987 size_t crcLen = getCRCLength(recSize - 1);
00988
00989 recSize += crcLen;
00990
00991 if (syncByte & eReverseReadable)
00992 {
00993 UBNXI t(1 + r.getSize() + m.getSize() + msg.size() + crcLen);
00994
00995 recSize += t.getSize();
00996
00997 recSize += 1;
00998 }
00999
01000 return recSize;
01001 }
01002
01003
01004
01005 BinexData&
01006 BinexData::clearMessage()
01007 {
01008 msg.resize(0);
01009 return *this;
01010
01011 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
01151
01152
01153 void
01154 BinexData::reallyPutRecord(FFStream& ffs) const
01155 throw(std::exception, FFStreamError,
01156 StringUtils::StringException)
01157 {
01158
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
01180 std::string headBuf;
01181 size_t bufLen = 0;
01182 size_t crcLen = 0;
01183
01184 bool littleEndian = (syncByte&eBigEndian)==0 ? true : false;
01185
01186 headBuf.reserve(9);
01187
01188
01189 headBuf.append(1, syncByte);
01190 bufLen += 1;
01191
01192
01193 UBNXI r(recID);
01194 bufLen += r.encode(headBuf, bufLen, littleEndian);
01195
01196
01197 UBNXI m(msg.size() );
01198 bufLen += m.encode(headBuf, bufLen, littleEndian);
01199
01200
01201 strm->write(headBuf.data(), headBuf.size() );
01202 strm->write(msg.data(), msg.size() );
01203
01204
01205 std::string tailBuf;
01206 tailBuf.reserve(21);
01207 headBuf.erase(0, 1);
01208 getCRC(headBuf, msg, tailBuf);
01209 crcLen = tailBuf.size();
01210
01211
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
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
01241 }
01242
01243
01244 void BinexData::reallyGetRecord(FFStream& ffs)
01245 throw(std::exception, FFStreamError, StringUtils::StringException)
01246 {
01247
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);
01271 }
01272 catch (std::exception &e)
01273 {
01274 if ( (strm->gcount() == 0) && strm->eof() )
01275 {
01276
01277 EndOfFile err("EOF encountered");
01278 GPSTK_THROW(err);
01279 }
01280 else
01281 {
01282
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
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
01307
01308
01309
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
01320
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
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
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
01367 offset += m.decode(revRecBuf, offset, littleEndian);
01368
01369
01370 msg.assign(revRecBuf, offset, (unsigned long)m);
01371 offset += msg.size();
01372
01373
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
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
01424 crcLen = 16;
01425 }
01426 else
01427 {
01428 if (syncByte & eEnhancedCRC)
01429 {
01430 if (crcDataLen < 128)
01431 {
01432
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
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
01458 {
01459 if (crcDataLen < 128)
01460 {
01461
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
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
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 }
01503
01504
01505 if (!nativeLittleEndian)
01506 {
01507 BinUtils::twiddle(crcTmp);
01508 }
01509 crc.assign( (const char*)&crcTmp, crcLen);
01510
01511 }
01512
01513 }
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
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
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 }
01554
01555 }
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:
01568 case 0xE2:
01569 case 0xC8:
01570 case 0xE8:
01571 expectedTailSync = 0x00;
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;
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;
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 }