BinexData.cpp
Go to the documentation of this file.
1 //==============================================================================
2 //
3 // This file is part of GNSSTk, the ARL:UT GNSS Toolkit.
4 //
5 // The GNSSTk is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation; either version 3.0 of the License, or
8 // any later version.
9 //
10 // The GNSSTk is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with GNSSTk; if not, write to the Free Software Foundation,
17 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 //
19 // This software was developed by Applied Research Laboratories at the
20 // University of Texas at Austin.
21 // Copyright 2004-2022, The Board of Regents of The University of Texas System
22 //
23 //==============================================================================
24 
25 //==============================================================================
26 //
27 // This software was developed by Applied Research Laboratories at the
28 // University of Texas at Austin, under contract to an agency or agencies
29 // within the U.S. Department of Defense. The U.S. Government retains all
30 // rights to use, duplicate, distribute, disclose, or release this software.
31 //
32 // Pursuant to DoD Directive 523024
33 //
34 // DISTRIBUTION STATEMENT A: This software has been approved for public
35 // release, distribution is unlimited.
36 //
37 //==============================================================================
38 
44 #include "BinexData.hpp"
45 #include "BinexStream.hpp"
46 #include <stdlib.h>
47 #include <string.h>
48 
49 using namespace std;
50 
51 namespace gnsstk
52 {
53  #if BYTE_ORDER == LITTLE_ENDIAN
54  const bool BinexData::nativeLittleEndian = true;
55  #else
56  const bool BinexData::nativeLittleEndian = false;
57  #endif
58 
59  const BinexData::RecordID BinexData::INVALID_RECORD_ID = 0xFFFFFFFF;
60  const BinexData::SyncByte BinexData::DEFAULT_RECORD_FLAGS = 0x20;
61  const BinexData::SyncByte BinexData::VALID_RECORD_FLAGS = 0x38;
62 
63  const unsigned long BinexData::UBNXI::MIN_VALUE = 0;
64  const unsigned long BinexData::UBNXI::MAX_VALUE = 536870911;
65  const unsigned char BinexData::UBNXI::MAX_BYTES = 4;
66 
67  const long long BinexData::MGFZI::MIN_VALUE = -1157442765409226759LL;
68  const long long BinexData::MGFZI::MAX_VALUE = 1157442765409226759LL;
69  const unsigned char BinexData::MGFZI::MAX_BYTES = 8;
70 
71 
72  // =========================================================================
73  // BinexData::UBNXI Methods
74  // =========================================================================
75 
76  // -------------------------------------------------------------------------
77  BinexData::UBNXI::UBNXI()
78  {
79  value = 0;
80  size = 1;
81  }
82 
83  // -------------------------------------------------------------------------
84  BinexData::UBNXI::UBNXI(unsigned long ul)
85  {
86  if (ul < 128)
87  {
88  size = 1;
89  }
90  else if (ul < 16384)
91  {
92  size = 2;
93  }
94  else if (ul < 2097152)
95  {
96  size = 3;
97  }
98  else if (ul < 536870912)
99  {
100  size = 4;
101  }
102  else
103  {
104  value = 0;
105  size = 0;
106 
107  std::ostringstream errStrm;
108  errStrm << "BINEX UBNXI overflow: " << ul;
109  FFStreamError err(errStrm.str() );
110  GNSSTK_THROW(err);
111  }
112 
113  value = ul;
114  }
115 
116 
117  // -------------------------------------------------------------------------
118  size_t
119  BinexData::UBNXI::decode(
120  const std::string& inBuffer,
121  size_t offset,
122  bool littleEndian)
123  {
124  if (offset > inBuffer.size() )
125  {
126  std::ostringstream errStrm;
127  errStrm << "Invalid offset into BINEX UBNXI input buffer: " << offset;
128  FFStreamError err(errStrm.str() );
129  GNSSTK_THROW(err);
130  }
131  bool more = true;
132  for (size = 0, value = 0L; (size < MAX_BYTES) && more; size++)
133  {
134  unsigned char mask = (size < 3) ? 0x7f : 0xff;
135  if (littleEndian)
136  {
137  value |= ( (unsigned long)inBuffer[offset + size] & mask) << (7 * size);
138  }
139  else
140  {
141  value <<= (size < 3) ? 7 : 8;
142  value |= ( (unsigned long)inBuffer[offset + size] & mask);
143  }
144  if ( (inBuffer[offset + size] & 0x80) != 0x80)
145  {
146  more = false;
147  }
148  }
149  return size;
150  }
151 
152 
153  // -------------------------------------------------------------------------
154  size_t
155  BinexData::UBNXI::encode(
156  std::string& outBuffer,
157  size_t offset,
158  bool littleEndian) const
159  {
160  uint8_t uc;
161  uint16_t us, us1;
162  uint32_t ul, ul1, ul2, ul3;
163 
164  if (offset > outBuffer.size() )
165  {
166  std::ostringstream errStrm;
167  errStrm << "Invalid offset into BINEX UBNXI output buffer: " << offset;
168  FFStreamError err(errStrm.str() );
169  GNSSTK_THROW(err);
170  }
171  switch (size)
172  {
173  case 1:
174  uc = (uint8_t)value;
175  outBuffer.replace(offset, size, reinterpret_cast<char*>(&uc), size);
176  break;
177 
178  case 2:
179  us = (uint16_t)value;
180  us1 = 0x7f00 & (us << 1);
181  us &= 0x007f;
182  us |= us1;
183 
184  if (littleEndian != nativeLittleEndian)
185  {
186  // Allow encoding to non-native byte ordering
187  reverseBytes(us);
188  }
189  us |= nativeLittleEndian ? 0x0080 : 0x8000;
190 
191  outBuffer.replace(offset, size, reinterpret_cast<char*>(&us), size);
192  break;
193 
194  case 3:
195  ul = (uint32_t)value;
196  ul2 = 0x007f0000 & (ul << 2);
197  ul1 = 0x00007f00 & (ul << 1);
198  ul &= 0x0000007f;
199  ul |= ul1 | ul2;
200 
201  if (littleEndian != nativeLittleEndian)
202  {
203  // Allow encoding to non-native byte ordering
204  reverseBytes(ul);
205  ul >>= 8;
206  }
207  if (nativeLittleEndian)
208  {
209  ul |= 0x00008080;
210  }
211  else
212  {
213  ul |= 0x00808000;
214  ul <<= 8;
215  }
216 
217  outBuffer.replace(offset, size, reinterpret_cast<char*>(&ul), size);
218  break;
219 
220  case 4:
221  if (littleEndian)
222  {
223  ul = (uint32_t)value;
224  ul3 = 0xff000000 & (ul << 3);
225  ul2 = 0x007f0000 & (ul << 2);
226  ul1 = 0x00007f00 & (ul << 1);
227  ul &= 0x0000007f;
228  ul |= ul1 | ul2 | ul3;
229 
230  if (!nativeLittleEndian)
231  {
232  // Allow encoding to non-native byte ordering
233  reverseBytes(ul);
234  }
235  }
236  else
237  {
238  ul = (uint32_t)value;
239  ul2 = 0x7f000000 & (ul << 2);
240  ul1 = 0x007f0000 & (ul << 1);
241  ul &= 0x00007fff;
242  ul |= ul1 | ul2;
243 
244  if (nativeLittleEndian)
245  {
246  // Allow encoding to non-native byte ordering
247  reverseBytes(ul);
248  }
249  }
250  ul |= nativeLittleEndian ? 0x00808080 : 0x80808000;
251 
252  outBuffer.replace(offset, size, reinterpret_cast<char*>(&ul), size);
253  break;
254 
255  default:
256  std::ostringstream errStrm;
257  errStrm << "BINEX UBNXI invalid size: " << size;
258  FFStreamError err(errStrm.str() );
259  GNSSTK_THROW(err);
260  break;
261  }
262  return size;
263  }
264 
265 
266  // -------------------------------------------------------------------------
267  size_t
268  BinexData::UBNXI::read(
269  istream& strm,
270  std::string *outBuffer,
271  size_t offset,
272  bool reverseBytes,
273  bool littleEndian)
274  {
275  unsigned char mask = 0;
276  char buffer [MAX_BYTES];
277 
278  if (reverseBytes)
279  {
281  }
282  else
283  {
284  bool more = true;
285  for (size = 0, value = 0L; (size < MAX_BYTES) && more; size++)
286  {
287  mask = (size < 3) ? 0x7f : 0xff;
288 
289  strm.read(&buffer[size], 1);
290  if (!strm.good() )
291  {
292  FFStreamError err("Error reading BINEX UBNXI");
293  GNSSTK_THROW(err);
294  }
295  if (littleEndian)
296  {
297  value |= ( (unsigned long)buffer[size] & mask) << (size * 7);
298  }
299  else
300  {
301  value <<= (size < 3) ? 7 : 8;
302  value |= (unsigned long)buffer[size] & mask;
303  }
304  if ( (buffer[size] & 0x80) != 0x80)
305  {
306  more = false; // End of UBNXI detected - exit loop
307  }
308  }
309  if (outBuffer)
310  {
311  // Store the as-read bytes
312  if (offset <= outBuffer->size() )
313  {
314  outBuffer->replace(offset, size, buffer, size);
315  }
316  else
317  {
318  std::ostringstream errStrm;
319  errStrm << "Invalid offset into BINEX UBNXI output buffer: " << offset;
320  FFStreamError err(errStrm.str() );
321  GNSSTK_THROW(err);
322  }
323  }
324  }
325  return size;
326  }
327 
328 
329  // -------------------------------------------------------------------------
330  size_t
331  BinexData::UBNXI::write(
332  ostream& strm,
333  std::string *outBuffer,
334  size_t offset,
335  bool reverseBytes,
336  bool littleEndian) const
337  {
338  std::string buffer;
339  encode(buffer, 0, littleEndian);
340  if (outBuffer)
341  {
342  if (offset <= outBuffer->size() )
343  {
344  // Store the as written bytes
345  outBuffer->replace(offset, size, buffer);
346  }
347  else
348  {
349  std::ostringstream errStrm;
350  errStrm << "Invalid offset into BINEX UBNXI output buffer: " << offset;
351  FFStreamError err(errStrm.str() );
352  GNSSTK_THROW(err);
353  }
354  }
355  if (reverseBytes)
356  {
357  reverseBuffer(buffer);
358  }
359  strm.write(buffer.data(), size);
360  if (!strm.good() )
361  {
362  FFStreamError err("Error writing BINEX UBNXI");
363  GNSSTK_THROW(err);
364  }
365  return size;
366  }
367 
368  // =========================================================================
369  // BinexData::MGFZI Methods
370  // =========================================================================
371 
372  // -------------------------------------------------------------------------
373  BinexData::MGFZI::MGFZI()
374  {
375  value = 0;
376  size = 1;
377  }
378 
379 
380  // -------------------------------------------------------------------------
381  BinexData::MGFZI::MGFZI(long long ll)
382  {
383  value = ll;
384  long long absValue = llabs(ll);
385 
386  if (absValue < 16LL)
387  {
388  size = 1;
389  }
390  else if (absValue < 4110LL)
391  {
392  size = 2;
393  }
394  else if (absValue < 1052685LL)
395  {
396  size = 3;
397  }
398  else if (absValue < 269488140LL)
399  {
400  size = 4;
401  }
402  else if (absValue < 68988964875LL)
403  {
404  size = 5;
405  }
406  else if (absValue < 17661175009290LL)
407  {
408  size = 6;
409  }
410  else if (absValue < 4521260802379785LL)
411  {
412  size = 7;
413  }
414  else if (absValue <= BinexData::MGFZI::MAX_VALUE)
415  {
416  size = 8;
417  }
418  else
419  {
420  value = 0LL;
421  size = 0;
422 
423  std::ostringstream errStrm;
424  errStrm << "BINEX MGFZI overflow: " << ll;
425  FFStreamError err(errStrm.str() );
426  GNSSTK_THROW(err);
427  }
428  }
429 
430 
431  // -------------------------------------------------------------------------
432  size_t
433  BinexData::MGFZI::decode(
434  const std::string& inBuffer,
435  size_t offset,
436  bool littleEndian)
437  {
438  long long absValue = 0;
439  unsigned char flags;
440  uint64_t ull;
441  short sign;
442 
443  if (offset > inBuffer.size() )
444  {
445  std::ostringstream errStrm;
446  errStrm << "Invalid offset into BINEX MGFZI input buffer: " << offset;
447  FFStreamError err(errStrm.str() );
448  GNSSTK_THROW(err);
449  }
450 
451  if (inBuffer.size() == 0)
452  {
453  // Nothing to decode
454  size = 0;
455  value = 0;
456  return 0;
457  }
458  // Isolate sign and byte-length flags
459  flags = littleEndian
460  ? inBuffer[offset] & 0x0f
461  : (inBuffer[offset] >> 4) & 0x0f;
462 
463  // Determine whether the final value is positive or negative.
464  sign = (flags & 0x08) ? -1 : 1;
465 
466  // Handle varying byte lengths
467  size = (flags & 0x07) + 1;
468  if (size > inBuffer.size() )
469  {
470  std::ostringstream errStrm;
471  errStrm << "BINEX MGFZI is too large for the supplied decode buffer: "
472  << "MGFZI size = " << size << " , buffer size = "
473  << inBuffer.size();
474  FFStreamError err(errStrm.str() );
475  GNSSTK_THROW(err);
476  }
477 
478  switch (size)
479  {
480  case 0x01:
481  // Use 1 byte:
482  //
483  ull = parseBuffer(inBuffer, offset, 1);
484  absValue = littleEndian
485  ? ull >> 4
486  : ull & 0x0000000fULL;
487  if (sign == -1 && absValue == 0)
488  {
489  // "-0" reserved for "no data" indicator
490  size = 0;
491  // todo - throw
492  }
493  else
494  {
495  value = sign * absValue;
496  }
497  break;
498 
499  case 0x02:
500  // Use 2 bytes:
501  //
502  ull = parseBuffer(inBuffer, offset, 2);
503  if (littleEndian != nativeLittleEndian)
504  {
505  reverseBytes(ull);
506  ull >>= 48;
507  }
508  absValue = littleEndian
509  ? ull >> 4
510  : ull & 0x0000000000000fffULL;
511  value = sign * (14ULL + absValue);
512  break;
513 
514  case 0x03:
515  // Use 3 bytes:
516  //
517  ull = parseBuffer(inBuffer, offset, 3);
518  if (littleEndian != nativeLittleEndian)
519  {
520  reverseBytes(ull);
521  ull >>= 40;
522  }
523  absValue = littleEndian
524  ? ull >> 4
525  : ull & 0x00000000000fffffULL;
526  value = sign * (4109ULL + absValue);
527  break;
528 
529  case 0x04:
530  // Use 4 bytes:
531  //
532  ull = parseBuffer(inBuffer, offset, 4);
533  if (littleEndian != nativeLittleEndian)
534  {
535  reverseBytes(ull);
536  ull >>= 32;
537  }
538  absValue = littleEndian
539  ? ull >> 4
540  : ull & 0x000000000fffffffULL;
541  value = sign * (1052684ULL + absValue);
542  break;
543 
544  case 0x05:
545  // Use 5 bytes:
546  //
547  ull = parseBuffer(inBuffer, offset, 5);
548  if (littleEndian != nativeLittleEndian)
549  {
550  reverseBytes(ull);
551  ull >>= 24;
552  }
553  absValue = littleEndian
554  ? ull >> 4
555  : ull & 0x0000000fffffffffULL;
556  value = sign * (269488139ULL + absValue);
557  break;
558 
559  case 0x06:
560  // Use 6 bytes:
561  //
562  ull = parseBuffer(inBuffer, offset, 6);
563  if (littleEndian != nativeLittleEndian)
564  {
565  reverseBytes(ull);
566  ull >>= 16;
567  }
568  absValue = littleEndian
569  ? ull >> 4
570  : ull & 0x00000fffffffffffULL;
571  value = sign * (68988964874ULL + absValue);
572  break;
573 
574  case 0x07:
575  // Use 7 bytes:
576  //
577  ull = parseBuffer(inBuffer, offset, 7);
578  if (littleEndian != nativeLittleEndian)
579  {
580  reverseBytes(ull);
581  ull >>= 8;
582  }
583  absValue = littleEndian
584  ? ull >> 4
585  : ull & 0x000fffffffffffffULL;
586  value = sign * (17661175009289ULL + absValue);
587  break;
588 
589  case 0x08:
590  // Use 8 bytes:
591  //
592  ull = parseBuffer(inBuffer, offset, 8);
593  if (littleEndian != nativeLittleEndian)
594  {
595  reverseBytes(ull);
596  }
597  absValue = littleEndian
598  ? ull >> 4
599  : ull & 0x0fffffffffffffffULL;
600  value = sign * (4521260802379784ULL + absValue);
601  break;
602 
603  default:
604  // Internal error
605  std::ostringstream errStrm;
606  errStrm << "BINEX MGFZI invalid size: " << size;
607  FFStreamError err(errStrm.str() );
608  size = 0;
609  GNSSTK_THROW(err);
610  break;
611 
612  } // switch (flag)
613  return size;
614  }
615 
616 
617  // -------------------------------------------------------------------------
618  size_t
619  BinexData::MGFZI::encode(
620  std::string& outBuffer,
621  size_t offset,
622  bool littleEndian) const
623  {
624  char buffer[MAX_BYTES];
625  uint8_t uc;
626  uint16_t us;
627  uint32_t ul;
628  uint64_t ull;
629 
630  if (offset > outBuffer.size() )
631  {
632  std::ostringstream errStrm;
633  errStrm << "Invalid offset into BINEX MGFZI output buffer: " << offset;
634  FFStreamError err(errStrm.str() );
635  GNSSTK_THROW(err);
636  }
637 
638  long long absValue = llabs(value);
639  unsigned char signBit = (value < 0) ? 0x01 : 0x00;
640 
641  size_t result = size; // Default
642  switch (size)
643  {
644  case 1:
645  if (!littleEndian)
646  {
647  uc = (signBit << 7) | (0x0f & (unsigned char)absValue);
648  }
649  else
650  {
651  uc = (signBit << 3) | (0xf0 & ( (unsigned char)absValue << 4) );
652  }
653  if (uc == 0x08)
654  {
655  // A valid value has been rounded to "-0"; convert to "+0".
656  uc = 0x00;
657  }
658  buffer[0] = uc;
659  break;
660 
661  case 2:
662  absValue -= 14LL;
663  if (littleEndian)
664  {
665  us = ( (unsigned short)signBit << 3)
666  | (0xfff1 & (0x0001 | (unsigned short)absValue << 4) );
667  }
668  else
669  {
670  us = ((unsigned short)signBit << 15)
671  | (0x1fff & (0x1000 | (unsigned short)absValue) );
672  }
673  if (littleEndian != nativeLittleEndian)
674  {
675  reverseBytes(us);
676  }
677  memcpy((void*)buffer, (const void*)&us, 2);
678  break;
679 
680  case 3:
681  absValue -= 4109LL;
682  if (littleEndian)
683  {
684  ul = ((unsigned long)signBit << 3)
685  | (0x00fffff2 & (0x00000002 | (unsigned long)absValue << 4) );
686  }
687  else
688  {
689  ul = ((unsigned long)signBit << 31)
690  | (0x2fffff00 & (0x20000000 | (unsigned long)absValue << 8) );
691  }
692  if (littleEndian != nativeLittleEndian)
693  {
694  reverseBytes(ul);
695  }
696  memcpy((void*)buffer, (const void*)&ul, 3);
697  break;
698 
699  case 4:
700  absValue -= 1052684LL;
701  if (littleEndian)
702  {
703  ul = ((unsigned long)signBit << 3)
704  | (0xfffffff3 & (0x00000003 | (unsigned long)absValue << 4) );
705  }
706  else
707  {
708  ul = ((unsigned long)signBit << 31)
709  | (0x3fffffff & (0x30000000 | (unsigned long)absValue) );
710  }
711  if (littleEndian != nativeLittleEndian)
712  {
713  reverseBytes(ul);
714  }
715  memcpy((void*)buffer, (const void*)&ul, 4);
716  break;
717 
718  case 5:
719  absValue -= 269488139LL;
720  if (littleEndian)
721  {
722  ull = ((unsigned long long)signBit << 3)
723  | (0x000000fffffffff4ULL & (0x0000000000000004ULL | (unsigned long long)absValue << 4) );
724  }
725  else
726  {
727  ull = ((unsigned long long)signBit << 63)
728  | (0x4fffffffff000000ULL & (0x4000000000000000ULL | (unsigned long long)absValue << 24) );
729  }
730  if (littleEndian != nativeLittleEndian)
731  {
732  reverseBytes(ull);
733  }
734  memcpy((void*)buffer, (const void*)&ull, 5);
735  break;
736 
737  case 6:
738  absValue -= 68988964874LL;
739  if (littleEndian)
740  {
741  ull = ((unsigned long long)signBit << 3)
742  | (0x0000fffffffffff5ULL & (0x0000000000000005ULL | (unsigned long long)absValue << 4) );
743  }
744  else
745  {
746  ull = ((unsigned long long)signBit << 63)
747  | (0x5fffffffffff0000ULL & (0x5000000000000000ULL | (unsigned long long)absValue << 16) );
748  }
749  if (littleEndian != nativeLittleEndian)
750  {
751  reverseBytes(ull);
752  }
753  memcpy((void*)buffer, (const void*)&ull, 6);
754  break;
755 
756  case 7:
757  absValue -= 17661175009289LL;
758  if (littleEndian)
759  {
760  ull = ((unsigned long long)signBit << 3)
761  | (0x00fffffffffffff6ULL & (0x0000000000000006ULL | (unsigned long long)absValue << 4) );
762  }
763  else
764  {
765  ull = ((unsigned long long)signBit << 63)
766  | (0x6fffffffffffff00ULL & (0x6000000000000000ULL | (unsigned long long)absValue << 8) );
767  }
768  if (littleEndian != nativeLittleEndian)
769  {
770  reverseBytes(ull);
771  }
772  memcpy((void*)buffer, (const void*)&ull, 7);
773  break;
774 
775  case 8:
776  absValue -= 4521260802379784LL;
777  if (littleEndian)
778  {
779  ull = ((unsigned long long)signBit << 3)
780  | (0xfffffffffffffff7ULL & (0x0000000000000007ULL | (unsigned long long)absValue << 4) );
781  }
782  else
783  {
784  ull = ((unsigned long long)signBit << 63)
785  | (0x7fffffffffffffffULL & (0x7000000000000000ULL | (unsigned long long)absValue) );
786  }
787  if (littleEndian != nativeLittleEndian)
788  {
789  reverseBytes(ull);
790  }
791  memcpy((void*)buffer, (const void*)&ull, 8);
792  break;
793 
794  default:
795  // If the byte count is 0, store "no value"
796  result = 1;
797  buffer[0] = (char)0x80;
798  break;
799  } // switch
800  outBuffer.replace(offset, size, buffer, size);
801  return result;
802  }
803 
804 
805  // -------------------------------------------------------------------------
806  size_t
807  BinexData::MGFZI::read(
808  istream& strm,
809  std::string *outBuffer,
810  size_t offset,
811  bool reverseBytes,
812  bool littleEndian)
813  {
814  std::string buffer(" ");
815  unsigned char flags;
816 
817  // Read the flags byte
818  strm.read((char*)&buffer[0], 1);
819 
820  // Isolate sign and byte-length flags
821  flags = reverseBytes
822  ? buffer[0] & 0x0f
823  : (buffer[0] >> 4) & 0x0f;
824 
825  // Determine the number of bytes comprising the MGFZI.
826  size = (flags & 0x07) + 1;
827 
828  if (size > 1)
829  {
830  buffer.resize(size);
831  strm.read((char*)&buffer[1], size - 1);
832  if (!strm.good() || ((size_t)strm.gcount() + 1 != size))
833  {
834  FFStreamError err("Error reading BINEX MGFZI");
835  GNSSTK_THROW(err);
836  }
837  }
838  if (reverseBytes)
839  {
840  reverseBuffer(buffer);
841  }
842  if (outBuffer)
843  {
844  // Store the as-read bytes
845  if (offset <= outBuffer->size() )
846  {
847  outBuffer->replace(offset, size, buffer, 0, size);
848  }
849  else
850  {
851  std::ostringstream errStrm;
852  errStrm << "Invalid offset into BINEX MGFZI output buffer: "
853  << offset;
854  FFStreamError err(errStrm.str() );
855  GNSSTK_THROW(err);
856  }
857  }
858 
859  // Decode the entire buffer
860  std::string tmp((const char*)&buffer[0], size);
861  decode(tmp, size, littleEndian);
862 
863  return size;
864  }
865 
866 
867  // -------------------------------------------------------------------------
868  size_t
869  BinexData::MGFZI::write(
870  ostream& strm,
871  std::string *outBuffer,
872  size_t offset,
873  bool reverseBytes,
874  bool littleEndian) const
875  {
876  std::string buffer;
877  encode(buffer, 0, littleEndian);
878  if (outBuffer)
879  {
880  // Store the as-written bytes
881  //memcpy(outBuffer, buffer, bufferSize);
882  if (offset <= outBuffer->size() )
883  {
884  outBuffer->replace(offset, size, buffer);
885  }
886  else
887  {
888  std::ostringstream errStrm;
889  errStrm << "Invalid offset into BINEX MGFZI output buffer: " << offset;
890  FFStreamError err(errStrm.str() );
891  GNSSTK_THROW(err);
892  }
893  }
894  if (reverseBytes)
895  {
896  reverseBuffer(buffer);
897  }
898  strm.write(buffer.data(), size);
899  if (!strm.good() )
900  {
901  FFStreamError err("Error writing BINEX MGFZI");
902  GNSSTK_THROW(err);
903  }
904  return size;
905  }
906 
907 
908  // =========================================================================
909  // BinexData Methods
910  // =========================================================================
911 
912  // -------------------------------------------------------------------------
913  BinexData::BinexData()
914  {
915  setRecordFlags(); // Establish defaults
916  recID = INVALID_RECORD_ID;
917  }
918 
919 
920  // -------------------------------------------------------------------------
921  BinexData::BinexData(const BinexData& other)
922  {
923  *this = other;
924  }
925 
926 
927  // -------------------------------------------------------------------------
928  BinexData::BinexData(RecordID recordID,
929  SyncByte recordFlags)
930  noexcept
931  {
932  setRecordFlags(recordFlags);
933  setRecordID(recordID);
934  }
935 
936 
937  // -------------------------------------------------------------------------
938  BinexData&
939  BinexData::operator=(const BinexData& right)
940  {
941  recID = right.recID;
942  syncByte = right.syncByte;
943  msg = right.msg;
944  return *this;
945  }
946 
947  // -------------------------------------------------------------------------
948  bool BinexData::operator==(const BinexData& b) const
949  {
950  return ( (recID == b.recID)
951  && (syncByte == b.syncByte)
952  && (msg.compare(b.msg) == 0) );
953  }
954 
955 
956  // -------------------------------------------------------------------------
957  BinexData&
958  BinexData::setRecordID(RecordID id)
959  {
960  if (id > UBNXI::MAX_VALUE)
961  {
962  FFStreamError err("BINEX record ID overflow");
963  GNSSTK_THROW(err);
964  }
965 
966  recID = id;
967  return *this;
968 
969  } // BinexData::setRecordID()
970 
971 
972  // -------------------------------------------------------------------------
973  BinexData&
974  BinexData::setRecordFlags(SyncByte flags)
975  {
976  // Set all unsupported bits to 0.
977  syncByte = flags & VALID_RECORD_FLAGS;
978 
979  // Set "regular CRC" bit (0x02) to the opposite of the enhanced CRC bit
980  // and set the two leading always-on bits (0xC0).
981  syncByte |= (flags & eEnhancedCRC) ? 0xC0 : 0xC2;
982 
983  return *this;
984  }
985 
986 
987  // -------------------------------------------------------------------------
988  size_t
989  BinexData::getRecordSize() const
990  {
991  size_t headLen = getHeadLength(); // Start with head length
992  size_t recSize = headLen + msg.size(); // Add message length
993  size_t crcLen = getCRCLength(recSize - 1);
994 
995  recSize += crcLen; // Add CRC length
996 
997  if (syncByte & eReverseReadable)
998  {
999  UBNXI t(headLen + msg.size() + crcLen);
1000 
1001  recSize += t.getSize(); // Add total reverse length
1002 
1003  recSize += 1; // Add sync byte
1004  }
1005 
1006  return recSize;
1007  }
1008 
1009 
1010  // -------------------------------------------------------------------------
1011  BinexData&
1012  BinexData::clearMessage()
1013  {
1014  msg.resize(0);
1015  return *this;
1016 
1017  } // BinexData::clearMessage()
1018 
1019  // -------------------------------------------------------------------------
1020  BinexData&
1021  BinexData::ensureMessageCapacity(size_t cap)
1022  {
1023  if (cap > UBNXI::MAX_VALUE)
1024  {
1025  std::ostringstream errStrm;
1026  errStrm << "Requested message length exceeds allowable maximum: " << cap;
1027  InvalidParameter ip(errStrm.str() );
1028  GNSSTK_THROW(ip);
1029  }
1030  msg.reserve(cap);
1031  return *this;
1032 
1033  } // BinexData::ensureMessageCapacity()
1034 
1035  // -------------------------------------------------------------------------
1036  size_t
1037  BinexData::getHeadLength() const
1038  {
1039  size_t headLen = 1; // Start with sync byte
1040 
1041  UBNXI r(recID); // Add record ID
1042  headLen += r.getSize();
1043  UBNXI m(msg.size() ); // Add message length
1044  headLen += m.getSize();
1045 
1046  return headLen;
1047  }
1048 
1049  // -------------------------------------------------------------------------
1050  BinexData&
1051  BinexData::updateMessageData(
1052  size_t& offset,
1053  const UBNXI& data)
1054  {
1055  bool littleEndian = ( (syncByte & eBigEndian) == 0) ? true : false;
1056  ensureMessageCapacity(offset + data.getSize() );
1057  offset += data.encode(msg, offset, littleEndian);
1058  return *this;
1059 
1060  } // BinexData::updateMessageData()
1061 
1062  // -------------------------------------------------------------------------
1063  BinexData&
1064  BinexData::updateMessageData(
1065  size_t& offset,
1066  const MGFZI& data)
1067  {
1068  bool littleEndian = ( (syncByte & eBigEndian) == 0) ? true : false;
1069  ensureMessageCapacity(offset + data.getSize() );
1070  offset += data.encode(msg, offset, littleEndian);
1071  return *this;
1072 
1073  } // BinexData::updateMessageData()
1074 
1075  // -------------------------------------------------------------------------
1076  BinexData&
1077  BinexData::updateMessageData(
1078  size_t& offset,
1079  const std::string& data,
1080  size_t size)
1081  {
1082  ensureMessageCapacity(offset + size);
1083  if (size > data.size() )
1084  {
1085  std::ostringstream errStrm;
1086  errStrm << "Invalid data size: " << size;
1087  InvalidParameter ip(errStrm.str() );
1088  GNSSTK_THROW(ip);
1089  }
1090  msg.replace(offset, size, data, 0, size);
1091  offset += size;
1092  return *this;
1093 
1094  } // BinexData::updateMessageData()
1095 
1096  // -------------------------------------------------------------------------
1097  BinexData&
1098  BinexData::updateMessageData(
1099  size_t& offset,
1100  const char *data,
1101  size_t size)
1102  {
1103  ensureMessageCapacity(offset + size);
1104  msg.replace(offset, size, data, size);
1105  offset += size;
1106  return *this;
1107  }
1108 
1109  // -------------------------------------------------------------------------
1110  void
1111  BinexData::extractMessageData(
1112  size_t& offset,
1113  UBNXI& data)
1114  {
1115  if (offset > msg.size() )
1116  {
1117  std::ostringstream errStrm;
1118  errStrm << "Message buffer offset invalid: " << offset;
1119  InvalidParameter ip(errStrm.str() );
1120  GNSSTK_THROW(ip);
1121  }
1122  bool littleEndian = ( (syncByte & eBigEndian) == 0) ? true : false;
1123  offset += data.decode(msg, offset, littleEndian);
1124 
1125  } // BinexData::extractMessageData()
1126 
1127  // -------------------------------------------------------------------------
1128  void
1129  BinexData::extractMessageData(
1130  size_t& offset,
1131  MGFZI& data)
1132  {
1133  if (offset > msg.size() )
1134  {
1135  std::ostringstream errStrm;
1136  errStrm << "Message buffer offset invalid: " << offset;
1137  InvalidParameter ip(errStrm.str() );
1138  GNSSTK_THROW(ip);
1139  }
1140  bool littleEndian = ( (syncByte & eBigEndian) == 0) ? true : false;
1141  offset += data.decode(msg, offset, littleEndian);
1142 
1143  } // BinexData::extractMessageData()
1144 
1145  // -------------------------------------------------------------------------
1146  void
1147  BinexData::extractMessageData(
1148  size_t& offset,
1149  std::string& data,
1150  size_t size) const
1151  {
1152  if (offset + size > msg.size() )
1153  {
1154  std::ostringstream errStrm;
1155  errStrm << "Message buffer offset invalid: " << offset;
1156  InvalidParameter ip(errStrm.str() );
1157  GNSSTK_THROW(ip);
1158  }
1159  data.assign(msg, offset, size);
1160  offset += size;
1161 
1162  } // BinexData::extractMessageData()
1163 
1164  // -------------------------------------------------------------------------
1165  void
1166  BinexData::reallyPutRecord(FFStream& ffs) const
1167  {
1168  if (NULL == dynamic_cast<BinexStream*>(&ffs))
1169  {
1170  FFStreamError e("Attempt to read a BinexData object"
1171  " from a non-BinexStream FFStream.");
1172  GNSSTK_THROW(e);
1173  }
1174  putRecord(dynamic_cast<std::ostream&>(ffs));
1175  }
1176 
1177  // -------------------------------------------------------------------------
1178  void
1179  BinexData::putRecord(std::ostream& strm) const
1180  {
1181  try
1182  {
1183  SyncByte syncTail;
1184  if (!isHeadSyncByteValid(syncByte, syncTail) )
1185  {
1186  std::ostringstream errStrm;
1187  errStrm << "Invalid BINEX synchronization byte: "
1188  << static_cast<uint16_t>(syncByte);
1189  FFStreamError err(errStrm.str() );
1190  GNSSTK_THROW(err);
1191  }
1192  // Buffer, etc. for non-msg data
1193  std::string headBuf;
1194  size_t bufLen = 0; // Total buffer data length
1195  size_t crcLen = 0; // Length of calculated CRC
1196 
1197  bool littleEndian = (syncByte&eBigEndian)==0 ? true : false;
1198 
1199  headBuf.reserve(9); // 1+4+4
1200 
1201  // Copy sync byte to header buffer
1202  headBuf.append(1, syncByte);
1203  bufLen += 1;
1204 
1205  // Copy record ID to header buffer
1206  UBNXI r(recID);
1207  bufLen += r.encode(headBuf, bufLen, littleEndian);
1208 
1209  // Copy message length to header buffer
1210  UBNXI m(msg.size() );
1211  bufLen += m.encode(headBuf, bufLen, littleEndian);
1212 
1213  // Write header buffer and message to the output stream
1214  strm.write(headBuf.data(), headBuf.size() );
1215  strm.write(msg.data(), msg.size() );
1216 
1217  // Calculate CRC and store it in the tail buffer
1218  std::string tailBuf;
1219  tailBuf.reserve(21); // 16+4+1
1220  headBuf.erase(0, 1); // Exclude sync byte from CRC calculation
1221  getCRC(headBuf, msg, tailBuf);
1222  crcLen = tailBuf.size();
1223 
1224  // Copy enhanced CRC record items into the tail buffer
1225  if (syncByte & eReverseReadable)
1226  {
1227  UBNXI recLen(1 + r.getSize() + m.getSize() + msg.size() + crcLen);
1228  recLen.encode(tailBuf, crcLen, littleEndian);
1229  reverseBuffer(tailBuf, crcLen);
1230  tailBuf.append(1, syncTail);
1231  }
1232 
1233  // Write the tail buffer to the output stream.
1234  strm.write(tailBuf.data(), tailBuf.size() );
1235  }
1236  catch(std::exception& exc)
1237  {
1238  FFStreamError err(exc.what());
1239  GNSSTK_THROW(err);
1240  }
1241  catch(...)
1242  {
1243  FFStreamError err("Unknown exception");
1244  GNSSTK_THROW(err);
1245  }
1246 
1247  if (strm.fail() || strm.bad())
1248  {
1249  FFStreamError err("Error writing data");
1250  GNSSTK_THROW(err);
1251  }
1252  }
1253 
1254  // -------------------------------------------------------------------------
1255  void BinexData::reallyGetRecord(FFStream& ffs)
1256  {
1257  if (NULL == dynamic_cast<BinexStream*>(&ffs))
1258  {
1259  FFStreamError e("Attempt to read a BinexData object"
1260  " from a non-BinexStream FFStream.");
1261  GNSSTK_THROW(e);
1262  }
1263  getRecord(dynamic_cast<std::istream&>(ffs));
1264  }
1265 
1266  // -------------------------------------------------------------------------
1267  size_t BinexData::getRecord(std::istream& strm)
1268  {
1269  size_t offset = 0;
1270 
1271  std::string crcBuf;
1272  size_t crcBufLen = 0;
1273 
1274  SyncByte expectedSyncByte;
1275  std::string expectedCrc;
1276  unsigned char crc [16];
1277  size_t crcLen = 0;
1278  SyncByte syncBuf;
1279  std::istream::pos_type stpos, endpos;
1280 
1281  try
1282  {
1283  stpos = endpos = strm.tellg();
1284  strm.read((char*)&syncBuf, 1); // Read synchronization byte
1285  }
1286  catch (std::exception &e)
1287  {
1288  if ( (strm.gcount() == 0) && strm.eof() )
1289  {
1290  // Process as EOF
1291  EndOfFile err("EOF encountered");
1292  GNSSTK_THROW(err);
1293  }
1294  else
1295  {
1296  // Rethrow if not EOF
1297  FFStreamError err(e.what() );
1298  GNSSTK_THROW(err);
1299  }
1300  }
1301 
1302  try
1303  {
1304  if (isHeadSyncByteValid(syncBuf, expectedSyncByte) )
1305  {
1306  syncByte = syncBuf;
1307 
1308  // Process the BINEX record forward (not in reverse)
1309  bool littleEndian = (syncByte & eBigEndian) == 0 ? true : false;
1310 
1311  UBNXI uRecID;
1312  crcBufLen += uRecID.read(strm, &crcBuf, crcBufLen, false, littleEndian);
1313  setRecordID( (RecordID)uRecID);
1314 
1315  UBNXI uMsgLen;
1316  crcBufLen += uMsgLen.read(strm, &crcBuf, crcBufLen, false, littleEndian);
1317 
1318  unsigned long msgLen = (unsigned long)uMsgLen;
1319 
1320  // Read directly into the memory buffer of a vector. This is OK
1321  // because, unlike a string, a vector is stored contiguously.
1322  // The vector's memory will be reclaimed in all exit conditions
1323  // since the vector is allocated on the stack.
1324  std::vector<char> msgBuf(msgLen);
1325  strm.read((char*)&msgBuf[0], msgLen);
1326  if (!strm.good() || ((unsigned long)strm.gcount() != msgLen) )
1327  {
1328  FFStreamError err("Incomplete BINEX record message");
1329  GNSSTK_THROW(err);
1330  }
1331  msg.assign((char*)&msgBuf[0], msgLen);
1332 
1333  // Check CRC - first calculate expected, then read actual,
1334  // then compare.
1335  getCRC(crcBuf, msg, expectedCrc);
1336  crcLen = expectedCrc.size();
1337 
1338  strm.read( (char*)crc, crcLen);
1339  if (!strm.good() || ((size_t)strm.gcount() != crcLen) )
1340  {
1341  FFStreamError err("Error reading BINEX CRC");
1342  GNSSTK_THROW(err);
1343  }
1344  if (memcmp(crc, expectedCrc.data(), crcLen) )
1345  {
1346  FFStreamError err("Bad BINEX CRC");
1347  GNSSTK_THROW(err);
1348  }
1349  }
1350  else if (isTailSyncByteValid(syncBuf, expectedSyncByte) )
1351  {
1352  // Process the BINEX record in reverse
1353  bool littleEndian = (expectedSyncByte & eBigEndian) == 0 ? true : false;
1354 
1355  UBNXI r, m, b;
1356  b.read(strm, NULL, 0, false, littleEndian);
1357  unsigned long revRecSize = (unsigned long)b;
1358 
1359  // Read the entire remainder of the record into memory
1360  std::vector<char> revRecVec(revRecSize);
1361  strm.read( (char*)&revRecVec[0], revRecSize);
1362  if (!strm.good() || ((unsigned long)strm.gcount() != revRecSize) )
1363  {
1364  FFStreamError err("Incomplete BINEX record message");
1365  GNSSTK_THROW(err);
1366  }
1367  std::string revRecBuf( (char*)&revRecVec[0], revRecSize);
1368  reverseBuffer(revRecBuf, revRecSize);
1369 
1370  if (revRecBuf[0] != expectedSyncByte)
1371  {
1372  FFStreamError err("BINEX head/tail synchronization byte mismatch");
1373  GNSSTK_THROW(err);
1374  }
1375  syncByte = expectedSyncByte;
1376  offset += 1;
1377 
1378  offset += r.decode(revRecBuf, offset, littleEndian);
1379  setRecordID( (RecordID)r);
1380  // @todo - Check against revRecSize
1381  offset += m.decode(revRecBuf, offset, littleEndian);
1382  // @todo - Check against revRecSize
1383 
1384  msg.assign(revRecBuf, offset, (unsigned long)m);
1385  offset += msg.size();
1386 
1387  // Check CRC - first calculate expected, then compare to actual.
1388  getCRC(revRecBuf.substr(1, r.getSize() + m.getSize() ), msg, expectedCrc);
1389  crcLen = expectedCrc.size();
1390 
1391  if ( (offset + crcLen != revRecSize)
1392  || expectedCrc.compare(revRecBuf.substr(offset, crcLen) ) )
1393  {
1394  FFStreamError err("Bad BINEX CRC");
1395  GNSSTK_THROW(err);
1396  }
1397  }
1398  else
1399  {
1400  std::ostringstream errStrm;
1401  errStrm << "Invalid BINEX synchronization byte: "
1402  << static_cast<uint16_t>(syncBuf);
1403  FFStreamError err(errStrm.str() );
1404  GNSSTK_THROW(err);
1405  }
1406 
1407  endpos = strm.tellg();
1408  }
1409  catch(FFStreamError& exc)
1410  {
1411  GNSSTK_RETHROW(exc);
1412  }
1413  catch(std::exception& exc)
1414  {
1415  FFStreamError err(exc.what() );
1416  GNSSTK_THROW(err);
1417  }
1418  catch(...)
1419  {
1420  FFStreamError err("Unknown exception");
1421  GNSSTK_THROW(err);
1422  }
1423 
1424  return (endpos-stpos);
1425  }
1426 
1427  void
1428  BinexData::getCRC(const std::string& head,
1429  const std::string& message,
1430  std::string& crc) const
1431  {
1432  size_t crcDataLen = head.size() + message.size();
1433  size_t crcLen = 0;
1434  unsigned long crcTmp = 0;
1435 
1436  if (crcDataLen >= 1048576)
1437  {
1438  // @todo - Use 16-byte CRC (128-bit MD5 checksum)
1439  crcLen = 16;
1440  }
1441  else // (crcLen < 1048576)
1442  {
1443  if (syncByte & eEnhancedCRC)
1444  {
1445  if (crcDataLen < 128)
1446  {
1447  // Use 2-byte CRC (CRC16)
1449  crcTmp = BinUtils::computeCRC((const unsigned char*)head.data(),
1450  head.size(),
1451  params);
1452  params.initial = crcTmp;
1453  crcTmp = BinUtils::computeCRC((const unsigned char*)message.data(),
1454  message.size(),
1455  params);
1456  crcLen = 2;
1457  }
1458  else
1459  {
1460  // Use 4-byte CRC (CRC32)
1462  crcTmp = BinUtils::computeCRC((const unsigned char*)head.data(),
1463  head.size(),
1464  params);
1465  params.initial = crcTmp;
1466  crcTmp = BinUtils::computeCRC((const unsigned char*)message.data(),
1467  message.size(),
1468  params);
1469  crcLen = 4;
1470  }
1471  }
1472  else // Regular CRC
1473  {
1474  if (crcDataLen < 128)
1475  {
1476  // Use 1-byte checksum: 8-bit XOR of all bytes
1477  size_t b;
1478  const char *ptr;
1479  ptr = head.data();
1480  for (b = head.size(); b > 0 ; b--, ptr++)
1481  {
1482  crcTmp ^= *ptr;
1483  }
1484  ptr = message.data();
1485  for (b = message.size(); b > 0 ; b--, ptr++)
1486  {
1487  crcTmp ^= *ptr;
1488  }
1489  crcLen = 1;
1490  }
1491  else if (crcDataLen < 4096)
1492  {
1493  // Use 2-byte CRC (CRC16)
1495  crcTmp = BinUtils::computeCRC((const unsigned char*)head.data(),
1496  head.size(),
1497  params);
1498  params.initial = crcTmp;
1499  crcTmp = BinUtils::computeCRC((const unsigned char*)message.data(),
1500  message.size(),
1501  params);
1502  crcLen = 2;
1503  }
1504  else
1505  {
1506  // Use 4-byte CRC (CRC32)
1508  crcTmp = BinUtils::computeCRC((const unsigned char*)head.data(),
1509  head.size(),
1510  params);
1511  params.initial = crcTmp;
1512  crcTmp = BinUtils::computeCRC((const unsigned char*)message.data(),
1513  message.size(),
1514  params);
1515  crcLen = 4;
1516  }
1517  } // Regular CRC
1518 
1519  // Copy the CRC into the output
1520  crc.resize(sizeof(crcTmp));
1521  BinUtils::encodeVarLE(crcTmp, crc);
1522  crc.resize(crcLen);
1523 
1524  } // (crcLen < 1048576)
1525 
1526  } // BinexData::getCRC()
1527 
1528  // -------------------------------------------------------------------------
1529  size_t
1530  BinexData::getCRCLength(size_t crcDataLen) const
1531  {
1532  size_t crcLen = 0;
1533 
1534  if (crcDataLen >= 1048576)
1535  {
1536  crcLen = 16;
1537  }
1538  else // (crcLen < 1048576)
1539  {
1540  if (syncByte & eEnhancedCRC)
1541  {
1542  if (crcDataLen < 128)
1543  {
1544  crcLen = 2;
1545  }
1546  else
1547  {
1548  crcLen = 4;
1549  }
1550  }
1551  else // Regular CRC
1552  {
1553  if (crcDataLen < 128)
1554  {
1555  crcLen = 1;
1556  }
1557  else if (crcDataLen < 4096)
1558  {
1559  crcLen = 2;
1560  }
1561  else
1562  {
1563  crcLen = 4;
1564  }
1565 
1566  } // Regular CRC
1567 
1568  } // (crcLen < 1048576)
1569 
1570  return crcLen;
1571  }
1572 
1573  // -------------------------------------------------------------------------
1574  bool
1575  BinexData::isHeadSyncByteValid(SyncByte headSync,
1576  SyncByte& expectedTailSync) const
1577  {
1578  switch (headSync)
1579  {
1580  case 0xC2: // Fall through ...
1581  case 0xE2: // Fall through ...
1582  case 0xC8: // Fall through ...
1583  case 0xE8:
1584  expectedTailSync = 0x00; // No tail sync byte
1585  break;
1586 
1587  case 0xD2:
1588  expectedTailSync = 0xB4;
1589  break;
1590 
1591  case 0xF2:
1592  expectedTailSync = 0xB0;
1593  break;
1594 
1595  case 0xD8:
1596  expectedTailSync = 0xE4;
1597  break;
1598 
1599  case 0xF8:
1600  expectedTailSync = 0xE0;
1601  break;
1602 
1603  default:
1604  return false; // Invalid head synchronization byte
1605  }
1606  return true;
1607  }
1608 
1609  // -------------------------------------------------------------------------
1610  bool
1611  BinexData::isTailSyncByteValid(SyncByte tailSync,
1612  SyncByte& expectedHeadSync) const
1613  {
1614  switch (tailSync)
1615  {
1616  case 0xB4:
1617  expectedHeadSync = 0xD2;
1618  break;
1619 
1620  case 0xB0:
1621  expectedHeadSync = 0xF2;
1622  break;
1623 
1624  case 0xE4:
1625  expectedHeadSync = 0xD8;
1626  break;
1627 
1628  case 0xE0:
1629  expectedHeadSync = 0xF8;
1630  break;
1631 
1632  default:
1633  return false; // Invalid tail synchronization byte
1634  }
1635  return true;
1636  }
1637 
1638  // -------------------------------------------------------------------------
1639  unsigned long long
1640  BinexData::parseBuffer(const std::string& buffer,
1641  size_t offset,
1642  size_t size)
1643  {
1644  unsigned long long value = 0;
1645  if (size > sizeof(value) )
1646  {
1647  FFStreamError err("Invalid data size parsing BINEX data buffer");
1648  GNSSTK_THROW(err);
1649  }
1650  if (offset + size > buffer.size() )
1651  {
1652  FFStreamError err("Invalid offset parsing BINEX data buffer");
1653  GNSSTK_THROW(err);
1654  }
1655  char* valp = (char*)&value;
1656  for (size_t i = 0; i < size; i++, valp++)
1657  {
1658  *valp = buffer[offset + i];
1659  }
1660  if (!nativeLittleEndian)
1661  {
1662  value >>= ( (sizeof(value) - size) << 3);
1663  }
1664  return value;
1665  }
1666 
1667 
1668  template <class T>
1669  void
1670  BinexData::reverseBytes(T& val)
1671  {
1672  T copy(val);
1673  uint8_t *from((uint8_t*)(&copy)), *to((uint8_t*)(&val));
1674  for (unsigned i = 0; i < sizeof(T); i++)
1675  {
1676  to[i] = from[sizeof(T)-(i+1)];
1677  }
1678  }
1679 
1680 
1681  // -------------------------------------------------------------------------
1682  void
1683  BinexData::reverseBuffer(std::string& buffer, size_t offset, size_t n)
1684  {
1685  if (n < 2)
1686  return; // Nothing to do
1687 
1688  if (offset >= buffer.size() )
1689  {
1690  FFStreamError err("Invalid offset reversing BINEX data buffer");
1691  GNSSTK_THROW(err);
1692  }
1693  size_t back = (n == std::string::npos) ? buffer.size() - 1: offset + n;
1694  if (back >= buffer.size() )
1695  {
1696  FFStreamError err("Invalid size reversing BINEX data buffer");
1697  GNSSTK_THROW(err);
1698  }
1699  --back;
1700  unsigned char tmp;
1701  while (offset < back)
1702  {
1703  tmp = buffer[offset];
1704  buffer[offset] = buffer[back];
1705  buffer[back] = tmp;
1706  ++offset;
1707  --back;
1708  }
1709  }
1710 
1711  // -------------------------------------------------------------------------
1712  void BinexData::dump(ostream& s) const
1713  {
1714  std::cout << "RecordID: " << recID << std::endl;
1715  std::cout << "SyncByte: " << (unsigned short)syncByte << std::endl;
1716  std::cout << "MessageLen: " << msg.size() << std::endl;
1717  std::cout << "MessageData: " << std::endl;
1718  for (size_t i = 0; i < msg.size(); i++)
1719  {
1720  unsigned short s = msg[i];
1721  std::cout << s << " ";
1722  }
1723  std::cout << std::endl;
1724  }
1725 
1726 
1727 } // namespace gnsstk
gnsstk::dump
void dump(vector< SatPass > &SatPassList, ostream &os, bool rev, bool dbug)
Definition: SatPassUtilities.cpp:59
gnsstk::operator==
bool operator==(const IonexData::IonexValType &x, const IonexData::IonexValType &y)
operator == for IonexData::IonexValType
Definition: IonexData.hpp:253
gnsstk::BinexData::RecordID
uint32_t RecordID
Record ID type.
Definition: BinexData.hpp:72
gnsstk::FFStream
Definition: FFStream.hpp:119
gnsstk::BinexData::UBNXI::decode
size_t decode(const std::string &inBuffer, size_t offset=0, bool littleEndian=false)
Definition: BinexData.cpp:119
NULL
#define NULL
Definition: getopt1.c:64
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
gnsstk::BinUtils::computeCRC
uint32_t computeCRC(const unsigned char *data, unsigned long len, const CRCParam &params)
Definition: BinUtils.hpp:477
gnsstk::BinexData::syncByte
SyncByte syncByte
Flags for endianness, CRC, etc.
Definition: BinexData.hpp:973
gnsstk::BinexStream
Definition: BinexStream.hpp:63
gnsstk::BinUtils::CRCParam
Encapsulate parameters for CRC computation.
Definition: BinUtils.hpp:280
gnsstk::BinexData
Definition: BinexData.hpp:65
gnsstk::BinexData::msg
std::string msg
Record message (opaque)
Definition: BinexData.hpp:975
BinexStream.hpp
example4.err
err
Definition: example4.py:126
gnsstk::BinexData::UBNXI::getSize
size_t getSize() const
Definition: BinexData.hpp:202
gnsstk::BinUtils::CRCParam::initial
unsigned long initial
initial CRC initial value.
Definition: BinUtils.hpp:297
GNSSTK_RETHROW
#define GNSSTK_RETHROW(exc)
Definition: Exception.hpp:369
gnsstk::BinUtils::encodeVarLE
std::string encodeVarLE(const T &v)
Definition: BinUtils.hpp:436
gnsstk::BinexData::UBNXI
Definition: BinexData.hpp:96
example3.data
data
Definition: example3.py:22
std
Definition: Angle.hpp:142
gnsstk::BinexData::UBNXI::encode
size_t encode(std::string &outBuffer, size_t offset=0, bool littleEndian=false) const
Definition: BinexData.cpp:155
GNSSTK_THROW
#define GNSSTK_THROW(exc)
Definition: Exception.hpp:366
gnsstk::BinexData::recID
RecordID recID
Record ID.
Definition: BinexData.hpp:974
gnsstk::BinUtils::CRC32
const CRCParam CRC32(32, 0x4c11db7, 0xffffffff, 0xffffffff, true, true, true)
CRC-32 parameters.
Definition: BinUtils.hpp:309
gnsstk::BinexData::SyncByte
uint8_t SyncByte
Synchronization byte (record flags)
Definition: BinexData.hpp:73
gnsstk::BinexData::MGFZI
Definition: BinexData.hpp:293
gnsstk::BinexData::UBNXI::read
size_t read(std::istream &strm, std::string *outBuffer=NULL, size_t offset=0, bool reverseBytes=false, bool littleEndian=false)
Definition: BinexData.cpp:268
gnsstk::BinUtils::CRC16
const CRCParam CRC16(16, 0x8005, 0, 0, true, true, true)
CRC-16 parameters.
Definition: BinUtils.hpp:307
BinexData.hpp


gnsstk
Author(s):
autogenerated on Wed Oct 25 2023 02:40:38