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