Elaztek Developer Hub
Blamite Game Engine - Strings  00425.12.30.24.2120.blamite
A library containing general purpose utilities and classes for use in multiple projects.
rapidxml_print.hpp
Go to the documentation of this file.
1 #ifndef RAPIDXML_PRINT_HPP_INCLUDED
2 #define RAPIDXML_PRINT_HPP_INCLUDED
3 
4 // Copyright (C) 2006, 2009 Marcin Kalicinski
5 // Version 1.13
6 // Revision $DateTime: 2009/05/13 01:46:17 $
8 
9 #include "rapidxml.hpp"
10 
11 // Only include streams if not disabled
12 #ifndef RAPIDXML_NO_STREAMS
13  #include <ostream>
14  #include <iterator>
15 #endif
16 
17 namespace rapidxml
18 {
19 
21  // Printing flags
22 
23  const int print_no_indenting = 0x1;
24 
26  // Internal
27 
29  namespace internal
30  {
31 
33  // Internal character operations
34 
35  // Copy characters from given range to given output iterator
36  template<class OutIt, class Ch>
37  inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
38  {
39  while (begin != end)
40  *out++ = *begin++;
41  return out;
42  }
43 
44  // Copy characters from given range to given output iterator and expand
45  // characters into references (&lt; &gt; &apos; &quot; &amp;)
46  template<class OutIt, class Ch>
47  inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out)
48  {
49  while (begin != end)
50  {
51  if (*begin == noexpand)
52  {
53  *out++ = *begin; // No expansion, copy character
54  }
55  else
56  {
57  switch (*begin)
58  {
59  case Ch('<'):
60  *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
61  break;
62  case Ch('>'):
63  *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
64  break;
65  case Ch('\''):
66  *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
67  break;
68  case Ch('"'):
69  *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
70  break;
71  case Ch('&'):
72  *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';');
73  break;
74  default:
75  *out++ = *begin; // No expansion, copy character
76  }
77  }
78  ++begin; // Step to next character
79  }
80  return out;
81  }
82 
83  // Fill given output iterator with repetitions of the same character
84  template<class OutIt, class Ch>
85  inline OutIt fill_chars(OutIt out, int n, Ch ch)
86  {
87  for (int i = 0; i < n; ++i)
88  *out++ = ch;
89  return out;
90  }
91 
92  // Find character
93  template<class Ch, Ch ch>
94  inline bool find_char(const Ch *begin, const Ch *end)
95  {
96  while (begin != end)
97  if (*begin++ == ch)
98  return true;
99  return false;
100  }
101 
103  // Internal printing operations
104 
105  /* external compile fixes: https://stackoverflow.com/a/14114300 */
106  template<class OutIt, class Ch>
107  inline OutIt print_children(OutIt out, const xml_node<Ch>* node, int flags, int indent);
108 
109  template<class OutIt, class Ch>
110  inline OutIt print_attributes(OutIt out, const xml_node<Ch>* node, int flags);
111 
112  template<class OutIt, class Ch>
113  inline OutIt print_data_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);
114 
115  template<class OutIt, class Ch>
116  inline OutIt print_cdata_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);
117 
118  template<class OutIt, class Ch>
119  inline OutIt print_element_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);
120 
121  template<class OutIt, class Ch>
122  inline OutIt print_declaration_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);
123 
124  template<class OutIt, class Ch>
125  inline OutIt print_comment_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);
126 
127  template<class OutIt, class Ch>
128  inline OutIt print_doctype_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);
129 
130  template<class OutIt, class Ch>
131  inline OutIt print_pi_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);
132  /* end external compile fixes */
133 
134  // Print node
135  template<class OutIt, class Ch>
136  inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
137  {
138  // Print proper node type
139  switch (node->type())
140  {
141 
142  // Document
143  case node_document:
144  out = print_children(out, node, flags, indent);
145  break;
146 
147  // Element
148  case node_element:
149  out = print_element_node(out, node, flags, indent);
150  break;
151 
152  // Data
153  case node_data:
154  out = print_data_node(out, node, flags, indent);
155  break;
156 
157  // CDATA
158  case node_cdata:
159  out = print_cdata_node(out, node, flags, indent);
160  break;
161 
162  // Declaration
163  case node_declaration:
164  out = print_declaration_node(out, node, flags, indent);
165  break;
166 
167  // Comment
168  case node_comment:
169  out = print_comment_node(out, node, flags, indent);
170  break;
171 
172  // Doctype
173  case node_doctype:
174  out = print_doctype_node(out, node, flags, indent);
175  break;
176 
177  // Pi
178  case node_pi:
179  out = print_pi_node(out, node, flags, indent);
180  break;
181 
182  // Unknown
183  default:
184  assert(0);
185  break;
186  }
187 
188  // If indenting not disabled, add line break after node
189  if (!(flags & print_no_indenting))
190  *out = Ch('\n'), ++out;
191 
192  // Return modified iterator
193  return out;
194  }
195 
196  // Print children of the node
197  template<class OutIt, class Ch>
198  inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
199  {
200  for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
201  out = print_node(out, child, flags, indent);
202  return out;
203  }
204 
205  // Print attributes of the node
206  template<class OutIt, class Ch>
207  inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
208  {
209  for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
210  {
211  if (attribute->name() && attribute->value())
212  {
213  // Print attribute name
214  *out = Ch(' '), ++out;
215  out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
216  *out = Ch('='), ++out;
217  // Print attribute value using appropriate quote type
218  if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
219  {
220  *out = Ch('\''), ++out;
221  out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
222  *out = Ch('\''), ++out;
223  }
224  else
225  {
226  *out = Ch('"'), ++out;
227  out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
228  *out = Ch('"'), ++out;
229  }
230  }
231  }
232  return out;
233  }
234 
235  // Print data node
236  template<class OutIt, class Ch>
237  inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
238  {
239  assert(node->type() == node_data);
240  if (!(flags & print_no_indenting))
241  out = fill_chars(out, indent, Ch('\t'));
242  out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
243  return out;
244  }
245 
246  // Print data node
247  template<class OutIt, class Ch>
248  inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
249  {
250  assert(node->type() == node_cdata);
251  if (!(flags & print_no_indenting))
252  out = fill_chars(out, indent, Ch('\t'));
253  *out = Ch('<'); ++out;
254  *out = Ch('!'); ++out;
255  *out = Ch('['); ++out;
256  *out = Ch('C'); ++out;
257  *out = Ch('D'); ++out;
258  *out = Ch('A'); ++out;
259  *out = Ch('T'); ++out;
260  *out = Ch('A'); ++out;
261  *out = Ch('['); ++out;
262  out = copy_chars(node->value(), node->value() + node->value_size(), out);
263  *out = Ch(']'); ++out;
264  *out = Ch(']'); ++out;
265  *out = Ch('>'); ++out;
266  return out;
267  }
268 
269  // Print element node
270  template<class OutIt, class Ch>
271  inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
272  {
273  assert(node->type() == node_element);
274 
275  // Print element name and attributes, if any
276  if (!(flags & print_no_indenting))
277  out = fill_chars(out, indent, Ch('\t'));
278  *out = Ch('<'), ++out;
279  out = copy_chars(node->name(), node->name() + node->name_size(), out);
280  out = print_attributes(out, node, flags);
281 
282  // If node is childless
283  if (node->value_size() == 0 && !node->first_node())
284  {
285  // Print childless node tag ending
286  *out = Ch('/'), ++out;
287  *out = Ch('>'), ++out;
288  }
289  else
290  {
291  // Print normal node tag ending
292  *out = Ch('>'), ++out;
293 
294  // Test if node contains a single data node only (and no other nodes)
295  xml_node<Ch> *child = node->first_node();
296  if (!child)
297  {
298  // If node has no children, only print its value without indenting
299  out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
300  }
301  else if (child->next_sibling() == 0 && child->type() == node_data)
302  {
303  // If node has a sole data child, only print its value without indenting
304  out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
305  }
306  else
307  {
308  // Print all children with full indenting
309  if (!(flags & print_no_indenting))
310  *out = Ch('\n'), ++out;
311  out = print_children(out, node, flags, indent + 1);
312  if (!(flags & print_no_indenting))
313  out = fill_chars(out, indent, Ch('\t'));
314  }
315 
316  // Print node end
317  *out = Ch('<'), ++out;
318  *out = Ch('/'), ++out;
319  out = copy_chars(node->name(), node->name() + node->name_size(), out);
320  *out = Ch('>'), ++out;
321  }
322  return out;
323  }
324 
325  // Print declaration node
326  template<class OutIt, class Ch>
327  inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
328  {
329  // Print declaration start
330  if (!(flags & print_no_indenting))
331  out = fill_chars(out, indent, Ch('\t'));
332  *out = Ch('<'), ++out;
333  *out = Ch('?'), ++out;
334  *out = Ch('x'), ++out;
335  *out = Ch('m'), ++out;
336  *out = Ch('l'), ++out;
337 
338  // Print attributes
339  out = print_attributes(out, node, flags);
340 
341  // Print declaration end
342  *out = Ch('?'), ++out;
343  *out = Ch('>'), ++out;
344 
345  return out;
346  }
347 
348  // Print comment node
349  template<class OutIt, class Ch>
350  inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
351  {
352  assert(node->type() == node_comment);
353  if (!(flags & print_no_indenting))
354  out = fill_chars(out, indent, Ch('\t'));
355  *out = Ch('<'), ++out;
356  *out = Ch('!'), ++out;
357  *out = Ch('-'), ++out;
358  *out = Ch('-'), ++out;
359  out = copy_chars(node->value(), node->value() + node->value_size(), out);
360  *out = Ch('-'), ++out;
361  *out = Ch('-'), ++out;
362  *out = Ch('>'), ++out;
363  return out;
364  }
365 
366  // Print doctype node
367  template<class OutIt, class Ch>
368  inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
369  {
370  assert(node->type() == node_doctype);
371  if (!(flags & print_no_indenting))
372  out = fill_chars(out, indent, Ch('\t'));
373  *out = Ch('<'), ++out;
374  *out = Ch('!'), ++out;
375  *out = Ch('D'), ++out;
376  *out = Ch('O'), ++out;
377  *out = Ch('C'), ++out;
378  *out = Ch('T'), ++out;
379  *out = Ch('Y'), ++out;
380  *out = Ch('P'), ++out;
381  *out = Ch('E'), ++out;
382  *out = Ch(' '), ++out;
383  out = copy_chars(node->value(), node->value() + node->value_size(), out);
384  *out = Ch('>'), ++out;
385  return out;
386  }
387 
388  // Print pi node
389  template<class OutIt, class Ch>
390  inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
391  {
392  assert(node->type() == node_pi);
393  if (!(flags & print_no_indenting))
394  out = fill_chars(out, indent, Ch('\t'));
395  *out = Ch('<'), ++out;
396  *out = Ch('?'), ++out;
397  out = copy_chars(node->name(), node->name() + node->name_size(), out);
398  *out = Ch(' '), ++out;
399  out = copy_chars(node->value(), node->value() + node->value_size(), out);
400  *out = Ch('?'), ++out;
401  *out = Ch('>'), ++out;
402  return out;
403  }
404 
405  }
407 
409  // Printing
410 
416  template<class OutIt, class Ch>
417  inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
418  {
419  return internal::print_node(out, &node, flags, 0);
420  }
421 
422 #ifndef RAPIDXML_NO_STREAMS
423 
429  template<class Ch>
430  inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
431  {
432  print(std::ostream_iterator<Ch>(out), node, flags);
433  return out;
434  }
435 
440  template<class Ch>
441  inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
442  {
443  return print(out, node);
444  }
445 
446 #endif
447 
448 }
449 
450 #endif
rapidxml::print_no_indenting
const int print_no_indenting
Printer flag instructing the printer to suppress indenting of XML. See print() function.
Definition: rapidxml_print.hpp:23
rapidxml::print
OutIt print(OutIt out, const xml_node< Ch > &node, int flags=0)
Prints XML to given output iterator.
Definition: rapidxml_print.hpp:417
rapidxml::operator<<
std::basic_ostream< Ch > & operator<<(std::basic_ostream< Ch > &out, const xml_node< Ch > &node)
Prints formatted XML to given output stream.
Definition: rapidxml_print.hpp:441
rapidxml::node_document
@ node_document
A document node. Name and value are empty.
Definition: rapidxml.hpp:145
rapidxml::node_element
@ node_element
An element node. Name contains element name. Value contains text of first data node.
Definition: rapidxml.hpp:146
rapidxml::xml_attribute
Class representing attribute node of XML document.
Definition: rapidxml.hpp:138
rapidxml::node_pi
@ node_pi
A PI node. Name contains target. Value contains instructions.
Definition: rapidxml.hpp:152
rapidxml
Definition: rapidxml.hpp:57
rapidxml::xml_node::first_node
xml_node< Ch > * first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Gets first child node, optionally matching node name.
Definition: rapidxml.hpp:936
rapidxml::xml_node::type
node_type type() const
Gets type of node.
Definition: rapidxml.hpp:913
rapidxml::node_comment
@ node_comment
A comment node. Name is empty. Value contains comment text.
Definition: rapidxml.hpp:149
rapidxml::node_data
@ node_data
A data node. Name is empty. Value contains data text.
Definition: rapidxml.hpp:147
rapidxml::xml_node
Class representing a node of XML document.
Definition: rapidxml.hpp:137
rapidxml::node_doctype
@ node_doctype
A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
Definition: rapidxml.hpp:151
rapidxml::node_declaration
@ node_declaration
A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalon...
Definition: rapidxml.hpp:150
rapidxml.hpp
rapidxml::xml_node::first_attribute
xml_attribute< Ch > * first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Gets first attribute of node, optionally matching attribute name.
Definition: rapidxml.hpp:1025
rapidxml::node_cdata
@ node_cdata
A CDATA node. Name is empty. Value contains data text.
Definition: rapidxml.hpp:148
rapidxml::xml_node::next_sibling
xml_node< Ch > * next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Gets next sibling node, optionally matching node name.
Definition: rapidxml.hpp:1004