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 void Add(const StringRef& name)
00077 {
00078 index_map_.insert(std::make_pair(name.str(), index_map_.size()));
00079 }
00080 size_t GetSize() const
00081 {
00082 return index_map_.size();
00083 }
00084 void Clear()
00085 {
00086 category_.clear();
00087 index_map_.clear();
00088 }
00089
00090 const String& GetCategory() const { return category_; }
00091 private:
00092 String category_;
00093 std::map<String, int> index_map_;
00094 };
00095
00112 class DLLEXPORT_OST_IO StarParser {
00113 public:
00120 explicit StarParser(std::istream& stream, bool items_as_row=false);
00121 explicit StarParser(const String& filename, bool items_as_row=false);
00122 virtual ~StarParser() { }
00123
00124 public:
00129 virtual bool OnBeginLoop(const StarLoopDesc& header) { return true; }
00133 virtual void OnEndLoop() { }
00137 virtual void OnDataRow(const StarLoopDesc& header,
00138 const std::vector<StringRef>& columns)
00139 {
00140 }
00142 virtual void OnDataItem(const StarDataItem& item) { }
00143
00147 virtual bool OnBeginData(const StringRef& data_name) { return true; }
00148
00151 virtual void OnEndData() { }
00152
00159 Real TryGetReal(const StringRef& data, const String& name) const;
00160
00167 float TryGetFloat(const StringRef& data, const String& name) const;
00168
00176 std::pair<bool, float> TryGetFloat(const StringRef& data,
00177 const String& name,
00178 bool may_fail) const;
00179
00186 int TryGetInt(const StringRef& data, const String& name) const;
00187
00195 std::pair<bool, int> TryGetInt(const StringRef& data,
00196 const String& name,
00197 bool may_fail) const;
00198
00205 bool TryGetBool(const StringRef& data, const String& name) const;
00206
00208 String FormatDiagnostic(StarDiagType type, const String& message,
00209 int line=-1) const;
00210
00211 void SetFilename(const String& filename)
00212 {
00213 filename_ = filename;
00214 }
00215
00217 int GetCurrentLinenum() const
00218 {
00219 return line_num_;
00220 }
00221 public:
00222 void Parse();
00223
00224 public:
00225 static bool SplitLine(const StringRef& line,
00226 std::vector<StringRef>& parts, bool clear=true);
00227 private:
00228 void ParseLoop();
00231 void ParseLastDataItemRow();
00234 void ParseDataItemOrRow(StarDataItem& item);
00236 void ParseEndDataItemRow();
00237 private:
00239 bool NextLine(StringRef& str)
00240 {
00241 if (std::getline(stream_, current_line_)) {
00242 str=StringRef(current_line_.data(), current_line_.length());
00243 ++line_num_;
00244 has_current_line_=true;
00245 return true;
00246 }
00247 return false;
00248 }
00250 bool GetLine(StringRef& ref)
00251 {
00252 if (has_current_line_) {
00253 ref=StringRef(current_line_.data(), current_line_.size());
00254 return true;
00255 }
00256 return this->NextLine(ref);
00257 }
00258
00259 void ConsumeLine()
00260 {
00261 assert(has_current_line_);
00262 has_current_line_=false;
00263 }
00264
00265 void ParseDataItemIdent(const StringRef ident,
00266 StringRef& cat, StringRef& name);
00267 void ParseGlobal();
00268 void ParseData();
00269 void ParseDataItem();
00270 void DiagnoseUnknown();
00271 bool ParseMultilineValue(String& value, bool skip=false);
00272 std::ifstream fstream_;
00273 boost::iostreams::filtering_stream<boost::iostreams::input> stream_;
00274 String filename_;
00275 int line_num_;
00276 bool has_current_line_;
00277 String current_line_;
00278 bool items_as_row_;
00279 StarLoopDesc items_row_header_;
00280 bool file_open_;
00281 std::vector<StringRef> items_row_columns_;
00282 std::vector<String> items_row_values_;
00283 };
00284
00285 }}
00286
00287 #endif