1 // XML_Parser.h - an XML file reader 2 // 3 // Vamos Automotive Simulator 4 // Copyright (C) 2004 Sam Varner 5 // 6 // This program is free software; you can redistribute it and/or modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation; either version 2 of the License, or 9 // (at your option) any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program; if not, write to the Free Software 18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 20 #ifndef _XML_PARSER_H_ 21 #define _XML_PARSER_H_ 22 23 #include <string> 24 #include <fstream> 25 #include <vector> 26 27 namespace Vamos_Media 28 { 29 //** Exception Classes 30 class XML_Exception 31 { 32 protected: 33 std::string m_file; 34 int m_line; 35 std::string m_message; 36 public: 37 XML_Exception (std::string file, int line = 0, std::string message = "") : m_file(file)38 m_file (file), 39 m_line (line), 40 m_message (message) 41 {}; ~XML_Exception()42 virtual ~XML_Exception () {}; 43 44 virtual std::string message () const; 45 }; 46 47 class No_XML_File : public XML_Exception 48 { 49 public: No_XML_File(std::string file)50 No_XML_File (std::string file) : XML_Exception (file) {}; message()51 std::string message () const 52 { return "Can't find the file \"" + m_file + '"'; } 53 }; 54 55 class No_Declaration : public XML_Exception 56 { 57 public: No_Declaration(std::string file,int line,std::string message)58 No_Declaration (std::string file, int line, std::string message) : 59 XML_Exception (file, line, message) {}; 60 }; 61 62 class Bad_Tag_Type : public XML_Exception 63 { 64 public: Bad_Tag_Type(std::string file,int line,std::string message)65 Bad_Tag_Type (std::string file, int line, std::string message) : 66 XML_Exception (file, line, message) {}; 67 }; 68 69 class Tag_Mismatch : public XML_Exception 70 { 71 public: Tag_Mismatch(std::string file,int line,std::string message)72 Tag_Mismatch (std::string file, int line, std::string message) : 73 XML_Exception (file, line, message) {} 74 }; 75 76 struct XML_Unterminated 77 { 78 int lines; 79 std::string text; 80 bool eof; 81 char delimiter; 82 XML_UnterminatedXML_Unterminated83 XML_Unterminated (int lines_in, 84 std::string text_in, 85 bool eof_in, 86 char delimiter_in) : 87 lines (lines_in), 88 text (text_in), 89 eof (eof_in), 90 delimiter (delimiter_in) 91 {}; 92 }; 93 94 struct Unterminated_Tag : public XML_Unterminated 95 { Unterminated_TagUnterminated_Tag96 Unterminated_Tag (int lines_in, std::string text_in, bool eof_in) 97 : XML_Unterminated (lines_in, text_in, eof_in, '>') {}; 98 }; 99 100 struct Unterminated_Attribute : public XML_Unterminated 101 { Unterminated_AttributeUnterminated_Attribute102 Unterminated_Attribute (int lines_in, std::string text_in, bool eof_in) 103 : XML_Unterminated (lines_in, text_in, eof_in, '"') {}; 104 }; 105 106 107 108 //** Class XML_Tag 109 class XML_Tag 110 { 111 public: 112 enum Tag_Type 113 { 114 NONE, 115 START, 116 END, 117 EMPTY, 118 PROCESSING_INSTRUCTION, 119 COMMENT 120 }; 121 122 struct Attribute 123 { AttributeAttribute124 Attribute (std::string name_in, std::string value_in) 125 : name (name_in), value (value_in) {} 126 std::string name; 127 std::string value; 128 }; 129 130 typedef std::vector <Attribute> Attribute_List; 131 132 private: 133 typedef std::string::iterator String_Iterator; 134 135 Tag_Type m_type; 136 int m_lines; 137 std::vector <Attribute> m_attributes; 138 std::string m_data; 139 std::string m_text; 140 std::string m_label; 141 142 // Read everything up to the next '<'. Return true if '<' was found. 143 bool read_to_tag_start (std::ifstream& stream); 144 145 // Read everything up to the next `>'. Return true if '>' was found. 146 bool read_to_tag_end (std::ifstream& stream); 147 148 // Determine the type of the tag. 149 Tag_Type find_tag_type (std::ifstream& stream); 150 151 // Determine the tag's label. 152 std::string find_label (String_Iterator text_start, 153 String_Iterator text_end); 154 155 // Get the next character from the stream. 156 std::ifstream& get_next_char (std::ifstream& stream, char& ch); 157 158 // Parse attributes. 159 void find_attributes (String_Iterator attr_begin, 160 String_Iterator attr_end); 161 162 // Throw out characters inside a comment. 163 void eat_comment (std::ifstream& stream); 164 165 bool find_comment_end (std::ifstream& stream); 166 167 void skip_spaces (String_Iterator& text_start); 168 169 Attribute get_attribute (String_Iterator text_start, 170 String_Iterator text_end); 171 void get_text_boundries (String_Iterator& text_start, 172 String_Iterator& text_end); 173 174 public: 175 XML_Tag (std::ifstream& stream); 176 get_type()177 Tag_Type get_type () const { return m_type; } get_lines()178 int get_lines () const { return m_lines; } get_attributes()179 const Attribute_List& get_attributes () const { return m_attributes; } get_data()180 std::string get_data () const { return m_data; } get_text()181 std::string get_text () const { return m_text; } get_label()182 std::string get_label () const { return m_label; } 183 }; 184 185 //** XML Tag Path Class 186 class XML_Path 187 { 188 std::string m_path; 189 190 public: push(std::string element)191 void push (std::string element) { m_path += '/' + element; } drop()192 void drop () { m_path = m_path.substr (0, m_path.find_last_of ("/")); } empty()193 bool empty () const { return m_path.empty (); } 194 bool match (std::string pattern) const; path()195 std::string path () const { return m_path; } 196 std::string subpath (size_t n) const; top()197 std::string top () const { return subpath (1); } 198 }; 199 200 //** Parser Class 201 class XML_Parser 202 { 203 public: 204 XML_Parser (); 205 virtual ~XML_Parser (); 206 207 void read (std::string file); 208 void error (std::string message); 209 match(std::string pattern)210 bool match (std::string pattern) const { return m_path.match (pattern); } path()211 std::string path () const { return m_path.path (); } label()212 std::string label () const { return m_path.top (); } 213 214 // Event handlers overridden by derived classes. 215 virtual void on_start_tag (const XML_Tag& tag) = 0; 216 virtual void on_end_tag (const XML_Tag& tag) = 0; 217 virtual void on_data (std::string data_string) = 0; 218 219 private: 220 std::string m_file; 221 std::ifstream* mp_stream; 222 int m_line; 223 XML_Path m_path; 224 225 void check_declaration (); 226 void read_document (); 227 bool run_callbacks (const XML_Tag& tag); 228 void add_tag (const XML_Tag& tag); 229 void remove_tag (const XML_Tag& tag); 230 void handle_unterminated (XML_Unterminated& unterminated); 231 }; 232 } 233 234 #endif // not _XML_PARSER_H_ 235