00001 #pragma ident "$Id: BinexData.cpp 3143 2012-06-19 16:19:50Z snelsen $"
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 "BinexData.hpp"
00033 #include "BinexStream.hpp"
00034
00035 using namespace std;
00036
00037 namespace gpstk
00038 {
00039
00040
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
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
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
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
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;
00277 }
00278 }
00279 if (outBuffer)
00280 {
00281
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
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
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
00433 size = 0;
00434 value = 0;
00435 return 0;
00436 }
00437
00438 flags = littleEndian
00439 ? inBuffer[offset] & 0x0f
00440 : (inBuffer[offset] >> 4) & 0x0f;
00441
00442
00443 sign = (flags & 0x08) ? -1 : 1;
00444
00445
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
00460
00461 ull = parseBuffer(inBuffer, offset, 1);
00462 absValue = littleEndian
00463 ? ull >> 4
00464 : ull & 0x0000000fULL;
00465 if (sign == -1 && absValue == 0)
00466 {
00467
00468 size = 0;
00469
00470 }
00471 else
00472 {
00473 value = sign * absValue;
00474 }
00475 break;
00476
00477 case 0x02:
00478
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
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
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
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
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
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
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
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 }
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;
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
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
00779 result = 1;
00780 buffer[0] = 0x80;
00781
00782 }
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
00803 strm.read((char*)&buffer[0], 1);
00804
00805
00806 flags = reverseBytes
00807 ? buffer[0] & 0x0f
00808 : (buffer[0] >> 4) & 0x0f;
00809
00810
00811
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
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
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
00867
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
00896
00897
00898
00899 BinexData::BinexData()
00900 {
00901 setRecordFlags();
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 }
00957
00958
00959
00960 BinexData&
00961 BinexData::setRecordFlags(unsigned char flags)
00962 {
00963
00964 syncByte = flags & VALID_RECORD_FLAGS;
00965
00966
00967
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;
00979
00980 UBNXI r(recID);
00981 recSize += r.getSize();
00982 UBNXI m(msg.size() );
00983 recSize += m.getSize();
00984 recSize += msg.size();
00985
00986 size_t crcLen = getCRCLength(recSize - 1);
00987
00988 recSize += crcLen;
00989
00990 if (syncByte & eReverseReadable)
00991 {
00992 UBNXI t(1 + r.getSize() + m.getSize() + msg.size() + crcLen);
00993
00994 recSize += t.getSize();
00995
00996 recSize += 1;
00997 }
00998
00999 return recSize;
01000 }
01001
01002
01003
01004 BinexData&
01005 BinexData::clearMessage()
01006 {
01007 msg.resize(0);
01008 return *this;
01009
01010 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
01150
01151
01152 void
01153 BinexData::reallyPutRecord(FFStream& ffs) const
01154 throw(std::exception, FFStreamError,
01155 StringUtils::StringException)
01156 {
01157
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
01179 std::string headBuf;
01180 size_t bufLen = 0;
01181 size_t crcLen = 0;
01182
01183 bool littleEndian = (syncByte&eBigEndian)==0 ? true : false;
01184
01185 headBuf.reserve(9);
01186
01187
01188 headBuf.append(1, syncByte);
01189 bufLen += 1;
01190
01191
01192 UBNXI r(recID);
01193 bufLen += r.encode(headBuf, bufLen, littleEndian);
01194
01195
01196 UBNXI m(msg.size() );
01197 bufLen += m.encode(headBuf, bufLen, littleEndian);
01198
01199
01200 strm->write(headBuf.data(), headBuf.size() );
01201 strm->write(msg.data(), msg.size() );
01202
01203
01204 std::string tailBuf;
01205 tailBuf.reserve(21);
01206 headBuf.erase(0, 1);
01207 getCRC(headBuf, msg, tailBuf);
01208 crcLen = tailBuf.size();
01209
01210
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
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
01240 }
01241
01242
01243 void BinexData::reallyGetRecord(FFStream& ffs)
01244 throw(std::exception, FFStreamError, StringUtils::StringException)
01245 {
01246
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);
01270 }
01271 catch (std::exception &e)
01272 {
01273 if ( (strm->gcount() == 0) && strm->eof() )
01274 {
01275
01276 EndOfFile err("EOF encountered");
01277 GPSTK_THROW(err);
01278 }
01279 else
01280 {
01281
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
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
01306
01307
01308
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
01319
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
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
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
01366 offset += m.decode(revRecBuf, offset, littleEndian);
01367
01368
01369 msg.assign(revRecBuf, offset, (unsigned long)m);
01370 offset += msg.size();
01371
01372
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
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
01423 crcLen = 16;
01424 }
01425 else
01426 {
01427 if (syncByte & eEnhancedCRC)
01428 {
01429 if (crcDataLen < 128)
01430 {
01431
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
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
01457 {
01458 if (crcDataLen < 128)
01459 {
01460
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
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
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 }
01502
01503
01504 if (!nativeLittleEndian)
01505 {
01506 BinUtils::twiddle(crcTmp);
01507 }
01508 crc.assign( (const char*)&crcTmp, crcLen);
01509
01510 }
01511
01512 }
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
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
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 }
01553
01554 }
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:
01567 case 0xE2:
01568 case 0xC8:
01569 case 0xE8:
01570 expectedTailSync = 0x00;
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;
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;
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 }