astrotypes  0.0
HeaderBase.cpp
Go to the documentation of this file.
1 /*
2  * MIT License
3  *
4  * Copyright (c) 2018 PulsarSearchSoft
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #include <iomanip>
25 #include <sstream>
26 
27 namespace pss {
28 namespace astrotypes {
29 namespace sigproc {
30 
31 template<typename Derived>
32 template<typename T>
33 std::runtime_error HeaderBase<Derived>::parse_error(std::string const& msg, T const& msg2) const
34 {
35  std::stringstream ss(msg);
36  try {
37  ss << ": " << msg2;
38  }
39  catch(...) {
40  // don't let this method throw
41  }
42 
43  return std::runtime_error(ss.str());
44 }
45 
46 template<typename Derived>
48 {
49 }
50 
51 template<typename Derived>
53  : _size(h._size)
54 {
55 }
56 
57 template<typename Derived>
59 {
60  static_cast<Derived&>(*this).do_reset();
61 }
62 
63 template<typename Derived>
65 {
66  for(auto const& header : _headers) {
67  header.second->reset();
68  }
69 }
70 
71 template<typename Derived>
73 {
74  auto it = _compare_headers.find(label);
75  if(it == _compare_headers.end()) return;
76  _compare_headers.erase(it);
77 }
78 
79 template<typename Derived>
81 {
82  auto it = _compare_headers.find(label);
83  if(it != _compare_headers.end()) return;
84  _compare_headers.insert(std::make_pair(label, _headers.at(label)));
85 }
86 
87 template<typename Derived>
88 Derived& HeaderBase<Derived>::copy_header_values(Derived const& dst)
89 {
90  for(auto const& header : dst._headers) {
91  if(header.second->is_set()) {
92  auto& field = *_headers.at(header.first);
93  field = *header.second;
94  }
95  }
96  return static_cast<Derived&>(*this);
97 }
98 
99 template<typename Derived>
100 void HeaderBase<Derived>::read(std::istream & stream)
101 {
102  static_cast<Derived&>(*this).do_read(stream);
103 }
104 
105 template<typename Derived>
106 void HeaderBase<Derived>::do_read(std::istream & stream)
107 {
108  reset();
109 
110  // try to read in the first line of the header
111  SigProcLabel str;
112  //stream >> str;
113  str.read(stream);
114  _size = str.size();
115 
116  //if (std::strcmp(str.c_str(),"HEADER_START") !=0) {
117  if (str != "HEADER_START"){
118  throw parse_error("expecting HEADER_START got ", str);
119  }
120  /* loop over and read remaining header lines until HEADER_END reached */
121  while (1) {
122  stream >> str;
123  _size += str.size();
124 
125  if( str.string().find(std::string("HEADER_END") ) != std::string::npos) {
126  break;
127  }
128 
129  // look for a matching known header
130  auto it = _read_only_headers.find(str);
131  if( it == _read_only_headers.end()) {
132  // look for a matching known header
133  it = _headers.find(str);
134  if( it == _headers.end()) {
135  throw parse_error("Header - unknown parameter", str);
136  }
137  }
138 
139  // read in the value
140  _size += it->second->read(stream);
141  }
142 }
143 
144 template<typename Derived>
145 void HeaderBase<Derived>::write(std::ostream& stream) const {
146  static_cast<Derived const&>(*this).do_write(stream);
147 }
148 
149 template<typename Derived>
150 void HeaderBase<Derived>::do_write(std::ostream& stream) const {
151 
152  // Write header
153  const static SigProcLabel start("HEADER_START");
154  stream << start;
155  _size = start.size();
156 
157  // write out header data
158  for(auto const& header : _headers) {
159  if(header.second->is_set())
160  {
161  stream << header.first;
162  _size += header.first.size();
163  _size += header.second->write(stream);
164  }
165  }
166 
167  const static SigProcLabel end("HEADER_END");
168  stream << end;
169  _size += end.size();
170 }
171 
172 template<typename Derived>
173 std::ostream& operator<<(std::ostream& stream, HeaderBase<Derived> const& h)
174 {
175  h.write(stream);
176  return stream;
177 }
178 
179 template<typename Derived>
180 std::istream& operator>>(std::istream& stream, HeaderBase<Derived>& headers)
181 {
182  headers.read(stream);
183  return stream;
184 }
185 
186 template<typename Derived>
188 {
189  return static_cast<Derived const&>(*this).do_equal(h);
190 }
191 
192 template<typename Derived>
194 {
195  for(auto const& header : _compare_headers) {
196  auto const& field = *h._headers.at(header.first);
197  if(header.second->is_set()) {
198  if(!field.is_set()) {
199  // one is set, the other not so can't be equal
200  return false;
201  }
202  try {
203  if(!(field == *header.second)) {
204  // we test the actual values as they are both set
205  return false;
206  }
207  }
208  catch(std::exception const& e) {
209  throw parse_error(std::string("exception comparing values for header ") + header.first.string(), e.what());
210  }
211  catch(...) {
212  throw parse_error("exception comparing values for header ", header.first);
213  }
214  }
215  else if(field.is_set()) {
216  // one is set, the other not so can't be equal
217  return false;
218  }
219  }
220  return true;
221 }
222 
223 template<typename Derived>
225 {
226  return !(h==*this);
227 }
228 
229 template<typename Derived>
230 std::size_t HeaderBase<Derived>::size() const {
231 /*
232  std::size_t size = 0U;
233  for(auto const& header : _headers) {
234  if(header.second->is_set()) {
235  size += header.first.size();
236  size += header.size_bytes();
237  }
238  }
239  return size;
240 */
241  return _size;
242 }
243 
244 template<typename Derived>
246 {
247  _headers.insert(std::make_pair(name, &field));
248  if(name != "tstart")
249  {
250  _compare_headers.insert(std::make_pair(name, &field));
251  }
252 }
253 
254 template<typename Derived>
256 {
257  _read_only_headers.insert(std::make_pair(name, &field));
258 }
259 
260 template<typename Derived>
262 {
263 }
264 
265 template<typename Derived>
266 template<typename Stream>
268 {
269  return HeaderBase<Derived>::InfoSentry<Stream>(os);
270 }
271 
272 template<typename Derived>
273 template<typename Stream>
275  : _os(os)
276 {
277 }
278 
279 template<typename Derived>
280 template<typename Stream>
282 {
283  for(auto const& header : h._headers) {
284  if(header.second->is_set()) {
285  _os << std::left << std::setw(15) << header.second->header_info(header.first.string()) << " : ";
286  header.second->write_info(_os);
287  _os << "\n";
288  }
289  }
290  return _os;
291 }
292 
293 template<typename Derived, typename Stream>
294 typename HeaderBase<Derived>::template InfoSentry<Stream> const& operator<<(Stream& stream, typename HeaderBase<Derived>::Info const& adapter)
295 {
296  return adapter.sentry(stream);
297 }
298 
299 } // namespace sigproc
300 } // namespace astrotypes
301 } // namespace pss
class to provide a virtual lookup table for read/write the varoious types of SigProcVariables ...
Definition: HeaderField.h:44
std::runtime_error parse_error(std::string const &msg, T const &msg2) const
Definition: HeaderBase.cpp:33
bool do_equal(HeaderBase const &) const
Definition: HeaderBase.cpp:193
void reset()
reset all header variables to an undefined state
Definition: HeaderBase.cpp:58
void remove_compare_field(SigProcLabel const &)
remvoe a field to be checked in operator==
Definition: HeaderBase.cpp:72
std::size_t size() const
returns the number of bytes in the header
Definition: HeaderBase.cpp:230
Store SigProc header information.
Definition: HeaderBase.h:69
void add_compare_field(SigProcLabel const &)
add a field to be checked in operator==
Definition: HeaderBase.cpp:80
bool operator==(HeaderBase const &) const
returns true if the data formats match
Definition: HeaderBase.cpp:187
void add(SigProcLabel const &label, HeaderFieldBase &field)
add a field to be parsed for read and write
Definition: HeaderBase.cpp:245
std::istream & operator>>(std::istream &stream, HeaderBase< Derived > &headers)
Definition: HeaderBase.cpp:180
InfoSentry< Stream > sentry(Stream &os) const
void do_read(std::istream &stream)
Definition: HeaderBase.cpp:106
void add_read(SigProcLabel const &label, HeaderFieldBase &field)
add a field to be parsed for read only
Definition: HeaderBase.cpp:255
bool operator!=(HeaderBase const &) const
returns true if the data format meta data does not match
Definition: HeaderBase.cpp:224
void write(std::ostream &stream) const
write header data to the provided stream
Definition: HeaderBase.cpp:145
void do_write(std::ostream &stream) const
Definition: HeaderBase.cpp:150
HeaderBase< Derived >::template InfoSentry< Stream > const & operator<<(Stream &stream, typename HeaderBase< Derived >::Info const &adapter)
Definition: HeaderBase.cpp:294
void read(std::istream &stream)
read in header data from the provided stream
Definition: HeaderBase.cpp:100
Derived & copy_header_values(Derived const &dst)
copy values from one header to another
Definition: HeaderBase.cpp:88