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