00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef OST_IO_STAR_PARSER_HH
00020 #define OST_IO_STAR_PARSER_HH
00021
00022
00023
00024
00025
00026 #include <boost/iostreams/filtering_stream.hpp>
00027
00028 #include <iostream>
00029 #include <fstream>
00030 #include <vector>
00031 #include <map>
00032 #include <ost/string_ref.hh>
00033 #include <ost/io/module_config.hh>
00034
00035 namespace ost { namespace io {
00036
00037
00038 typedef enum {
00039 STAR_DIAG_WARNING,
00040 STAR_DIAG_ERROR
00041 } StarDiagType;
00042
00043
00044 class DLLEXPORT_OST_IO StarDataItem {
00045 public:
00046 StarDataItem(const StringRef& category, const StringRef& name,
00047 const StringRef& value):
00048 category_(category), name_(name), value_(value)
00049 { }
00050 const StringRef& GetCategory() const { return category_; }
00051 const StringRef& GetName() const { return name_; }
00052 const StringRef& GetValue() const { return value_; }
00053 private:
00054 StringRef category_;
00055 StringRef name_;
00056 StringRef value_;
00057 };
00058
00059 class DLLEXPORT_OST_IO StarLoopDesc {
00060 public:
00061 StarLoopDesc():
00062 category_("")
00063 { }
00064
00065 int GetIndex(const String& name) const
00066 {
00067 std::map<String, int>::const_iterator i=index_map_.find(name);
00068 return i==index_map_.end() ? -1 : i->second;
00069 }
00070
00071 void SetCategory(const StringRef& category)
00072 {
00073 category_=category.str();
00074 }
00075
00076
00077
00078 void Add(const StringRef& name)
00079 {
00080 index_map_.insert(std::make_pair(name.str(), index_map_.size()));
00081 }
00082 size_t GetSize() const
00083 {
00084 return index_map_.size();
00085 }
00086 void Clear()
00087 {
00088 category_.clear();
00089 index_map_.clear();
00090 }
00091
00092 const String& GetCategory() const { return category_; }
00093 private:
00094 String category_;
00095 std::map<String, int> index_map_;
00096 };
00097
00114 class DLLEXPORT_OST_IO StarParser {
00115 public:
00122 explicit StarParser(std::istream& stream, bool items_as_row=false);
00123 explicit StarParser(const String& filename, bool items_as_row=false);
00124 virtual ~StarParser() { }
00125
00126 public:
00131 virtual bool OnBeginLoop(const StarLoopDesc& header) { return true; }
00135 virtual void OnEndLoop() { }
00139 virtual void OnDataRow(const StarLoopDesc& header,
00140 const std::vector<StringRef>& columns)
00141 {
00142 }
00144 virtual void OnDataItem(const StarDataItem& item) { }
00145
00149 virtual bool OnBeginData(const StringRef& data_name) { return true; }
00150
00153 virtual void OnEndData() { }
00154
00161 Real TryGetReal(const StringRef& data, const String& name) const;
00162
00169 float TryGetFloat(const StringRef& data, const String& name) const;
00170
00178 std::pair<bool, float> TryGetFloat(const StringRef& data,
00179 const String& name,
00180 bool may_fail) const;
00181
00188 int TryGetInt(const StringRef& data, const String& name) const;
00189
00197 std::pair<bool, int> TryGetInt(const StringRef& data,
00198 const String& name,
00199 bool may_fail) const;
00200
00207 bool TryGetBool(const StringRef& data, const String& name) const;
00208
00210 String FormatDiagnostic(StarDiagType type, const String& message,
00211 int line=-1) const;
00212
00213 void SetFilename(const String& filename)
00214 {
00215 filename_ = filename;
00216 }
00217
00219 int GetCurrentLinenum() const
00220 {
00221 return line_num_;
00222 }
00223 public:
00224 void Parse();
00225
00226 public:
00227 static bool SplitLine(const StringRef& line,
00228 std::vector<StringRef>& parts, bool clear=true);
00229 private:
00230 void ParseLoop();
00233 void ParseLastDataItemRow();
00236 void ParseDataItemOrRow(StarDataItem& item);
00238 void ParseEndDataItemRow();
00239 private:
00241 bool NextLine(StringRef& str)
00242 {
00243 if (std::getline(stream_, current_line_)) {
00244 str=StringRef(current_line_.data(), current_line_.length());
00245 ++line_num_;
00246 has_current_line_=true;
00247 return true;
00248 }
00249 return false;
00250 }
00252 bool GetLine(StringRef& ref)
00253 {
00254 if (has_current_line_) {
00255 ref=StringRef(current_line_.data(), current_line_.size());
00256 return true;
00257 }
00258 return this->NextLine(ref);
00259 }
00260
00261 void ConsumeLine()
00262 {
00263 assert(has_current_line_);
00264 has_current_line_=false;
00265 }
00266
00267
00268
00269
00270
00271
00272
00273 void CallOnDataRow(const StarLoopDesc& header,
00274 const std::vector<String>& columns);
00275
00276 void ParseDataItemIdent(const StringRef ident,
00277 StringRef& cat, StringRef& name);
00278 void ParseGlobal();
00279 void ParseData();
00280 void ParseDataItem();
00281 void DiagnoseUnknown();
00282 bool ParseMultilineValue(String& value, bool skip=false);
00283 std::ifstream fstream_;
00284 boost::iostreams::filtering_stream<boost::iostreams::input> stream_;
00285 String filename_;
00286 int line_num_;
00287 bool has_current_line_;
00288 String current_line_;
00289 bool items_as_row_;
00290 StarLoopDesc items_row_header_;
00291 bool file_open_;
00292 std::vector<String> items_row_values_;
00293 };
00294
00295 }}
00296
00297 #endif