1 /* 2 * This source file is part of MyGUI. For the latest info, see http://mygui.info/ 3 * Distributed under the MIT License 4 * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT) 5 */ 6 7 #ifndef MYGUI_XML_DOCUMENT_H_ 8 #define MYGUI_XML_DOCUMENT_H_ 9 10 #include "MyGUI_Prerequest.h" 11 #include "MyGUI_UString.h" 12 #include "MyGUI_Diagnostic.h" 13 #include "MyGUI_DataStream.h" 14 15 #include <vector> 16 #include <string> 17 #include <iostream> 18 #include <fstream> 19 #include <sstream> 20 #include <cassert> 21 22 namespace MyGUI 23 { 24 namespace xml 25 { 26 27 struct ElementType 28 { 29 enum Enum 30 { 31 Comment, 32 Declaration, 33 Normal, 34 MAX 35 }; 36 mValueElementType37 ElementType(Enum _value = MAX) : mValue(_value) { } 38 friend bool operator == (ElementType const& a, ElementType const& b) 39 { 40 return a.mValue == b.mValue; 41 } 42 friend bool operator != (ElementType const& a, ElementType const& b) 43 { 44 return a.mValue != b.mValue; 45 } 46 getValueElementType47 int getValue() const 48 { 49 return mValue; 50 } 51 52 private: 53 Enum mValue; 54 }; 55 56 struct ErrorType 57 { 58 enum Enum 59 { 60 OpenFileFail, 61 CreateFileFail, 62 IncorrectContent, 63 NotClosedElements, 64 NoXMLDeclaration, 65 CloseNotOpenedElement, 66 InconsistentOpenCloseElements, 67 MoreThanOneXMLDeclaration, 68 MoreThanOneRootElement, 69 IncorrectAttribute, 70 MAX 71 }; 72 mValueErrorType73 ErrorType(Enum _value = MAX) : mValue(_value) { } 74 printErrorType75 std::string print() const 76 { 77 return getValueName(mValue); 78 } 79 80 private: getValueNameErrorType81 const char* getValueName(int _index) const 82 { 83 static const char* values[MAX + 1] = 84 { 85 "Failed to open XML file", 86 "Failed to ceate XML file", 87 "XML file contain incorrect content", 88 "XML file contain not closed elements", 89 "XML file without declaration", 90 "XML file contain closed but not opened element", 91 "XML file contain inconsistent elements", 92 "XML file contain more than one declaration", 93 "XML file contain more than one root element", 94 "XML file contain incorrect attribute", 95 "" 96 }; 97 return values[(_index < MAX && _index >= 0) ? _index : MAX]; 98 } 99 private: 100 Enum mValue; 101 }; 102 103 class Element; 104 class Document; 105 106 using ElementPtr = Element*; 107 typedef std::pair<std::string, std::string> PairAttribute; 108 using VectorAttributes = std::vector<PairAttribute>; 109 using VectorElement = std::vector<ElementPtr>; 110 111 //----------------------------------------------------------------------// 112 // class ElementEnumerator 113 //----------------------------------------------------------------------// 114 class MYGUI_EXPORT ElementEnumerator 115 { 116 friend class Element; 117 118 private: 119 ElementEnumerator(VectorElement::iterator _begin, VectorElement::iterator _end); 120 121 public: 122 bool next(); 123 bool next(const std::string& _name); 124 125 ElementPtr operator->() const; 126 ElementPtr current(); 127 128 /*obsolete:*/ 129 #ifndef MYGUI_DONT_USE_OBSOLETE 130 131 MYGUI_OBSOLETE("use : bool ElementEnumerator::next()") nextNode()132 bool nextNode() 133 { 134 return next(); 135 } 136 MYGUI_OBSOLETE("use : bool ElementEnumerator::next(const std::string& _name)") nextNode(const std::string & _name)137 bool nextNode(const std::string& _name) 138 { 139 return next(_name); 140 } 141 MYGUI_OBSOLETE("use : ElementPtr ElementEnumerator::current()") currentNode()142 ElementPtr currentNode() 143 { 144 return current(); 145 } 146 147 #endif // MYGUI_DONT_USE_OBSOLETE 148 149 private: 150 bool m_first; 151 VectorElement::iterator m_current, m_end; 152 }; 153 154 155 //----------------------------------------------------------------------// 156 // class Element 157 //----------------------------------------------------------------------// 158 class MYGUI_EXPORT Element 159 { 160 friend class Document; 161 162 public: 163 ~Element(); 164 165 private: 166 Element(const std::string& _name, ElementPtr _parent, ElementType _type = ElementType::Normal, const std::string& _content = ""); 167 void save(std::ostream& _stream, size_t _level); 168 169 public: 170 ElementPtr createChild(const std::string& _name, const std::string& _content = "", ElementType _type = ElementType::Normal); 171 void removeChild(ElementPtr _child); 172 173 template <typename T> addAttribute(const std::string & _key,const T & _value)174 void addAttribute(const std::string& _key, const T& _value) 175 { 176 addAttribute(_key, utility::toString(_value)); 177 } 178 179 void addAttribute(const std::string& _key, const std::string& _value); 180 181 void removeAttribute(const std::string& _key); 182 183 void setAttribute(const std::string& _key, const std::string& _value); 184 185 template <typename T> addContent(const T & _content)186 void addContent(const T& _content) 187 { 188 addContent(utility::toString(_content)); 189 } 190 191 void addContent(const std::string& _content); 192 193 template <typename T> setContent(const T & _content)194 void setContent(const T& _content) 195 { 196 setContent(utility::toString(_content)); 197 } 198 199 void setContent(const std::string& _content); 200 201 void clear(); 202 203 bool findAttribute(const std::string& _name, std::string& _value); 204 std::string findAttribute(const std::string& _name); 205 206 const std::string& getName() const; 207 208 const std::string& getContent() const; 209 210 const VectorAttributes& getAttributes() const; 211 212 ElementPtr getParent() const; 213 214 ElementEnumerator getElementEnumerator(); 215 216 ElementType getType() const; 217 218 ElementPtr createCopy(); 219 220 /*obsolete:*/ 221 #ifndef MYGUI_DONT_USE_OBSOLETE 222 223 template <typename T> 224 MYGUI_OBSOLETE("use : template <typename T> void Element::addAttribute(const std::string &_key, const T& _value)") addAttributes(const std::string & _key,const T & _value)225 void addAttributes(const std::string& _key, const T& _value) 226 { 227 addAttribute<T>(_key, _value); 228 } 229 MYGUI_OBSOLETE("use : void Element::addAttribute(const std::string& _key, const std::string& _value)") addAttributes(const std::string & _key,const std::string & _value)230 void addAttributes(const std::string& _key, const std::string& _value) 231 { 232 addAttribute(_key, _value); 233 } 234 235 template <typename T> 236 MYGUI_OBSOLETE("use : template <typename T> void Element::addContent(const T& _content)") addBody(const T & _content)237 void addBody(const T& _content) 238 { 239 addContent<T>(_content); 240 } 241 MYGUI_OBSOLETE("use : void Element::addContent(const std::string& _content)") addBody(const std::string & _content)242 void addBody(const std::string& _content) 243 { 244 addContent(_content); 245 } 246 template <typename T> 247 MYGUI_OBSOLETE("use : template <typename T> void Element::setContent(const T& _content)") setBody(const T & _content)248 void setBody(const T& _content) 249 { 250 setContent<T>(_content); 251 } 252 MYGUI_OBSOLETE("use : void Element::setContent(const std::string& _content)") setBody(const std::string & _content)253 void setBody(const std::string& _content) 254 { 255 setContent(_content); 256 } 257 258 MYGUI_OBSOLETE("use : const std::string& Element::getContent()") getBody()259 const std::string& getBody() const 260 { 261 return getContent(); 262 } 263 MYGUI_OBSOLETE("use : ElementEnumerator Element::getElementEnumerator()") getNodeIterator()264 ElementEnumerator getNodeIterator() 265 { 266 return getElementEnumerator(); 267 } 268 269 #endif // MYGUI_DONT_USE_OBSOLETE 270 271 private: 272 std::string mName; 273 std::string mContent; 274 VectorAttributes mAttributes; 275 VectorElement mChilds; 276 ElementPtr mParent; 277 ElementType mType; 278 }; 279 280 //----------------------------------------------------------------------// 281 // class Document 282 //----------------------------------------------------------------------// 283 class MYGUI_EXPORT Document 284 { 285 public: 286 Document(); 287 ~Document(); 288 289 // открывает обычным файлом, имя файла в utf8 290 bool open(const std::string& _filename); 291 292 // открывает обычным файлом, имя файла в utf16 или utf32 293 bool open(const std::wstring& _filename); 294 295 // открывает обычным потоком 296 bool open(std::istream& _stream); 297 298 bool open(const UString& _filename); 299 300 bool open(IDataStream* _data); 301 302 // сохраняет файл 303 bool save(const std::string& _filename); 304 305 // сохраняет файл 306 bool save(const std::wstring& _filename); 307 308 bool save(std::ostream& _stream); 309 310 bool save(const UString& _filename); 311 312 void clear(); 313 314 std::string getLastError(); 315 316 void clearLastError(); 317 318 ElementPtr createDeclaration(const std::string& _version = "1.0", const std::string& _encoding = "UTF-8"); 319 ElementPtr createRoot(const std::string& _name); 320 321 ElementPtr getRoot() const; 322 323 /*obsolete:*/ 324 #ifndef MYGUI_DONT_USE_OBSOLETE 325 326 MYGUI_OBSOLETE("use : ElementPtr Document::createDeclaration(const std::string& _version, const std::string& _encoding)") 327 ElementPtr createInfo(const std::string& _version = "1.0", const std::string& _encoding = "UTF-8") 328 { 329 return createDeclaration(_version, _encoding); 330 } 331 332 #endif // MYGUI_DONT_USE_OBSOLETE 333 334 private: 335 void setLastFileError(const std::string& _filename); 336 void setLastFileError(const std::wstring& _filename); 337 338 bool parseTag(ElementPtr& _currentNode, std::string _content); 339 340 bool checkPair(std::string& _key, std::string& _value); 341 342 bool parseLine(std::string& _line, ElementPtr& _element); 343 344 // ищет символ без учета ковычек 345 size_t find(const std::string& _text, char _char, size_t _start = 0); 346 347 void clearDeclaration(); 348 void clearRoot(); 349 350 private: 351 ElementPtr mRoot; 352 ElementPtr mDeclaration; 353 ErrorType mLastError; 354 std::string mLastErrorFile; 355 size_t mLine; 356 size_t mCol; 357 358 }; // class Document 359 360 MYGUI_OBSOLETE("use : class MyGUI::xml::ElementEnumerator") 361 typedef ElementEnumerator xmlNodeIterator; 362 MYGUI_OBSOLETE("use : class MyGUI::xml::ElementPtr") 363 typedef ElementPtr xmlNodePtr; 364 MYGUI_OBSOLETE("use : class MyGUI::xml::Document") 365 typedef Document xmlDocument; 366 367 } // namespace xml 368 369 } // namespace MyGUI 370 371 #endif // MYGUI_XML_DOCUMENT_H_ 372