1 //////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // Nestopia - NES/Famicom emulator written in C++ 4 // 5 // Copyright (C) 2003-2008 Martin Freij 6 // 7 // This file is part of Nestopia. 8 // 9 // Nestopia is free software; you can redistribute it and/or modify 10 // it under the terms of the GNU General Public License as published by 11 // the Free Software Foundation; either version 2 of the License, or 12 // (at your option) any later version. 13 // 14 // Nestopia is distributed in the hope that it will be useful, 15 // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 // GNU General Public License for more details. 18 // 19 // You should have received a copy of the GNU General Public License 20 // along with Nestopia; if not, write to the Free Software 21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 // 23 //////////////////////////////////////////////////////////////////////////////////////// 24 25 #ifndef NST_XML_H 26 #define NST_XML_H 27 28 #include <cstring> 29 #include <iosfwd> 30 31 #ifdef NST_PRAGMA_ONCE 32 #pragma once 33 #endif 34 35 namespace Nes 36 { 37 namespace Core 38 { 39 class Xml 40 { 41 typedef word utfchar; 42 typedef const word* utfstring; 43 44 static inline int ToChar(idword); 45 static inline wchar_t ToWideChar(idword); 46 47 class BaseNode 48 { 49 public: 50 51 enum In {IN}; 52 enum Out {OUT}; 53 54 private: 55 56 static utfchar ParseReference(utfstring&,utfstring); 57 58 static wchar_t* SetType(wchar_t* NST_RESTRICT,utfstring,utfstring,In); 59 static wchar_t* SetType(wchar_t* NST_RESTRICT,wcstring,wcstring,Out); 60 61 static wchar_t* SetValue(wchar_t* NST_RESTRICT,utfstring,utfstring,In); 62 static wchar_t* SetValue(wchar_t* NST_RESTRICT,wcstring,wcstring,Out); 63 64 public: 65 66 struct Attribute 67 { 68 template<typename T,typename U> 69 Attribute(T,T,T,T,U); 70 71 ~Attribute(); 72 73 wcstring const type; 74 wcstring const value; 75 Attribute* next; 76 }; 77 78 template<typename T,typename U> 79 BaseNode(T,T,U); 80 81 ~BaseNode(); 82 83 template<typename T,typename U> 84 void SetValue(T,T,U); 85 86 void AddAttribute(utfstring,utfstring,utfstring,utfstring); 87 88 wcstring const type; 89 wcstring value; 90 Attribute* attribute; 91 BaseNode* child; 92 BaseNode* sibling; 93 }; 94 95 static bool IsEqual(wcstring,wcstring); 96 static bool IsEqualNonCase(wcstring,wcstring); 97 static long ToSigned(wcstring,uint,wcstring*); 98 static ulong ToUnsigned(wcstring,uint,wcstring*); 99 100 public: 101 102 Xml(); 103 ~Xml(); 104 105 class Node; 106 107 class Attribute : public ImplicitBool<Attribute> 108 { 109 public: 110 111 long GetSignedValue(uint=0) const; 112 long GetSignedValue(wcstring&,uint=0) const; 113 114 ulong GetUnsignedValue(uint=0) const; 115 ulong GetUnsignedValue(wcstring&,uint=0) const; 116 117 private: 118 119 friend class Node; 120 121 BaseNode::Attribute* attribute; 122 Attribute(BaseNode::Attribute * a)123 Attribute(BaseNode::Attribute* a) 124 : attribute(a) {} 125 126 public: 127 operator !() const128 bool operator ! () const 129 { 130 return !attribute; 131 } 132 GetType() const133 wcstring GetType() const 134 { 135 return attribute ? attribute->type : L""; 136 } 137 GetValue() const138 wcstring GetValue() const 139 { 140 return attribute ? attribute->value : L""; 141 } 142 GetNext() const143 Attribute GetNext() const 144 { 145 return attribute ? attribute->next : NULL; 146 } 147 IsType(wcstring type) const148 bool IsType(wcstring type) const 149 { 150 return IsEqual( GetType(), type ? type : L"" ); 151 } 152 IsValue(wcstring value) const153 bool IsValue(wcstring value) const 154 { 155 return IsEqualNonCase( GetValue(), value ? value : L"" ); 156 } 157 }; 158 159 class Node : public ImplicitBool<Node> 160 { 161 friend class Xml; 162 163 public: 164 165 dword NumChildren(wcstring=NULL) const; 166 dword NumAttributes() const; 167 168 Attribute GetAttribute(dword) const; 169 Attribute GetAttribute(wcstring) const; 170 171 Node GetChild(dword) const; 172 Node GetChild(wcstring) const; 173 174 Node AddChild(wcstring,wcstring=NULL); 175 Node AddSibling(wcstring,wcstring=NULL); 176 Attribute AddAttribute(wcstring,wcstring); 177 178 long GetSignedValue(uint=0) const; 179 long GetSignedValue(wcstring&,uint=0) const; 180 181 ulong GetUnsignedValue(uint=0) const; 182 ulong GetUnsignedValue(wcstring&,uint=0) const; 183 184 private: 185 186 BaseNode* Add(wcstring,wcstring,BaseNode**) const; 187 188 BaseNode* node; 189 Node(BaseNode * n)190 Node(BaseNode* n) 191 : node(n) {} 192 193 public: 194 Node()195 Node() 196 : node(NULL) {} 197 operator !() const198 bool operator ! () const 199 { 200 return !node; 201 } 202 HasChildren() const203 bool HasChildren() const 204 { 205 return node && node->child; 206 } 207 HasNextSibling() const208 bool HasNextSibling() const 209 { 210 return node && node->sibling; 211 } 212 HasAttributes() const213 bool HasAttributes() const 214 { 215 return node && node->attribute; 216 } 217 GetFirstAttribute() const218 Attribute GetFirstAttribute() const 219 { 220 return node ? node->attribute : NULL; 221 } 222 GetFirstChild() const223 Node GetFirstChild() const 224 { 225 return node ? node->child : NULL; 226 } 227 GetNextSibling() const228 Node GetNextSibling() const 229 { 230 return node ? node->sibling : NULL; 231 } 232 GetType() const233 wcstring GetType() const 234 { 235 return node ? node->type : L""; 236 } 237 GetValue() const238 wcstring GetValue() const 239 { 240 return node ? node->value : L""; 241 } 242 IsType(wcstring type) const243 bool IsType(wcstring type) const 244 { 245 return IsEqual( GetType(), type ? type : L"" ); 246 } 247 IsValue(wcstring value) const248 bool IsValue(wcstring value) const 249 { 250 return IsEqualNonCase( GetValue(), value ? value : L"" ); 251 } 252 }; 253 254 struct Format 255 { 256 Format(); 257 258 cstring tab; 259 cstring newline; 260 cstring valueDelimiter; 261 bool xmlHeader; 262 bool byteOrderMark; 263 }; 264 265 Node Create(wcstring); 266 Node Read(utfstring); 267 Node Read(std::istream&); 268 void Write(Node,std::ostream&,const Format& = Format()) const; 269 void Destroy(); 270 271 private: 272 273 enum Tag 274 { 275 TAG_XML, 276 TAG_COMMENT, 277 TAG_INSTRUCTION, 278 TAG_OPEN, 279 TAG_OPEN_CLOSE, 280 TAG_CLOSE 281 }; 282 283 class Input 284 { 285 static byte* Init(std::istream&,dword&); 286 287 const byte* const stream; 288 const dword size; 289 dword pos; 290 291 public: 292 293 Input(std::istream&,dword=0); 294 ~Input(); 295 296 inline dword Size() const; 297 298 inline uint ToByte(dword) const; 299 inline int ToChar(dword) const; 300 inline uint FromUTF16LE(dword) const; 301 inline uint FromUTF16BE(dword) const; 302 303 uint ReadUTF8(); 304 inline void SetReadPointer(dword); 305 }; 306 307 class Output 308 { 309 std::ostream& stream; 310 311 void Write(cstring,uint) const; 312 313 public: 314 315 const Format format; 316 317 Output(std::ostream&,const Format&); 318 319 class Type 320 { 321 friend class Output; 322 wcstring string; 323 324 public: 325 326 inline Type(wcstring); 327 }; 328 329 class Value 330 { 331 friend class Output; 332 wcstring string; 333 334 public: 335 336 inline Value(wcstring); 337 }; 338 339 const Output& operator << (char) const; 340 const Output& operator << (wchar_t) const; 341 const Output& operator << (byte) const; 342 const Output& operator << (Type) const; 343 const Output& operator << (Value) const; 344 345 inline const Output& operator << (cstring) const; 346 347 template<uint N> 348 inline const Output& operator << (const char (&)[N]) const; 349 }; 350 351 static bool IsVoid(utfchar); 352 static bool IsCtrl(utfchar); 353 static Tag CheckTag(utfstring); 354 355 static utfstring SkipVoid(utfstring); 356 static utfstring RewindVoid(utfstring,utfstring=NULL); 357 static utfstring ReadTag(utfstring,BaseNode*&); 358 static utfstring ReadValue(utfstring,BaseNode&); 359 static utfstring ReadNode(utfstring,Tag,BaseNode*&); 360 static void WriteNode(Node,const Output&,uint); 361 362 BaseNode* root; 363 364 public: 365 GetRoot() const366 Node GetRoot() const 367 { 368 return root; 369 } 370 }; 371 } 372 } 373 374 #endif 375