cphot 0.1
A C++ tool for computing photometry from spectra.
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 $
7 //! \file rapidxml_print.hpp This file contains rapidxml printer implementation
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 
20  ///////////////////////////////////////////////////////////////////////
21  // Printing flags
22 
23  const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.
24 
25  ///////////////////////////////////////////////////////////////////////
26  // Internal
27 
28  //! \cond internal
29  namespace internal
30  {
31 
32  ///////////////////////////////////////////////////////////////////////////
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 
102  ///////////////////////////////////////////////////////////////////////////
103  // Internal printing operations
104 
105  // Print node
106  template<class OutIt, class Ch>
107  inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
108 
109  // Print children of the node
110  template<class OutIt, class Ch>
111  inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
112  {
113  for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
114  out = print_node(out, child, flags, indent);
115  return out;
116  }
117 
118  // Print attributes of the node
119  template<class OutIt, class Ch>
120  inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
121  {
122  for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
123  {
124  if (attribute->name() && attribute->value())
125  {
126  // Print attribute name
127  *out = Ch(' '), ++out;
128  out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
129  *out = Ch('='), ++out;
130  // Print attribute value using appropriate quote type
131  if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
132  {
133  *out = Ch('\''), ++out;
134  out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
135  *out = Ch('\''), ++out;
136  }
137  else
138  {
139  *out = Ch('"'), ++out;
140  out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
141  *out = Ch('"'), ++out;
142  }
143  }
144  }
145  return out;
146  }
147 
148  // Print data node
149  template<class OutIt, class Ch>
150  inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
151  {
152  assert(node->type() == node_data);
153  if (!(flags & print_no_indenting))
154  out = fill_chars(out, indent, Ch('\t'));
155  out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
156  return out;
157  }
158 
159  // Print data node
160  template<class OutIt, class Ch>
161  inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
162  {
163  assert(node->type() == node_cdata);
164  if (!(flags & print_no_indenting))
165  out = fill_chars(out, indent, Ch('\t'));
166  *out = Ch('<'); ++out;
167  *out = Ch('!'); ++out;
168  *out = Ch('['); ++out;
169  *out = Ch('C'); ++out;
170  *out = Ch('D'); ++out;
171  *out = Ch('A'); ++out;
172  *out = Ch('T'); ++out;
173  *out = Ch('A'); ++out;
174  *out = Ch('['); ++out;
175  out = copy_chars(node->value(), node->value() + node->value_size(), out);
176  *out = Ch(']'); ++out;
177  *out = Ch(']'); ++out;
178  *out = Ch('>'); ++out;
179  return out;
180  }
181 
182  // Print element node
183  template<class OutIt, class Ch>
184  inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
185  {
186  assert(node->type() == node_element);
187 
188  // Print element name and attributes, if any
189  if (!(flags & print_no_indenting))
190  out = fill_chars(out, indent, Ch('\t'));
191  *out = Ch('<'), ++out;
192  out = copy_chars(node->name(), node->name() + node->name_size(), out);
193  out = print_attributes(out, node, flags);
194 
195  // If node is childless
196  if (node->value_size() == 0 && !node->first_node())
197  {
198  // Print childless node tag ending
199  *out = Ch('/'), ++out;
200  *out = Ch('>'), ++out;
201  }
202  else
203  {
204  // Print normal node tag ending
205  *out = Ch('>'), ++out;
206 
207  // Test if node contains a single data node only (and no other nodes)
208  xml_node<Ch> *child = node->first_node();
209  if (!child)
210  {
211  // If node has no children, only print its value without indenting
212  out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
213  }
214  else if (child->next_sibling() == 0 && child->type() == node_data)
215  {
216  // If node has a sole data child, only print its value without indenting
217  out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
218  }
219  else
220  {
221  // Print all children with full indenting
222  if (!(flags & print_no_indenting))
223  *out = Ch('\n'), ++out;
224  out = print_children(out, node, flags, indent + 1);
225  if (!(flags & print_no_indenting))
226  out = fill_chars(out, indent, Ch('\t'));
227  }
228 
229  // Print node end
230  *out = Ch('<'), ++out;
231  *out = Ch('/'), ++out;
232  out = copy_chars(node->name(), node->name() + node->name_size(), out);
233  *out = Ch('>'), ++out;
234  }
235  return out;
236  }
237 
238  // Print declaration node
239  template<class OutIt, class Ch>
240  inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
241  {
242  // Print declaration start
243  if (!(flags & print_no_indenting))
244  out = fill_chars(out, indent, Ch('\t'));
245  *out = Ch('<'), ++out;
246  *out = Ch('?'), ++out;
247  *out = Ch('x'), ++out;
248  *out = Ch('m'), ++out;
249  *out = Ch('l'), ++out;
250 
251  // Print attributes
252  out = print_attributes(out, node, flags);
253 
254  // Print declaration end
255  *out = Ch('?'), ++out;
256  *out = Ch('>'), ++out;
257 
258  return out;
259  }
260 
261  // Print comment node
262  template<class OutIt, class Ch>
263  inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
264  {
265  assert(node->type() == node_comment);
266  if (!(flags & print_no_indenting))
267  out = fill_chars(out, indent, Ch('\t'));
268  *out = Ch('<'), ++out;
269  *out = Ch('!'), ++out;
270  *out = Ch('-'), ++out;
271  *out = Ch('-'), ++out;
272  out = copy_chars(node->value(), node->value() + node->value_size(), out);
273  *out = Ch('-'), ++out;
274  *out = Ch('-'), ++out;
275  *out = Ch('>'), ++out;
276  return out;
277  }
278 
279  // Print doctype node
280  template<class OutIt, class Ch>
281  inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
282  {
283  assert(node->type() == node_doctype);
284  if (!(flags & print_no_indenting))
285  out = fill_chars(out, indent, Ch('\t'));
286  *out = Ch('<'), ++out;
287  *out = Ch('!'), ++out;
288  *out = Ch('D'), ++out;
289  *out = Ch('O'), ++out;
290  *out = Ch('C'), ++out;
291  *out = Ch('T'), ++out;
292  *out = Ch('Y'), ++out;
293  *out = Ch('P'), ++out;
294  *out = Ch('E'), ++out;
295  *out = Ch(' '), ++out;
296  out = copy_chars(node->value(), node->value() + node->value_size(), out);
297  *out = Ch('>'), ++out;
298  return out;
299  }
300 
301  // Print pi node
302  template<class OutIt, class Ch>
303  inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
304  {
305  assert(node->type() == node_pi);
306  if (!(flags & print_no_indenting))
307  out = fill_chars(out, indent, Ch('\t'));
308  *out = Ch('<'), ++out;
309  *out = Ch('?'), ++out;
310  out = copy_chars(node->name(), node->name() + node->name_size(), out);
311  *out = Ch(' '), ++out;
312  out = copy_chars(node->value(), node->value() + node->value_size(), out);
313  *out = Ch('?'), ++out;
314  *out = Ch('>'), ++out;
315  return out;
316  }
317 
318  // Print node
319  template<class OutIt, class Ch>
320  inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
321  {
322  // Print proper node type
323  switch (node->type())
324  {
325 
326  // Document
327  case node_document:
328  out = print_children(out, node, flags, indent);
329  break;
330 
331  // Element
332  case node_element:
333  out = print_element_node(out, node, flags, indent);
334  break;
335 
336  // Data
337  case node_data:
338  out = print_data_node(out, node, flags, indent);
339  break;
340 
341  // CDATA
342  case node_cdata:
343  out = print_cdata_node(out, node, flags, indent);
344  break;
345 
346  // Declaration
347  case node_declaration:
348  out = print_declaration_node(out, node, flags, indent);
349  break;
350 
351  // Comment
352  case node_comment:
353  out = print_comment_node(out, node, flags, indent);
354  break;
355 
356  // Doctype
357  case node_doctype:
358  out = print_doctype_node(out, node, flags, indent);
359  break;
360 
361  // Pi
362  case node_pi:
363  out = print_pi_node(out, node, flags, indent);
364  break;
365 
366  // Unknown
367  default:
368  assert(0);
369  break;
370  }
371 
372  // If indenting not disabled, add line break after node
373  if (!(flags & print_no_indenting))
374  *out = Ch('\n'), ++out;
375 
376  // Return modified iterator
377  return out;
378  }
379 
380  }
381  //! \endcond
382 
383  ///////////////////////////////////////////////////////////////////////////
384  // Printing
385 
386  //! Prints XML to given output iterator.
387  //! \param out Output iterator to print to.
388  //! \param node Node to be printed. Pass xml_document to print entire document.
389  //! \param flags Flags controlling how XML is printed.
390  //! \return Output iterator pointing to position immediately after last character of printed text.
391  template<class OutIt, class Ch>
392  inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
393  {
394  return internal::print_node(out, &node, flags, 0);
395  }
396 
397 #ifndef RAPIDXML_NO_STREAMS
398 
399  //! Prints XML to given output stream.
400  //! \param out Output stream to print to.
401  //! \param node Node to be printed. Pass xml_document to print entire document.
402  //! \param flags Flags controlling how XML is printed.
403  //! \return Output stream.
404  template<class Ch>
405  inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
406  {
407  print(std::ostream_iterator<Ch>(out), node, flags);
408  return out;
409  }
410 
411  //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.
412  //! \param out Output stream to print to.
413  //! \param node Node to be printed.
414  //! \return Output stream.
415  template<class Ch>
416  inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
417  {
418  return print(out, node);
419  }
420 
421 #endif
422 
423 }
424 
425 #endif
rapidxml::print_no_indenting
const int print_no_indenting
Printer flag instructing the printer to suppress indenting of XML.
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:392
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:416
rapidxml::node_document
@ node_document
A document node.
Definition: rapidxml.hpp:148
rapidxml::node_element
@ node_element
An element node.
Definition: rapidxml.hpp:149
rapidxml::xml_attribute
Class representing attribute node of XML document.
Definition: rapidxml.hpp:141
rapidxml::node_pi
@ node_pi
A PI node.
Definition: rapidxml.hpp:155
rapidxml
Definition: rapidxml.hpp:59
rapidxml::xml_node::type
node_type type() const
Gets type of node.
Definition: rapidxml.hpp:999
rapidxml::xml_node::first_node
xml_node< Ch > * first_node(const Ch *name=0, const Ch *xmlns=0, std::size_t name_size=0, std::size_t xmlns_size=0, bool case_sensitive=true) const
Gets first child node, optionally matching node name.
Definition: rapidxml.hpp:1115
rapidxml::node_comment
@ node_comment
A comment node.
Definition: rapidxml.hpp:152
rapidxml::node_data
@ node_data
A data node.
Definition: rapidxml.hpp:150
rapidxml::xml_node
Class representing a node of XML document.
Definition: rapidxml.hpp:140
rapidxml::node_doctype
@ node_doctype
A DOCTYPE node.
Definition: rapidxml.hpp:154
rapidxml::node_declaration
@ node_declaration
A declaration node.
Definition: rapidxml.hpp:153
internal
Definition: document.h:391
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:1208
rapidxml::node_cdata
@ node_cdata
A CDATA node.
Definition: rapidxml.hpp:151
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:1187