OpenStructure
star_parser.hh
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // This file is part of the OpenStructure project <www.openstructure.org>
3 //
4 // Copyright (C) 2008-2020 by the OpenStructure authors
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License as published by the Free
8 // Software Foundation; either version 3.0 of the License, or (at your option)
9 // any later version.
10 // This library is distributed in the hope that it will be useful, but WITHOUT
11 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 // details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with this library; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 //------------------------------------------------------------------------------
19 #ifndef OST_IO_STAR_PARSER_HH
20 #define OST_IO_STAR_PARSER_HH
21 
22 
23 /*
24  Author: Marco Biasini
25  */
26 #include <boost/iostreams/filtering_stream.hpp>
27 
28 #include <iostream>
29 #include <fstream>
30 #include <vector>
31 #include <map>
32 #include <ost/string_ref.hh>
33 #include <ost/io/module_config.hh>
34 
35 namespace ost { namespace io {
36 
37 
38 typedef enum {
42 
43 
45 public:
46  StarDataItem(const StringRef& category, const StringRef& name,
47  const StringRef& value):
48  category_(category), name_(name), value_(value)
49  { }
50  const StringRef& GetCategory() const { return category_; }
51  const StringRef& GetName() const { return name_; }
52  const StringRef& GetValue() const { return value_; }
53 private:
54  StringRef category_;
55  StringRef name_;
56  StringRef value_;
57 };
58 
60 public:
62  category_("")
63  { }
64 
65  int GetIndex(const String& name) const
66  {
67  std::map<String, int>::const_iterator i=index_map_.find(name);
68  return i==index_map_.end() ? -1 : i->second;
69  }
70 
71  void SetCategory(const StringRef& category)
72  {
73  category_=category.str();
74  }
75 
76 
77 
78  void Add(const StringRef& name)
79  {
80  index_map_.insert(std::make_pair(name.str(), index_map_.size()));
81  }
82  size_t GetSize() const
83  {
84  return index_map_.size();
85  }
86  void Clear()
87  {
88  category_.clear();
89  index_map_.clear();
90  }
91 
92  const String& GetCategory() const { return category_; }
93 private:
94  String category_;
95  std::map<String, int> index_map_;
96 };
97 
115 public:
122  explicit StarParser(std::istream& stream, bool items_as_row=false);
123  explicit StarParser(const String& filename, bool items_as_row=false);
124  virtual ~StarParser() { }
125 // callback interface
126 public:
131  virtual bool OnBeginLoop(const StarLoopDesc& header) { return true; }
135  virtual void OnEndLoop() { }
139  virtual void OnDataRow(const StarLoopDesc& header,
140  const std::vector<StringRef>& columns)
141  {
142  }
144  virtual void OnDataItem(const StarDataItem& item) { }
145 
149  virtual bool OnBeginData(const StringRef& data_name) { return true; }
150 
153  virtual void OnEndData() { }
154 
161  Real TryGetReal(const StringRef& data, const String& name) const;
162 
172  const String& name,
173  Real alt,
174  bool (*is_default)(StringRef)) const;
175 
182  float TryGetFloat(const StringRef& data, const String& name) const;
183 
191  std::pair<bool, float> TryGetFloat(const StringRef& data,
192  const String& name,
193  bool may_fail) const;
194 
201  int TryGetInt(const StringRef& data, const String& name) const;
202 
210  std::pair<bool, int> TryGetInt(const StringRef& data,
211  const String& name,
212  bool may_fail) const;
213 
220  bool TryGetBool(const StringRef& data, const String& name) const;
221 
224  int line=-1) const;
225 
226  void SetFilename(const String& filename)
227  {
228  filename_ = filename;
229  }
230 
232  int GetCurrentLinenum() const
233  {
234  return line_num_;
235  }
236 public:
237  void Parse();
238 
239 public:
240  static bool SplitLine(const StringRef& line,
241  std::vector<StringRef>& parts, bool clear=true);
242  static inline bool IsUndefined(StringRef value)
243 {
244  return value.size()==1 && (value[0]=='?' || value[0]=='.');
245 }
246 
247 private:
248  void ParseLoop();
251  void ParseLastDataItemRow();
254  void ParseDataItemOrRow(StarDataItem& item);
256  void ParseEndDataItemRow();
257 private:
259  bool NextLine(StringRef& str)
260  {
261  if (std::getline(stream_, current_line_)) {
262  str=StringRef(current_line_.data(), current_line_.length());
263  ++line_num_;
264  has_current_line_=true;
265  return true;
266  }
267  return false;
268  }
270  bool GetLine(StringRef& ref)
271  {
272  if (has_current_line_) {
273  ref=StringRef(current_line_.data(), current_line_.size());
274  return true;
275  }
276  return this->NextLine(ref);
277  }
278 
279  void ConsumeLine()
280  {
281  assert(has_current_line_);
282  has_current_line_=false;
283  }
284 
285  // the reason for having this function are problems when generating
286  // StringRefs that contain pointers to strings in a vector.
287  // When the vector grows, the memory of the strings might get
288  // reallocated and the StringRefs point into nothing.
289  // This function Prepares the stringrefs given a constant
290  // vector and calls OnDataRow to minimize the change in interface.
291  void CallOnDataRow(const StarLoopDesc& header,
292  const std::vector<String>& columns);
293 
294  void ParseDataItemIdent(const StringRef ident,
295  StringRef& cat, StringRef& name);
296  void ParseGlobal();
297  void ParseData();
298  void ParseDataItem();
299  void DiagnoseUnknown();
300  bool ParseMultilineValue(String& value, bool skip=false);
301  std::ifstream fstream_;
302  boost::iostreams::filtering_stream<boost::iostreams::input> stream_;
303  String filename_;
304  int line_num_;
305  bool has_current_line_;
306  String current_line_;
307  bool items_as_row_;
308  StarLoopDesc items_row_header_;
309  bool file_open_;
310  std::vector<String> items_row_values_;
311 };
312 
313 }}
314 
315 #endif
convenient datatype for referencing character data
Definition: string_ref.hh:39
size_t size() const
Definition: string_ref.hh:54
std::string str() const
Definition: string_ref.hh:94
const StringRef & GetName() const
Definition: star_parser.hh:51
const StringRef & GetValue() const
Definition: star_parser.hh:52
const StringRef & GetCategory() const
Definition: star_parser.hh:50
StarDataItem(const StringRef &category, const StringRef &name, const StringRef &value)
Definition: star_parser.hh:46
size_t GetSize() const
Definition: star_parser.hh:82
void Add(const StringRef &name)
Definition: star_parser.hh:78
void SetCategory(const StringRef &category)
Definition: star_parser.hh:71
int GetIndex(const String &name) const
Definition: star_parser.hh:65
const String & GetCategory() const
Definition: star_parser.hh:92
parser for the STAR file format
Definition: star_parser.hh:114
std::pair< bool, float > TryGetFloat(const StringRef &data, const String &name, bool may_fail) const
try to convert a value to float, on failure raise an exception.
virtual bool OnBeginData(const StringRef &data_name)
invoked when a new data control structure is encountered
Definition: star_parser.hh:149
int GetCurrentLinenum() const
retrieve the line, the parser is currently working on
Definition: star_parser.hh:232
float TryGetFloat(const StringRef &data, const String &name) const
try to convert a value to float, on failure raise an exception.
static bool SplitLine(const StringRef &line, std::vector< StringRef > &parts, bool clear=true)
void SetFilename(const String &filename)
Definition: star_parser.hh:226
static bool IsUndefined(StringRef value)
Definition: star_parser.hh:242
virtual void OnEndData()
called when leaving a datasection. Will only be invoked when OnBeginData() returned true.
Definition: star_parser.hh:153
String FormatDiagnostic(StarDiagType type, const String &message, int line=-1) const
format diagnostic and returns it as a string.
virtual void OnEndLoop()
invoked when leaving a loop
Definition: star_parser.hh:135
virtual void OnDataItem(const StarDataItem &item)
invoked when a data item is encountered
Definition: star_parser.hh:144
virtual void OnDataRow(const StarLoopDesc &header, const std::vector< StringRef > &columns)
invoked when a data row in a loop is encountered.
Definition: star_parser.hh:139
Real TryGetReal(const StringRef &data, const String &name) const
try to convert a value to Real, on failure raise an exception.
int TryGetInt(const StringRef &data, const String &name) const
try to convert a value to integer, on failure raise an exception.
bool TryGetBool(const StringRef &data, const String &name) const
try to convert a value to bool, on failure raise an exception.
StarParser(std::istream &stream, bool items_as_row=false)
create a StarParser
StarParser(const String &filename, bool items_as_row=false)
std::pair< bool, int > TryGetInt(const StringRef &data, const String &name, bool may_fail) const
try to convert a value to integer, exception can be turned off.
virtual bool OnBeginLoop(const StarLoopDesc &header)
called when a loop is encountered
Definition: star_parser.hh:131
Real GetRealOrDefault(const StringRef &data, const String &name, Real alt, bool(*is_default)(StringRef)) const
try to convert a value to Real, on failure return default value.
#define DLLEXPORT_OST_IO
float Real
Definition: base.hh:44
std::string String
Definition: base.hh:54
@ STAR_DIAG_ERROR
Definition: star_parser.hh:40
@ STAR_DIAG_WARNING
Definition: star_parser.hh:39
Definition: base.dox:1