diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CXMLWriter.cpp | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CXMLWriter.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CXMLWriter.cpp new file mode 100644 index 0000000..cc294c5 --- /dev/null +++ b/libraries/irrlicht-1.8/source/Irrlicht/CXMLWriter.cpp | |||
@@ -0,0 +1,257 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | ||
2 | // This file is part of the "Irrlicht Engine". | ||
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | ||
4 | |||
5 | #include "CXMLWriter.h" | ||
6 | #include <wchar.h> | ||
7 | #include "irrString.h" | ||
8 | #include "IrrCompileConfig.h" | ||
9 | |||
10 | namespace irr | ||
11 | { | ||
12 | namespace io | ||
13 | { | ||
14 | |||
15 | |||
16 | //! Constructor | ||
17 | CXMLWriter::CXMLWriter(IWriteFile* file) | ||
18 | : File(file), Tabs(0), TextWrittenLast(false) | ||
19 | { | ||
20 | #ifdef _DEBUG | ||
21 | setDebugName("CXMLWriter"); | ||
22 | #endif | ||
23 | |||
24 | if (File) | ||
25 | File->grab(); | ||
26 | } | ||
27 | |||
28 | |||
29 | |||
30 | //! Destructor | ||
31 | CXMLWriter::~CXMLWriter() | ||
32 | { | ||
33 | if (File) | ||
34 | File->drop(); | ||
35 | } | ||
36 | |||
37 | |||
38 | |||
39 | //! Writes a xml 1.0 header like <?xml version="1.0"?> | ||
40 | void CXMLWriter::writeXMLHeader() | ||
41 | { | ||
42 | if (!File) | ||
43 | return; | ||
44 | |||
45 | if (sizeof(wchar_t)==2) | ||
46 | { | ||
47 | const u16 h = 0xFEFF; | ||
48 | File->write(&h, 2); | ||
49 | } | ||
50 | else | ||
51 | { | ||
52 | const u32 h = 0x0000FEFF; | ||
53 | File->write(&h, sizeof(wchar_t)); | ||
54 | } | ||
55 | |||
56 | const wchar_t* const p = L"<?xml version=\"1.0\"?>"; | ||
57 | File->write(p, wcslen(p)*sizeof(wchar_t)); | ||
58 | |||
59 | writeLineBreak(); | ||
60 | TextWrittenLast = false; | ||
61 | } | ||
62 | |||
63 | |||
64 | |||
65 | //! Writes an xml element with maximal 5 attributes | ||
66 | void CXMLWriter::writeElement(const wchar_t* name, bool empty, | ||
67 | const wchar_t* attr1Name, const wchar_t* attr1Value, | ||
68 | const wchar_t* attr2Name, const wchar_t* attr2Value, | ||
69 | const wchar_t* attr3Name, const wchar_t* attr3Value, | ||
70 | const wchar_t* attr4Name, const wchar_t* attr4Value, | ||
71 | const wchar_t* attr5Name, const wchar_t* attr5Value) | ||
72 | { | ||
73 | if (!File || !name) | ||
74 | return; | ||
75 | |||
76 | if (Tabs > 0) | ||
77 | { | ||
78 | for (int i=0; i<Tabs; ++i) | ||
79 | File->write(L"\t", sizeof(wchar_t)); | ||
80 | } | ||
81 | |||
82 | // write name | ||
83 | |||
84 | File->write(L"<", sizeof(wchar_t)); | ||
85 | File->write(name, wcslen(name)*sizeof(wchar_t)); | ||
86 | |||
87 | // write attributes | ||
88 | |||
89 | writeAttribute(attr1Name, attr1Value); | ||
90 | writeAttribute(attr2Name, attr2Value); | ||
91 | writeAttribute(attr3Name, attr3Value); | ||
92 | writeAttribute(attr4Name, attr4Value); | ||
93 | writeAttribute(attr5Name, attr5Value); | ||
94 | |||
95 | // write closing tag | ||
96 | if (empty) | ||
97 | File->write(L" />", 3*sizeof(wchar_t)); | ||
98 | else | ||
99 | { | ||
100 | File->write(L">", sizeof(wchar_t)); | ||
101 | ++Tabs; | ||
102 | } | ||
103 | |||
104 | TextWrittenLast = false; | ||
105 | } | ||
106 | |||
107 | //! Writes an xml element with any number of attributes | ||
108 | void CXMLWriter::writeElement(const wchar_t* name, bool empty, | ||
109 | core::array<core::stringw> &names, | ||
110 | core::array<core::stringw> &values) | ||
111 | { | ||
112 | if (!File || !name) | ||
113 | return; | ||
114 | |||
115 | if (Tabs > 0) | ||
116 | { | ||
117 | for (int i=0; i<Tabs; ++i) | ||
118 | File->write(L"\t", sizeof(wchar_t)); | ||
119 | } | ||
120 | |||
121 | // write name | ||
122 | |||
123 | File->write(L"<", sizeof(wchar_t)); | ||
124 | File->write(name, wcslen(name)*sizeof(wchar_t)); | ||
125 | |||
126 | // write attributes | ||
127 | u32 i=0; | ||
128 | for (; i < names.size() && i < values.size(); ++i) | ||
129 | writeAttribute(names[i].c_str(), values[i].c_str()); | ||
130 | |||
131 | // write closing tag | ||
132 | if (empty) | ||
133 | File->write(L" />", 3*sizeof(wchar_t)); | ||
134 | else | ||
135 | { | ||
136 | File->write(L">", sizeof(wchar_t)); | ||
137 | ++Tabs; | ||
138 | } | ||
139 | |||
140 | TextWrittenLast = false; | ||
141 | } | ||
142 | |||
143 | |||
144 | void CXMLWriter::writeAttribute(const wchar_t* name, const wchar_t* value) | ||
145 | { | ||
146 | if (!name || !value) | ||
147 | return; | ||
148 | |||
149 | File->write(L" ", sizeof(wchar_t)); | ||
150 | File->write(name, wcslen(name)*sizeof(wchar_t)); | ||
151 | File->write(L"=\"", 2*sizeof(wchar_t)); | ||
152 | writeText(value); | ||
153 | File->write(L"\"", sizeof(wchar_t)); | ||
154 | } | ||
155 | |||
156 | |||
157 | //! Writes a comment into the xml file | ||
158 | void CXMLWriter::writeComment(const wchar_t* comment) | ||
159 | { | ||
160 | if (!File || !comment) | ||
161 | return; | ||
162 | |||
163 | File->write(L"<!--", 4*sizeof(wchar_t)); | ||
164 | writeText(comment); | ||
165 | File->write(L"-->", 3*sizeof(wchar_t)); | ||
166 | } | ||
167 | |||
168 | |||
169 | //! Writes the closing tag for an element. Like </foo> | ||
170 | void CXMLWriter::writeClosingTag(const wchar_t* name) | ||
171 | { | ||
172 | if (!File || !name) | ||
173 | return; | ||
174 | |||
175 | --Tabs; | ||
176 | |||
177 | if (Tabs > 0 && !TextWrittenLast) | ||
178 | { | ||
179 | for (int i=0; i<Tabs; ++i) | ||
180 | File->write(L"\t", sizeof(wchar_t)); | ||
181 | } | ||
182 | |||
183 | File->write(L"</", 2*sizeof(wchar_t)); | ||
184 | File->write(name, wcslen(name)*sizeof(wchar_t)); | ||
185 | File->write(L">", sizeof(wchar_t)); | ||
186 | TextWrittenLast = false; | ||
187 | } | ||
188 | |||
189 | |||
190 | |||
191 | const CXMLWriter::XMLSpecialCharacters XMLWSChar[] = | ||
192 | { | ||
193 | { L'&', L"&" }, | ||
194 | { L'<', L"<" }, | ||
195 | { L'>', L">" }, | ||
196 | { L'"', L""" }, | ||
197 | { L'\0', 0 } | ||
198 | }; | ||
199 | |||
200 | |||
201 | //! Writes a text into the file. All occurrences of special characters like | ||
202 | //! & (&), < (<), > (>), and " (") are automaticly replaced. | ||
203 | void CXMLWriter::writeText(const wchar_t* text) | ||
204 | { | ||
205 | if (!File || !text) | ||
206 | return; | ||
207 | |||
208 | // TODO: we have to get rid of that reserve call as well as it slows down xml-writing seriously. | ||
209 | // Making a member-variable would work, but a lot of memory would stay around after writing. | ||
210 | // So the correct solution is probably using fixed block here and always write when that is full. | ||
211 | core::stringw s; | ||
212 | s.reserve(wcslen(text)+1); | ||
213 | const wchar_t* p = text; | ||
214 | |||
215 | while(*p) | ||
216 | { | ||
217 | // check if it is matching | ||
218 | bool found = false; | ||
219 | for (s32 i=0; XMLWSChar[i].Character != '\0'; ++i) | ||
220 | if (*p == XMLWSChar[i].Character) | ||
221 | { | ||
222 | s.append(XMLWSChar[i].Symbol); | ||
223 | found = true; | ||
224 | break; | ||
225 | } | ||
226 | |||
227 | if (!found) | ||
228 | s.append(*p); | ||
229 | ++p; | ||
230 | } | ||
231 | |||
232 | // write new string | ||
233 | File->write(s.c_str(), s.size()*sizeof(wchar_t)); | ||
234 | TextWrittenLast = true; | ||
235 | } | ||
236 | |||
237 | |||
238 | //! Writes a line break | ||
239 | void CXMLWriter::writeLineBreak() | ||
240 | { | ||
241 | if (!File) | ||
242 | return; | ||
243 | |||
244 | #if defined(_IRR_OSX_PLATFORM_) | ||
245 | File->write(L"\r", sizeof(wchar_t)); | ||
246 | #elif defined(_IRR_WINDOWS_API_) | ||
247 | File->write(L"\r\n", 2*sizeof(wchar_t)); | ||
248 | #else | ||
249 | File->write(L"\n", sizeof(wchar_t)); | ||
250 | #endif | ||
251 | |||
252 | } | ||
253 | |||
254 | |||
255 | } // end namespace irr | ||
256 | } // end namespace io | ||
257 | |||