1 //==============================================================================
2 //
3 //  This file is part of GPSTk, the GPS Toolkit.
4 //
5 //  The GPSTk 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 GPSTk 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 GPSTk; 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-2020, 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 
39 /**
40  * @file SinexBlock.hpp
41  * Encapsulate SINEX block data, including I/O
42  */
43 
44 #ifndef GPSTK_SINEXBLOCK_HPP
45 #define GPSTK_SINEXBLOCK_HPP
46 
47 #include <vector>
48 #include <map>
49 #include "SinexBase.hpp"
50 #include "SinexTypes.hpp"
51 
52 namespace gpstk
53 {
54    namespace Sinex
55    {
56          /// @ingroup FileHandling
57          //@{
58 
59          /** Base class for all SINEX blocks; the common base allows blocks
60           * of varying types to be stored in a vector.  Specific block types
61           * are realized by the derived Block class defined below.
62           */
63       class BlockBase
64       {
65             /* Sinex:Data calls the protected putBlock() and
66              * getBlock() methods. */
67          friend class Data;
68 
69       public:
70 
~BlockBase()71          virtual ~BlockBase() {}
72 
73             /// Comments that apply to an entire block
74          std::string  comment;
75 
76             /**Returns the block title
77              */
78          virtual std::string  getTitle() const = 0;
79 
80             /** Returns the number of lines in the block
81              */
82          virtual size_t  getSize() const = 0;
83 
84       protected:
85 
86             /**
87              * Writes the formatted block to the SinexStream.
88              * @param s Stream to which to write
89              * @returns Number of lines written
90              * @throw std::exception
91              * @throw FFStreamError
92              * @throw StringUtils::StringException
93              */
94          virtual size_t putBlock(Sinex::Stream& s) const = 0;
95 
96             /**
97              * Reads a record from the given SinexStream; if an error
98              * is encountered in retrieving the record, the stream is reset
99              * to its original position and its fail-bit is set.
100              * @param s Stream from which to read
101              * @returns Number of lines read
102              * @throw std::exception
103              * @throw StringException when a StringUtils function fails
104              * @throw FFStreamError when exceptions(failbit) is set and
105              *  a read or formatting error occurs.  This also resets the
106              *  stream to its pre-read position.
107              */
108          virtual size_t getBlock(Sinex::Stream& s) = 0;
109 
110       }; // class BlockBase
111 
112 
113          /** SINEX block parameterized by the type of data it contains.
114           * Each element in the block is a data line of the specified type.
115           */
116       template<class T>
117       class Block : public BlockBase
118       {
119       public:
120 
~Block()121          virtual ~Block() {}
122 
create()123          static BlockBase* create() { return new Block<T>; }
124 
getTitle() const125          std::string  getTitle() const { return T::BLOCK_TITLE; }
126 
127             /** Returns the number of data items in the block
128              */
getSize() const129          size_t  getSize() const { return dataVec.size(); }
130 
131             /** Appends data to the block
132              */
push_back(const T & x)133          void push_back(const T& x) { dataVec.push_back(x); }
134 
getData()135          std::vector<T>& getData() { return dataVec; }
136 
137       protected:
138 
139          std::vector<T>  dataVec;  // Data storage
140 
141             /** Writes all data in the block to the specified stream
142              * @throw std::exception
143              * @throw FFStreamError
144              */
putBlock(Sinex::Stream & s) const145          virtual size_t putBlock(Sinex::Stream& s) const
146          {
147             size_t  lineNum = 0;
148             typename std::vector<T>::const_iterator  i = dataVec.begin();
149             for ( ; i != dataVec.end(); ++i, ++lineNum)
150             {
151                try
152                {
153                   const Sinex::DataType&  d = *i;
154                   s << (std::string)d << std::endl;
155                }
156                catch (Exception& exc)
157                {
158                   FFStreamError  err(exc);
159                   GPSTK_THROW(err);
160                }
161             }
162             return lineNum;
163          };
164 
165             /** Reads all data in a block from the specified stream
166              * @throw std::exception
167              * @throw FFStreamError
168              * @throw StringUtils::StringException
169              */
getBlock(Sinex::Stream & s)170          virtual size_t getBlock(Sinex::Stream& s)
171          {
172             size_t  lineNum = 0;
173             char    c;
174             while (s.good() )
175             {
176                c = s.get();
177                if (s.good() )
178                {
179                   if (c == DATA_START)
180                   {
181                         /// More data
182                      std::string  line;
183                      s.formattedGetLine(line);
184                      try
185                      {
186                         dataVec.push_back(
187                            T(line.insert( (size_t)0, (size_t)1, c),
188                              lineNum) );
189                      }
190                      catch (Exception& exc)
191                      {
192                         FFStreamError  err(exc);
193                         GPSTK_THROW(err);
194                      }
195                      ++lineNum;
196                   }
197                   else
198                   {
199                         /// End of data
200                      s.putback(c);
201                      break;
202                   }
203                }
204             }
205             return lineNum;
206          };
207 
208       }; // class Block<T>
209 
210 
211          /// Block storage type
212       typedef std::vector<const BlockBase*>  Blocks;
213 
214          /// Block iterator
215       typedef Blocks::iterator  BlockIter;
216 
217          /// Function pointer for invoking create methods for blocks
218       typedef BlockBase* (*BlockCreateFunc)();
219 
220          /// Mapping from block titles to block create functions
221       typedef std::map<std::string, BlockCreateFunc>  BlockFactory;
222 
223          //@}
224 
225    }  // namespace Sinex
226 
227 }  // namespace gpstk
228 
229 #endif // GPSTK_SINEXBLOCK_HPP
230