OpenStructure
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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-2011 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  void Add(const StringRef& name)
77  {
78  index_map_.insert(std::make_pair(name.str(), index_map_.size()));
79  }
80  size_t GetSize() const
81  {
82  return index_map_.size();
83  }
84  void Clear()
85  {
86  category_.clear();
87  index_map_.clear();
88  }
89 
90  const String& GetCategory() const { return category_; }
91 private:
92  String category_;
93  std::map<String, int> index_map_;
94 };
95 
112 class DLLEXPORT_OST_IO StarParser {
113 public:
120  explicit StarParser(std::istream& stream, bool items_as_row=false);
121  explicit StarParser(const String& filename, bool items_as_row=false);
122  virtual ~StarParser() { }
123 // callback interface
124 public:
129  virtual bool OnBeginLoop(const StarLoopDesc& header) { return true; }
133  virtual void OnEndLoop() { }
137  virtual void OnDataRow(const StarLoopDesc& header,
138  const std::vector<StringRef>& columns)
139  {
140  }
142  virtual void OnDataItem(const StarDataItem& item) { }
143 
147  virtual bool OnBeginData(const StringRef& data_name) { return true; }
148 
151  virtual void OnEndData() { }
152 
159  Real TryGetReal(const StringRef& data, const String& name) const;
160 
167  float TryGetFloat(const StringRef& data, const String& name) const;
168 
176  std::pair<bool, float> TryGetFloat(const StringRef& data,
177  const String& name,
178  bool may_fail) const;
179 
186  int TryGetInt(const StringRef& data, const String& name) const;
187 
195  std::pair<bool, int> TryGetInt(const StringRef& data,
196  const String& name,
197  bool may_fail) const;
198 
205  bool TryGetBool(const StringRef& data, const String& name) const;
206 
208  String FormatDiagnostic(StarDiagType type, const String& message,
209  int line=-1) const;
210 
211  void SetFilename(const String& filename)
212  {
213  filename_ = filename;
214  }
215 
217  int GetCurrentLinenum() const
218  {
219  return line_num_;
220  }
221 public:
222  void Parse();
223 
224 public:
225  static bool SplitLine(const StringRef& line,
226  std::vector<StringRef>& parts, bool clear=true);
227 private:
228  void ParseLoop();
231  void ParseLastDataItemRow();
234  void ParseDataItemOrRow(StarDataItem& item);
236  void ParseEndDataItemRow();
237 private:
239  bool NextLine(StringRef& str)
240  {
241  if (std::getline(stream_, current_line_)) {
242  str=StringRef(current_line_.data(), current_line_.length());
243  ++line_num_;
244  has_current_line_=true;
245  return true;
246  }
247  return false;
248  }
250  bool GetLine(StringRef& ref)
251  {
252  if (has_current_line_) {
253  ref=StringRef(current_line_.data(), current_line_.size());
254  return true;
255  }
256  return this->NextLine(ref);
257  }
258 
259  void ConsumeLine()
260  {
261  assert(has_current_line_);
262  has_current_line_=false;
263  }
264 
265  void ParseDataItemIdent(const StringRef ident,
266  StringRef& cat, StringRef& name);
267  void ParseGlobal();
268  void ParseData();
269  void ParseDataItem();
270  void DiagnoseUnknown();
271  bool ParseMultilineValue(String& value, bool skip=false);
272  std::ifstream fstream_;
273  boost::iostreams::filtering_stream<boost::iostreams::input> stream_;
274  String filename_;
275  int line_num_;
276  bool has_current_line_;
277  String current_line_;
278  bool items_as_row_;
279  StarLoopDesc items_row_header_;
280  bool file_open_;
281  std::vector<StringRef> items_row_columns_;
282  std::vector<String> items_row_values_;
283 };
284 
285 }}
286 
287 #endif