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 {
41 } StarDiagType;
42 
43 
44 class DLLEXPORT_OST_IO StarDataItem {
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 
59 class DLLEXPORT_OST_IO StarLoopDesc {
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 
114 class DLLEXPORT_OST_IO StarParser {
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 private:
243  void ParseLoop();
246  void ParseLastDataItemRow();
249  void ParseDataItemOrRow(StarDataItem& item);
251  void ParseEndDataItemRow();
252 private:
254  bool NextLine(StringRef& str)
255  {
256  if (std::getline(stream_, current_line_)) {
257  str=StringRef(current_line_.data(), current_line_.length());
258  ++line_num_;
259  has_current_line_=true;
260  return true;
261  }
262  return false;
263  }
265  bool GetLine(StringRef& ref)
266  {
267  if (has_current_line_) {
268  ref=StringRef(current_line_.data(), current_line_.size());
269  return true;
270  }
271  return this->NextLine(ref);
272  }
273 
274  void ConsumeLine()
275  {
276  assert(has_current_line_);
277  has_current_line_=false;
278  }
279 
280  // the reason for having this function are problems when generating
281  // StringRefs that contain pointers to strings in a vector.
282  // When the vector grows, the memory of the strings might get
283  // reallocated and the StringRefs point into nothing.
284  // This function Prepares the stringrefs given a constant
285  // vector and calls OnDataRow to minimize the change in interface.
286  void CallOnDataRow(const StarLoopDesc& header,
287  const std::vector<String>& columns);
288 
289  void ParseDataItemIdent(const StringRef ident,
290  StringRef& cat, StringRef& name);
291  void ParseGlobal();
292  void ParseData();
293  void ParseDataItem();
294  void DiagnoseUnknown();
295  bool ParseMultilineValue(String& value, bool skip=false);
296  std::ifstream fstream_;
297  boost::iostreams::filtering_stream<boost::iostreams::input> stream_;
298  String filename_;
299  int line_num_;
300  bool has_current_line_;
301  String current_line_;
302  bool items_as_row_;
303  StarLoopDesc items_row_header_;
304  bool file_open_;
305  std::vector<String> items_row_values_;
306 };
307 
308 }}
309 
310 #endif
convenient datatype for referencing character data
Definition: string_ref.hh:39
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
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
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