FFStream.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 "FFStream.hpp"
45 
46 namespace gnsstk
47 {
50  : recordNumber(0)
51  {
52  }
53 
54 
57  {
58  }
59 
60 
62  FFStream( const char* fn,
63  std::ios::openmode mode )
64  : recordNumber(0),
65  filename(fn)
66  {
67  // Note that this will call FFStream::open, not the child
68  // class. Virtual function pointer tables aren't populated
69  // until the end of the constructor so the child class'
70  // open() method won't be known at this point.
71  // https://isocpp.org/wiki/faq/strange-inheritance#calling-virtuals-from-ctors
72  // As such, child classes should implement their own init()
73  // methods to do any additional processing that is normally
74  // done in open() and call that in the constructor as well as
75  // their own open() methods.
76  // see open() comments for more.
77  open(fn, mode);
78  }
79 
80 
82  FFStream( const std::string& fn,
83  std::ios::openmode mode )
84  : recordNumber(0),
85  filename(fn)
86  {
87  open(fn, mode);
88  }
89 
90 
91  void FFStream ::
92  open( const std::string& fn,
93  std::ios::openmode mode )
94  {
95  open( fn.c_str(), mode );
96  }
97 
98 
99  void FFStream ::
100  open( const char* fn, std::ios::openmode mode )
101  {
102  // Child classes should never do anything more in open() than
103  // call a class-specific init function and the parent open()
104  // method. In this case we are calling init() first because
105  // it closes the stream if it's already open, which obviously
106  // shouldn't be done AFTER the new stream is open. Child
107  // classes typically will want to do their initialization
108  // AFTER the parent.
109  init(fn, mode);
110  std::fstream::open(fn, mode);
111  } // End of method 'FFStream::open()'
112 
113 
114  void FFStream ::
115  init( const char* fn, std::ios::openmode mode )
116  {
117  close();
118  clear();
119  filename = std::string(fn);
120  recordNumber = 0;
121  } // End of method 'FFStream::open()'
122 
123 
124  bool FFStream ::
125  isFFStream(std::istream& i)
126  {
127  try
128  {
129  (void)dynamic_cast<FFStream&>(i);
130  }
131  catch(...)
132  {
133  return false;
134  }
135 
136  return true;
137  }
138 
139 
140  void FFStream ::
141  dumpState(std::ostream& s) const
142  {
143  s << "filename:" << filename
144  << ", recordNumber:" << recordNumber;
145  s << ", exceptions:";
146 
147  if (exceptions() & std::ios::badbit) s << "bad ";
148  if (exceptions() & std::ios::failbit) s << "fail ";
149  if (exceptions() & std::ios::eofbit) s << "eof ";
150  if (exceptions() == 0) s << "none";
151 
152  s << ", rdstate:";
153 
154  if (rdstate() & std::ios::badbit) s << "bad ";
155  if (rdstate() & std::ios::failbit) s << "fail ";
156  if (rdstate() & std::ios::eofbit) s << "eof ";
157  if (rdstate() == 0) s << "none";
158  s << std::endl;
159  } // End of method 'FFStream::dumpState()'
160 
161 
163  {
164  // JMK 2015/12/07 - some implementations of streams will
165  // raise exceptions in tellg if eofbit is set but not
166  // failbit. This attempts to work around this situation and
167  // make FFStream work more like one would expect, i.e. don't
168  // fail until the failbit is set.
169  if (rdstate() == std::ios::eofbit)
170  clear(); // clear ONLY if eofbit is the only state flag set
171  // Mark where we start in case there is an error.
172  long initialPosition = tellg();
173  unsigned long initialRecordNumber = recordNumber;
174  clear();
175 
176  try
177  {
178  try
179  {
180  rec.reallyGetRecord(*this);
181  recordNumber++;
182  }
183  catch (EndOfFile& e)
184  {
185  // EOF - do nothing - eof causes fail() to be set which
186  // is handled by std::fstream
187  e.addText("In record " +
189  e.addText("In file " + filename);
190  e.addLocation(FILE_LOCATION);
192  }
193  catch (std::exception &e)
194  {
195  mostRecentException = FFStreamError("std::exception thrown: " +
196  std::string(e.what()));
197  mostRecentException.addText("In record " +
199  mostRecentException.addText("In file " + filename);
200  mostRecentException.addLocation(FILE_LOCATION);
201  clear();
202  seekg(initialPosition);
203  recordNumber = initialRecordNumber;
204  setstate(std::ios::failbit);
206  }
207  catch (gnsstk::StringUtils::StringException& e)
208  {
209  e.addText("In record " +
211  e.addText("In file " + filename);
212  e.addLocation(FILE_LOCATION);
214  clear();
215  seekg(initialPosition);
216  recordNumber = initialRecordNumber;
217  setstate(std::ios::failbit);
219  }
220  // catches some errors we can encounter
221  catch (FFStreamError& e)
222  {
223  e.addText("In record " +
225  e.addText("In file " + filename);
226  e.addLocation(FILE_LOCATION);
228  clear();
229  seekg(initialPosition);
230  recordNumber = initialRecordNumber;
231  setstate(std::ios::failbit);
233 
234  }
235  }
236  // this is if you throw an FFStream error in the above catch
237  // block because the catch(...) below will mask it otherwise.
238  // This also takes care of catching StringExceptions
239  catch (gnsstk::Exception &e)
240  {
241  GNSSTK_RETHROW(e);
242  }
243  catch (std::ifstream::failure &e)
244  {
245  // setting failbit when catching FFStreamError can cause
246  // this exception to be thrown. in this case, we don't want
247  // to lose the exception info so only make a new exception
248  // if this isn't a fail() case
249  if (!fail())
250  {
251  mostRecentException = FFStreamError("ifstream::failure thrown: " +
252  std::string(e.what()));
253  mostRecentException.addText("In file " + filename);
254  mostRecentException.addLocation(FILE_LOCATION);
255  }
257  }
258  catch (std::exception &e)
259  {
260  mostRecentException = FFStreamError("std::exception thrown: " +
261  std::string(e.what()));
262  mostRecentException.addText("In file " + filename);
263  mostRecentException.addLocation(FILE_LOCATION);
264  setstate(std::ios::failbit);
266  }
267  catch (...)
268  {
269  mostRecentException = FFStreamError("Unknown exception thrown");
270  mostRecentException.addText("In file " + filename);
271  mostRecentException.addLocation(FILE_LOCATION);
272  setstate(std::ios::failbit);
274  }
275 
276  } // End of method 'FFStream::tryFFStreamGet()'
277 
278 
279 
280  // the crazy double try block is so that no gnsstk::Exception throws
281  // get masked, allowing all exception information (line numbers, text,
282  // etc) to be retained.
283  void FFStream ::
285  {
286  // Mark where we start in case there is an error.
287  long initialPosition = tellg();
288  unsigned long initialRecordNumber = recordNumber;
289  clear();
290 
291  try
292  {
293  try
294  {
295  rec.reallyPutRecord(*this);
296  recordNumber++;
297  }
298  catch (std::exception &e)
299  {
300  // if this is a stream failure, don't mask it and let the
301  // later catch block handle it
302  if (dynamic_cast<std::ifstream::failure*>(&e))
303  throw;
304 
305  // the catch(FFStreamError) below will add file information
306  // to this exception
307  mostRecentException = FFStreamError("std::exception thrown: " +
308  std::string(e.what()));
309  mostRecentException.addLocation(FILE_LOCATION);
310  setstate(std::ios::failbit);
312  }
313  catch (gnsstk::StringUtils::StringException& e)
314  {
315  e.addText("In record " +
317  e.addText("In file " + filename);
318  e.addLocation(FILE_LOCATION);
320  seekg(initialPosition);
321  recordNumber = initialRecordNumber;
322  setstate(std::ios::failbit);
324  }
325  // catches some errors we can encounter
326  catch (FFStreamError& e)
327  {
328  e.addText("In record " +
330  e.addText("In file " + filename);
331  e.addLocation(FILE_LOCATION);
333  seekg(initialPosition);
334  recordNumber = initialRecordNumber;
335  setstate(std::ios::failbit);
337  }
338  }
339  // this is if you throw an FFStream error in the above catch
340  // block because the catch(...) below will mask it otherwise.
341  // This also takes care of catching StringExceptions
342  catch (gnsstk::Exception &e)
343  {
344  GNSSTK_RETHROW(e);
345  }
346  catch (std::ifstream::failure &e)
347  {
348  // setting failbit when catching FFStreamError can cause
349  // this exception to be thrown. in this case, we don't want
350  // to lose the exception info so only make a new exception
351  // if this isn't a fail() case
352  if (!fail())
353  {
354  mostRecentException = FFStreamError("ifstream::failure thrown: " +
355  std::string(e.what()));
356  mostRecentException.addText("In file " + filename);
357  mostRecentException.addLocation(FILE_LOCATION);
358  }
360  }
361  catch (std::exception &e)
362  {
363  mostRecentException = FFStreamError("std::exception thrown: " +
364  std::string(e.what()));
365  mostRecentException.addText("In file " + filename);
366  mostRecentException.addLocation(FILE_LOCATION);
367  setstate(std::ios::failbit);
369  }
370  catch (...)
371  {
372  mostRecentException = FFStreamError("Unknown exception thrown");
373  mostRecentException.addText("In file " + filename);
374  mostRecentException.addLocation(FILE_LOCATION);
375  setstate(std::ios::failbit);
377  }
378 
379  } // End of method 'FFStream::tryFFStreamPut()'
380 
381 
382 
383 } // End of namespace gnsstk
gnsstk::FFData
Definition: FFData.hpp:87
gnsstk::FFStream::filename
std::string filename
file name
Definition: FFStream.hpp:179
gnsstk::FFStream::tryFFStreamPut
virtual void tryFFStreamPut(const FFData &rec)
Definition: FFStream.cpp:284
gnsstk::FFStream
Definition: FFStream.hpp:119
gnsstk::FFStream::init
void init(const char *fn, std::ios::openmode mode)
Initialize internal data structures according to file name & mode.
Definition: FFStream.cpp:115
gnsstk::StringUtils::asString
std::string asString(IonexStoreStrategy e)
Convert a IonexStoreStrategy to a whitespace-free string name.
Definition: IonexStoreStrategy.cpp:46
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
gnsstk::FFStream::recordNumber
unsigned int recordNumber
keeps track of the number of records read
Definition: FFStream.hpp:176
gnsstk::FFStream::open
virtual void open(const char *fn, std::ios::openmode mode)
Definition: FFStream.cpp:100
gnsstk::Exception
Definition: Exception.hpp:151
gnsstk::FFStream::mostRecentException
FFStreamError mostRecentException
This stores the most recently thrown exception.
Definition: FFStream.hpp:173
gnsstk::FFData::reallyPutRecord
virtual void reallyPutRecord(FFStream &s) const =0
gnsstk::FFStream::isFFStream
static bool isFFStream(std::istream &i)
Check if the input stream is the kind of RinexObsStream.
Definition: FFStream.cpp:125
GNSSTK_RETHROW
#define GNSSTK_RETHROW(exc)
Definition: Exception.hpp:369
gnsstk::FFStream::FFStream
FFStream()
Default constructor, initialize internal data.
Definition: FFStream.cpp:49
gnsstk::FFStream::tryFFStreamGet
virtual void tryFFStreamGet(FFData &rec)
Definition: FFStream.cpp:162
example5.fn
string fn
Definition: example5.py:10
gnsstk::FFStream::dumpState
void dumpState(std::ostream &s=std::cout) const
A function to help debug FFStreams.
Definition: FFStream.cpp:141
FFStream.hpp
FILE_LOCATION
#define FILE_LOCATION
Definition: Exception.hpp:352
gnsstk::FFStream::~FFStream
virtual ~FFStream()
Virtual destructor, close the stream etc.
Definition: FFStream.cpp:56
gnsstk::FFData::reallyGetRecord
virtual void reallyGetRecord(FFStream &s)=0
gnsstk::FFStream::conditionalThrow
void conditionalThrow(void)
Definition: FFStream.hpp:213


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