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