]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/include/boost/spirit/home/classic/tree/impl/tree_to_xml.ipp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / classic / tree / impl / tree_to_xml.ipp
1 /*=============================================================================
2 Copyright (c) 2001-2008 Hartmut Kaiser
3 Copyright (c) 2001-2003 Daniel Nuffer
4 http://spirit.sourceforge.net/
5
6 Use, modification and distribution is subject to the Boost Software
7 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8 http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
10
11 #if !defined(TREE_TO_XML_IPP)
12 #define TREE_TO_XML_IPP
13
14 #include <cstdio>
15 #include <cstdarg>
16 #include <locale>
17 #include <string>
18 #include <cstring>
19
20 #include <map>
21 #include <iostream>
22 #include <boost/config.hpp>
23 #include <boost/assert.hpp>
24 #include <boost/scoped_array.hpp>
25
26 #ifdef BOOST_NO_STRINGSTREAM
27 #include <strstream>
28 #define BOOST_SPIRIT_OSSTREAM std::ostrstream
29 inline
30 std::string BOOST_SPIRIT_GETSTRING(std::ostrstream& ss)
31 {
32 ss << std::ends;
33 std::string rval = ss.str();
34 ss.freeze(false);
35 return rval;
36 }
37 #else
38 #include <sstream>
39 #define BOOST_SPIRIT_GETSTRING(ss) ss.str()
40 #define BOOST_SPIRIT_OSSTREAM std::basic_ostringstream<CharT>
41 #endif
42
43 namespace boost { namespace spirit {
44
45 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
46
47 namespace impl {
48
49 ///////////////////////////////////////////////////////////////////////////
50 template <typename CharT>
51 struct string_lit;
52
53 template <>
54 struct string_lit<char>
55 {
56 static char get(char c) { return c; }
57 static std::string get(char const* str = "") { return str; }
58 };
59
60 template <>
61 struct string_lit<wchar_t>
62 {
63 static wchar_t get(char c)
64 {
65 typedef std::ctype<wchar_t> ctype_t;
66 return std::use_facet<ctype_t>(std::locale()).widen(c);
67 }
68 static std::basic_string<wchar_t> get(char const* source = "")
69 {
70 using namespace std; // some systems have size_t in ns std
71 size_t len = strlen(source);
72 boost::scoped_array<wchar_t> result (new wchar_t[len+1]);
73 result.get()[len] = '\0';
74
75 // working with wide character streams is supported only if the
76 // platform provides the std::ctype<wchar_t> facet
77 BOOST_ASSERT(std::has_facet<std::ctype<wchar_t> >(std::locale()));
78
79 std::use_facet<std::ctype<wchar_t> >(std::locale())
80 .widen(source, source + len, result.get());
81 return result.get();
82 }
83 };
84 }
85
86 // xml formatting helper classes
87 namespace xml {
88
89 template <typename CharT>
90 inline void
91 encode (std::basic_string<CharT> &str, char s, char const *r, int len)
92 {
93 typedef typename std::basic_string<CharT>::size_type size_type;
94
95 size_type pos = 0;
96 while ((pos = str.find_first_of (impl::string_lit<CharT>::get(s), pos)) !=
97 size_type(std::basic_string<CharT>::npos))
98 {
99 str.replace (pos, 1, impl::string_lit<CharT>::get(r));
100 pos += len;
101 }
102 }
103
104 template <typename CharT>
105 inline std::basic_string<CharT>
106 encode (std::basic_string<CharT> str)
107 {
108 encode(str, '&', "&amp;", 3);
109 encode(str, '<', "&lt;", 2);
110 encode(str, '>', "&gt;", 2);
111 encode(str, '\r', "\\r", 1);
112 encode(str, '\n', "\\n", 1);
113 return str;
114 }
115
116 template <typename CharT>
117 inline std::basic_string<CharT>
118 encode (CharT const *text)
119 {
120 return encode (std::basic_string<CharT>(text));
121 }
122
123 // format a xml attribute
124 template <typename CharT>
125 struct attribute
126 {
127 attribute()
128 {
129 }
130
131 attribute (std::basic_string<CharT> const& key_,
132 std::basic_string<CharT> const& value_)
133 : key (key_), value(value_)
134 {
135 }
136
137 bool has_value()
138 {
139 return value.size() > 0;
140 }
141
142 std::basic_string<CharT> key;
143 std::basic_string<CharT> value;
144 };
145
146 template <typename CharT>
147 inline std::basic_ostream<CharT>&
148 operator<< (std::basic_ostream<CharT> &ostrm, attribute<CharT> const &attr)
149 {
150 if (0 == attr.key.size())
151 return ostrm;
152 ostrm << impl::string_lit<CharT>::get(" ") << encode(attr.key)
153 << impl::string_lit<CharT>::get("=\"") << encode(attr.value)
154 << impl::string_lit<CharT>::get("\"");
155 return ostrm;
156 }
157
158 // output a xml element (base class, not used directly)
159 template <typename CharT>
160 class element
161 {
162 protected:
163 element(std::basic_ostream<CharT> &ostrm_, bool incr_indent_ = true)
164 : ostrm(ostrm_), incr_indent(incr_indent_)
165 {
166 if (incr_indent) ++get_indent();
167 }
168 ~element()
169 {
170 if (incr_indent) --get_indent();
171 }
172
173 public:
174 void output_space ()
175 {
176 for (int i = 0; i < get_indent(); i++)
177 ostrm << impl::string_lit<CharT>::get(" ");
178 }
179
180 protected:
181 int &get_indent()
182 {
183 static int indent;
184
185 return indent;
186 }
187
188 std::basic_ostream<CharT> &ostrm;
189 bool incr_indent;
190 };
191
192 // a xml node
193 template <typename CharT>
194 class node : public element<CharT>
195 {
196 public:
197 node (std::basic_ostream<CharT> &ostrm_,
198 std::basic_string<CharT> const& tag_, attribute<CharT> &attr)
199 : element<CharT>(ostrm_), tag(tag_)
200 {
201 this->output_space();
202 this->ostrm
203 << impl::string_lit<CharT>::get("<") << tag_ << attr
204 << impl::string_lit<CharT>::get(">\n");
205 }
206 node (std::basic_ostream<CharT> &ostrm_,
207 std::basic_string<CharT> const& tag_)
208 : element<CharT>(ostrm_), tag(tag_)
209 {
210 this->output_space();
211 this->ostrm
212 << impl::string_lit<CharT>::get("<") << tag_
213 << impl::string_lit<CharT>::get(">\n");
214 }
215 ~node()
216 {
217 this->output_space();
218 this->ostrm
219 << impl::string_lit<CharT>::get("</") << tag
220 << impl::string_lit<CharT>::get(">\n");
221 }
222
223 private:
224 std::basic_string<CharT> tag;
225 };
226
227 template <typename CharT>
228 class text : public element<CharT>
229 {
230 public:
231 text (std::basic_ostream<CharT> &ostrm_,
232 std::basic_string<CharT> const& tag,
233 std::basic_string<CharT> const& textlit)
234 : element<CharT>(ostrm_)
235 {
236 this->output_space();
237 this->ostrm
238 << impl::string_lit<CharT>::get("<") << tag
239 << impl::string_lit<CharT>::get(">") << encode(textlit)
240 << impl::string_lit<CharT>::get("</") << tag
241 << impl::string_lit<CharT>::get(">\n");
242 }
243
244 text (std::basic_ostream<CharT> &ostrm_,
245 std::basic_string<CharT> const& tag,
246 std::basic_string<CharT> const& textlit,
247 attribute<CharT> &attr)
248 : element<CharT>(ostrm_)
249 {
250 this->output_space();
251 this->ostrm
252 << impl::string_lit<CharT>::get("<") << tag << attr
253 << impl::string_lit<CharT>::get(">") << encode(textlit)
254 << impl::string_lit<CharT>::get("</") << tag
255 << impl::string_lit<CharT>::get(">\n");
256 }
257
258 text (std::basic_ostream<CharT> &ostrm_,
259 std::basic_string<CharT> const& tag,
260 std::basic_string<CharT> const& textlit,
261 attribute<CharT> &attr1, attribute<CharT> &attr2)
262 : element<CharT>(ostrm_)
263 {
264 this->output_space();
265 this->ostrm
266 << impl::string_lit<CharT>::get("<") << tag << attr1 << attr2
267 << impl::string_lit<CharT>::get(">") << encode(textlit)
268 << impl::string_lit<CharT>::get("</") << tag
269 << impl::string_lit<CharT>::get(">\n");
270 }
271 };
272
273 // a xml comment
274 template <typename CharT>
275 class comment : public element<CharT>
276 {
277 public:
278 comment (std::basic_ostream<CharT> &ostrm_,
279 std::basic_string<CharT> const& commentlit)
280 : element<CharT>(ostrm_, false)
281 {
282 if ('\0' != commentlit[0])
283 {
284 this->output_space();
285 this->ostrm << impl::string_lit<CharT>::get("<!-- ")
286 << encode(commentlit)
287 << impl::string_lit<CharT>::get(" -->\n");
288 }
289 }
290 };
291
292 // a xml document
293 template <typename CharT>
294 class document : public element<CharT>
295 {
296 public:
297 document (std::basic_ostream<CharT> &ostrm_)
298 : element<CharT>(ostrm_)
299 {
300 this->get_indent() = -1;
301 this->ostrm << impl::string_lit<CharT>::get(
302 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
303 }
304
305 document (std::basic_ostream<CharT> &ostrm_,
306 std::basic_string<CharT> const& mainnode,
307 std::basic_string<CharT> const& dtd)
308 : element<CharT>(ostrm_)
309 {
310 this->get_indent() = -1;
311 this->ostrm << impl::string_lit<CharT>::get(
312 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
313
314 this->output_space();
315 this->ostrm << impl::string_lit<CharT>::get("<!DOCTYPE ") << mainnode
316 << impl::string_lit<CharT>::get(" SYSTEM \"") << dtd
317 << impl::string_lit<CharT>::get("\">\n");
318 }
319 ~document()
320 {
321 BOOST_SPIRIT_ASSERT(-1 == this->get_indent());
322 }
323 };
324
325 } // end of namespace xml
326
327 namespace impl {
328
329 ///////////////////////////////////////////////////////////////////////////
330 // look up the rule name from the given parser_id
331 template <typename AssocContainerT>
332 inline typename AssocContainerT::value_type::second_type
333 get_rulename (AssocContainerT const &id_to_name_map,
334 BOOST_SPIRIT_CLASSIC_NS::parser_id const &id)
335 {
336 typename AssocContainerT::const_iterator it = id_to_name_map.find(id);
337 if (it != id_to_name_map.end())
338 return (*it).second;
339 typedef typename AssocContainerT::value_type::second_type second_t;
340 return second_t();
341 }
342
343 // dump a parse tree as xml
344 template <
345 typename CharT, typename IteratorT, typename GetIdT, typename GetValueT
346 >
347 inline void
348 token_to_xml (std::basic_ostream<CharT> &ostrm, IteratorT const &it,
349 bool is_root, GetIdT const &get_token_id, GetValueT const &get_token_value)
350 {
351 BOOST_SPIRIT_OSSTREAM stream;
352
353 stream << get_token_id(*it) << std::ends;
354 xml::attribute<CharT> token_id (
355 impl::string_lit<CharT>::get("id"),
356 BOOST_SPIRIT_GETSTRING(stream).c_str());
357 xml::attribute<CharT> is_root_attr (
358 impl::string_lit<CharT>::get("is_root"),
359 impl::string_lit<CharT>::get(is_root ? "1" : ""));
360 xml::attribute<CharT> nil;
361 xml::text<CharT>(ostrm,
362 impl::string_lit<CharT>::get("token"),
363 get_token_value(*it).c_str(),
364 token_id,
365 is_root_attr.has_value() ? is_root_attr : nil);
366 }
367
368 template <
369 typename CharT, typename TreeNodeT, typename AssocContainerT,
370 typename GetIdT, typename GetValueT
371 >
372 inline void
373 tree_node_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &node,
374 AssocContainerT const& id_to_name_map, GetIdT const &get_token_id,
375 GetValueT const &get_token_value)
376 {
377 typedef typename TreeNodeT::const_iterator node_iter_t;
378 typedef
379 typename TreeNodeT::value_type::parse_node_t::const_iterator_t
380 value_iter_t;
381
382 xml::attribute<CharT> nil;
383 node_iter_t end = node.end();
384 for (node_iter_t it = node.begin(); it != end; ++it)
385 {
386 // output a node
387 xml::attribute<CharT> id (
388 impl::string_lit<CharT>::get("rule"),
389 get_rulename(id_to_name_map, (*it).value.id()).c_str());
390 xml::node<CharT> currnode (ostrm,
391 impl::string_lit<CharT>::get("parsenode"),
392 (*it).value.id() != 0 && id.has_value() ? id : nil);
393
394 // first dump the value
395 std::size_t cnt = std::distance((*it).value.begin(), (*it).value.end());
396
397 if (1 == cnt)
398 {
399 token_to_xml (ostrm, (*it).value.begin(),
400 (*it).value.is_root(), get_token_id, get_token_value);
401 }
402 else if (cnt > 1)
403 {
404 xml::node<CharT> value (ostrm,
405 impl::string_lit<CharT>::get("value"));
406 bool is_root = (*it).value.is_root();
407
408 value_iter_t val_end = (*it).value.end();
409 for (value_iter_t val_it = (*it).value.begin();
410 val_it != val_end; ++val_it)
411 {
412 token_to_xml (ostrm, val_it, is_root, get_token_id,
413 get_token_value);
414 }
415 }
416 tree_node_to_xml(ostrm, (*it).children, id_to_name_map,
417 get_token_id, get_token_value); // dump all subnodes
418 }
419 }
420
421 template <typename CharT, typename TreeNodeT, typename AssocContainerT>
422 inline void
423 tree_node_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &node,
424 AssocContainerT const& id_to_name_map)
425 {
426 typedef typename TreeNodeT::const_iterator node_iter_t;
427
428 xml::attribute<CharT> nil;
429 node_iter_t end = node.end();
430 for (node_iter_t it = node.begin(); it != end; ++it)
431 {
432 // output a node
433 xml::attribute<CharT> id (
434 impl::string_lit<CharT>::get("rule"),
435 get_rulename(id_to_name_map, (*it).value.id()).c_str());
436 xml::node<CharT> currnode (ostrm,
437 impl::string_lit<CharT>::get("parsenode"),
438 (*it).value.id() != parser_id() && id.has_value() ? id : nil);
439
440 // first dump the value
441 if ((*it).value.begin() != (*it).value.end())
442 {
443 std::basic_string<CharT> tokens ((*it).value.begin(), (*it).value.end());
444
445 if (tokens.size() > 0)
446 {
447 // output all subtokens as one string (for better readability)
448 xml::attribute<CharT> is_root (
449 impl::string_lit<CharT>::get("is_root"),
450 impl::string_lit<CharT>::get((*it).value.is_root() ? "1" : ""));
451 xml::text<CharT>(ostrm,
452 impl::string_lit<CharT>::get("value"), tokens.c_str(),
453 is_root.has_value() ? is_root : nil);
454 }
455
456 }
457 // dump all subnodes
458 tree_node_to_xml(ostrm, (*it).children, id_to_name_map);
459 }
460 }
461
462 } // namespace impl
463
464 ///////////////////////////////////////////////////////////////////////////////
465 // dump a parse tree as a xml stream (generic variant)
466 template <
467 typename CharT, typename TreeNodeT, typename AssocContainerT,
468 typename GetIdT, typename GetValueT
469 >
470 inline void
471 basic_tree_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &tree,
472 std::basic_string<CharT> const &input_line, AssocContainerT const& id_to_name,
473 GetIdT const &get_token_id, GetValueT const &get_token_value)
474 {
475 // generate xml dump
476 xml::document<CharT> doc (ostrm,
477 impl::string_lit<CharT>::get("parsetree"),
478 impl::string_lit<CharT>::get("parsetree.dtd"));
479 xml::comment<CharT> input (ostrm, input_line.c_str());
480 xml::attribute<CharT> ver (
481 impl::string_lit<CharT>::get("version"),
482 impl::string_lit<CharT>::get("1.0"));
483 xml::node<CharT> mainnode (ostrm,
484 impl::string_lit<CharT>::get("parsetree"), ver);
485
486 impl::tree_node_to_xml (ostrm, tree, id_to_name, get_token_id,
487 get_token_value);
488 }
489
490 // dump a parse tree as a xml steam (for character based parsers)
491 template <typename CharT, typename TreeNodeT, typename AssocContainerT>
492 inline void
493 basic_tree_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &tree,
494 std::basic_string<CharT> const &input_line,
495 AssocContainerT const& id_to_name)
496 {
497 // generate xml dump
498 xml::document<CharT> doc (ostrm,
499 impl::string_lit<CharT>::get("parsetree"),
500 impl::string_lit<CharT>::get("parsetree.dtd"));
501 xml::comment<CharT> input (ostrm, input_line.c_str());
502 xml::attribute<CharT> ver (
503 impl::string_lit<CharT>::get("version"),
504 impl::string_lit<CharT>::get("1.0"));
505 xml::node<CharT> mainnode (ostrm,
506 impl::string_lit<CharT>::get("parsetree"), ver);
507
508 impl::tree_node_to_xml(ostrm, tree, id_to_name);
509 }
510
511 template <typename CharT, typename TreeNodeT>
512 inline void
513 basic_tree_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &tree,
514 std::basic_string<CharT> const &input_line)
515 {
516 return basic_tree_to_xml<CharT>(ostrm, tree, input_line,
517 std::map<BOOST_SPIRIT_CLASSIC_NS::parser_id, std::basic_string<CharT> >());
518 }
519
520 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
521
522 }} // namespace boost::spirit
523
524 #undef BOOST_SPIRIT_OSSTREAM
525 #undef BOOST_SPIRIT_GETSTRING
526
527 #endif // !defined(PARSE_TREE_XML_HPP)