File indexing completed on 2025-01-31 10:02:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_SPIRIT_CLASSIC_TREE_IMPL_TREE_TO_XML_IPP
0012 #define BOOST_SPIRIT_CLASSIC_TREE_IMPL_TREE_TO_XML_IPP
0013
0014 #include <cstdio>
0015 #include <cstdarg>
0016 #include <locale>
0017 #include <string>
0018 #include <cstring>
0019
0020 #include <map>
0021 #include <iostream>
0022 #include <boost/config.hpp>
0023 #include <boost/assert.hpp>
0024 #include <boost/scoped_array.hpp>
0025
0026 #ifdef BOOST_NO_STRINGSTREAM
0027 #include <strstream>
0028 #define BOOST_SPIRIT_OSSTREAM std::ostrstream
0029 inline
0030 std::string BOOST_SPIRIT_GETSTRING(std::ostrstream& ss)
0031 {
0032 ss << std::ends;
0033 std::string rval = ss.str();
0034 ss.freeze(false);
0035 return rval;
0036 }
0037 #else
0038 #include <sstream>
0039 #define BOOST_SPIRIT_GETSTRING(ss) ss.str()
0040 #define BOOST_SPIRIT_OSSTREAM std::basic_ostringstream<CharT>
0041 #endif
0042
0043 namespace boost { namespace spirit {
0044
0045 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
0046
0047 namespace impl {
0048
0049
0050 template <typename CharT>
0051 struct string_lit;
0052
0053 template <>
0054 struct string_lit<char>
0055 {
0056 static char get(char c) { return c; }
0057 static std::string get(char const* str = "") { return str; }
0058 };
0059
0060 template <>
0061 struct string_lit<wchar_t>
0062 {
0063 static wchar_t get(char c)
0064 {
0065 typedef std::ctype<wchar_t> ctype_t;
0066 return std::use_facet<ctype_t>(std::locale()).widen(c);
0067 }
0068 static std::basic_string<wchar_t> get(char const* source = "")
0069 {
0070 using namespace std;
0071 size_t len = strlen(source);
0072 boost::scoped_array<wchar_t> result (new wchar_t[len+1]);
0073 result.get()[len] = '\0';
0074
0075
0076
0077 BOOST_ASSERT(std::has_facet<std::ctype<wchar_t> >(std::locale()));
0078
0079 std::use_facet<std::ctype<wchar_t> >(std::locale())
0080 .widen(source, source + len, result.get());
0081 return result.get();
0082 }
0083 };
0084 }
0085
0086
0087 namespace xml {
0088
0089 template <typename CharT>
0090 inline void
0091 encode (std::basic_string<CharT> &str, char s, char const *r, int len)
0092 {
0093 typedef typename std::basic_string<CharT>::size_type size_type;
0094
0095 size_type pos = 0;
0096 while ((pos = str.find_first_of (impl::string_lit<CharT>::get(s), pos)) !=
0097 size_type(std::basic_string<CharT>::npos))
0098 {
0099 str.replace (pos, 1, impl::string_lit<CharT>::get(r));
0100 pos += len;
0101 }
0102 }
0103
0104 template <typename CharT>
0105 inline std::basic_string<CharT>
0106 encode (std::basic_string<CharT> str)
0107 {
0108 encode(str, '&', "&", 3);
0109 encode(str, '<', "<", 2);
0110 encode(str, '>', ">", 2);
0111 encode(str, '\r', "\\r", 1);
0112 encode(str, '\n', "\\n", 1);
0113 return str;
0114 }
0115
0116 template <typename CharT>
0117 inline std::basic_string<CharT>
0118 encode (CharT const *text)
0119 {
0120 return encode (std::basic_string<CharT>(text));
0121 }
0122
0123
0124 template <typename CharT>
0125 struct attribute
0126 {
0127 attribute()
0128 {
0129 }
0130
0131 attribute (std::basic_string<CharT> const& key_,
0132 std::basic_string<CharT> const& value_)
0133 : key (key_), value(value_)
0134 {
0135 }
0136
0137 bool has_value()
0138 {
0139 return value.size() > 0;
0140 }
0141
0142 std::basic_string<CharT> key;
0143 std::basic_string<CharT> value;
0144 };
0145
0146 template <typename CharT>
0147 inline std::basic_ostream<CharT>&
0148 operator<< (std::basic_ostream<CharT> &ostrm, attribute<CharT> const &attr)
0149 {
0150 if (0 == attr.key.size())
0151 return ostrm;
0152 ostrm << impl::string_lit<CharT>::get(" ") << encode(attr.key)
0153 << impl::string_lit<CharT>::get("=\"") << encode(attr.value)
0154 << impl::string_lit<CharT>::get("\"");
0155 return ostrm;
0156 }
0157
0158
0159 template <typename CharT>
0160 class element
0161 {
0162 protected:
0163 element(std::basic_ostream<CharT> &ostrm_, bool incr_indent_ = true)
0164 : ostrm(ostrm_), incr_indent(incr_indent_)
0165 {
0166 if (incr_indent) ++get_indent();
0167 }
0168 ~element()
0169 {
0170 if (incr_indent) --get_indent();
0171 }
0172
0173 public:
0174 void output_space ()
0175 {
0176 for (int i = 0; i < get_indent(); i++)
0177 ostrm << impl::string_lit<CharT>::get(" ");
0178 }
0179
0180 protected:
0181 int &get_indent()
0182 {
0183 static int indent;
0184
0185 return indent;
0186 }
0187
0188 std::basic_ostream<CharT> &ostrm;
0189 bool incr_indent;
0190 };
0191
0192
0193 template <typename CharT>
0194 class node : public element<CharT>
0195 {
0196 public:
0197 node (std::basic_ostream<CharT> &ostrm_,
0198 std::basic_string<CharT> const& tag_, attribute<CharT> &attr)
0199 : element<CharT>(ostrm_), tag(tag_)
0200 {
0201 this->output_space();
0202 this->ostrm
0203 << impl::string_lit<CharT>::get("<") << tag_ << attr
0204 << impl::string_lit<CharT>::get(">\n");
0205 }
0206 node (std::basic_ostream<CharT> &ostrm_,
0207 std::basic_string<CharT> const& tag_)
0208 : element<CharT>(ostrm_), tag(tag_)
0209 {
0210 this->output_space();
0211 this->ostrm
0212 << impl::string_lit<CharT>::get("<") << tag_
0213 << impl::string_lit<CharT>::get(">\n");
0214 }
0215 ~node()
0216 {
0217 this->output_space();
0218 this->ostrm
0219 << impl::string_lit<CharT>::get("</") << tag
0220 << impl::string_lit<CharT>::get(">\n");
0221 }
0222
0223 private:
0224 std::basic_string<CharT> tag;
0225 };
0226
0227 template <typename CharT>
0228 class text : public element<CharT>
0229 {
0230 public:
0231 text (std::basic_ostream<CharT> &ostrm_,
0232 std::basic_string<CharT> const& tag,
0233 std::basic_string<CharT> const& textlit)
0234 : element<CharT>(ostrm_)
0235 {
0236 this->output_space();
0237 this->ostrm
0238 << impl::string_lit<CharT>::get("<") << tag
0239 << impl::string_lit<CharT>::get(">") << encode(textlit)
0240 << impl::string_lit<CharT>::get("</") << tag
0241 << impl::string_lit<CharT>::get(">\n");
0242 }
0243
0244 text (std::basic_ostream<CharT> &ostrm_,
0245 std::basic_string<CharT> const& tag,
0246 std::basic_string<CharT> const& textlit,
0247 attribute<CharT> &attr)
0248 : element<CharT>(ostrm_)
0249 {
0250 this->output_space();
0251 this->ostrm
0252 << impl::string_lit<CharT>::get("<") << tag << attr
0253 << impl::string_lit<CharT>::get(">") << encode(textlit)
0254 << impl::string_lit<CharT>::get("</") << tag
0255 << impl::string_lit<CharT>::get(">\n");
0256 }
0257
0258 text (std::basic_ostream<CharT> &ostrm_,
0259 std::basic_string<CharT> const& tag,
0260 std::basic_string<CharT> const& textlit,
0261 attribute<CharT> &attr1, attribute<CharT> &attr2)
0262 : element<CharT>(ostrm_)
0263 {
0264 this->output_space();
0265 this->ostrm
0266 << impl::string_lit<CharT>::get("<") << tag << attr1 << attr2
0267 << impl::string_lit<CharT>::get(">") << encode(textlit)
0268 << impl::string_lit<CharT>::get("</") << tag
0269 << impl::string_lit<CharT>::get(">\n");
0270 }
0271 };
0272
0273
0274 template <typename CharT>
0275 class comment : public element<CharT>
0276 {
0277 public:
0278 comment (std::basic_ostream<CharT> &ostrm_,
0279 std::basic_string<CharT> const& commentlit)
0280 : element<CharT>(ostrm_, false)
0281 {
0282 if ('\0' != commentlit[0])
0283 {
0284 this->output_space();
0285 this->ostrm << impl::string_lit<CharT>::get("<!-- ")
0286 << encode(commentlit)
0287 << impl::string_lit<CharT>::get(" -->\n");
0288 }
0289 }
0290 };
0291
0292
0293 template <typename CharT>
0294 class document : public element<CharT>
0295 {
0296 public:
0297 document (std::basic_ostream<CharT> &ostrm_)
0298 : element<CharT>(ostrm_)
0299 {
0300 this->get_indent() = -1;
0301 this->ostrm << impl::string_lit<CharT>::get(
0302 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
0303 }
0304
0305 document (std::basic_ostream<CharT> &ostrm_,
0306 std::basic_string<CharT> const& mainnode,
0307 std::basic_string<CharT> const& dtd)
0308 : element<CharT>(ostrm_)
0309 {
0310 this->get_indent() = -1;
0311 this->ostrm << impl::string_lit<CharT>::get(
0312 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
0313
0314 this->output_space();
0315 this->ostrm << impl::string_lit<CharT>::get("<!DOCTYPE ") << mainnode
0316 << impl::string_lit<CharT>::get(" SYSTEM \"") << dtd
0317 << impl::string_lit<CharT>::get("\">\n");
0318 }
0319 ~document()
0320 {
0321 BOOST_SPIRIT_ASSERT(-1 == this->get_indent());
0322 }
0323 };
0324
0325 }
0326
0327 namespace impl {
0328
0329
0330
0331 template <typename AssocContainerT>
0332 inline typename AssocContainerT::value_type::second_type
0333 get_rulename (AssocContainerT const &id_to_name_map,
0334 BOOST_SPIRIT_CLASSIC_NS::parser_id const &id)
0335 {
0336 typename AssocContainerT::const_iterator it = id_to_name_map.find(id);
0337 if (it != id_to_name_map.end())
0338 return (*it).second;
0339 typedef typename AssocContainerT::value_type::second_type second_t;
0340 return second_t();
0341 }
0342
0343
0344 template <
0345 typename CharT, typename IteratorT, typename GetIdT, typename GetValueT
0346 >
0347 inline void
0348 token_to_xml (std::basic_ostream<CharT> &ostrm, IteratorT const &it,
0349 bool is_root, GetIdT const &get_token_id, GetValueT const &get_token_value)
0350 {
0351 BOOST_SPIRIT_OSSTREAM stream;
0352
0353 stream << get_token_id(*it) << std::ends;
0354 xml::attribute<CharT> token_id (
0355 impl::string_lit<CharT>::get("id"),
0356 BOOST_SPIRIT_GETSTRING(stream).c_str());
0357 xml::attribute<CharT> is_root_attr (
0358 impl::string_lit<CharT>::get("is_root"),
0359 impl::string_lit<CharT>::get(is_root ? "1" : ""));
0360 xml::attribute<CharT> nil;
0361 xml::text<CharT>(ostrm,
0362 impl::string_lit<CharT>::get("token"),
0363 get_token_value(*it).c_str(),
0364 token_id,
0365 is_root_attr.has_value() ? is_root_attr : nil);
0366 }
0367
0368 template <
0369 typename CharT, typename TreeNodeT, typename AssocContainerT,
0370 typename GetIdT, typename GetValueT
0371 >
0372 inline void
0373 tree_node_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &node,
0374 AssocContainerT const& id_to_name_map, GetIdT const &get_token_id,
0375 GetValueT const &get_token_value)
0376 {
0377 typedef typename TreeNodeT::const_iterator node_iter_t;
0378 typedef
0379 typename TreeNodeT::value_type::parse_node_t::const_iterator_t
0380 value_iter_t;
0381
0382 xml::attribute<CharT> nil;
0383 node_iter_t end = node.end();
0384 for (node_iter_t it = node.begin(); it != end; ++it)
0385 {
0386
0387 xml::attribute<CharT> id (
0388 impl::string_lit<CharT>::get("rule"),
0389 get_rulename(id_to_name_map, (*it).value.id()).c_str());
0390 xml::node<CharT> currnode (ostrm,
0391 impl::string_lit<CharT>::get("parsenode"),
0392 (*it).value.id() != 0 && id.has_value() ? id : nil);
0393
0394
0395 std::size_t cnt = std::distance((*it).value.begin(), (*it).value.end());
0396
0397 if (1 == cnt)
0398 {
0399 token_to_xml (ostrm, (*it).value.begin(),
0400 (*it).value.is_root(), get_token_id, get_token_value);
0401 }
0402 else if (cnt > 1)
0403 {
0404 xml::node<CharT> value (ostrm,
0405 impl::string_lit<CharT>::get("value"));
0406 bool is_root = (*it).value.is_root();
0407
0408 value_iter_t val_end = (*it).value.end();
0409 for (value_iter_t val_it = (*it).value.begin();
0410 val_it != val_end; ++val_it)
0411 {
0412 token_to_xml (ostrm, val_it, is_root, get_token_id,
0413 get_token_value);
0414 }
0415 }
0416 tree_node_to_xml(ostrm, (*it).children, id_to_name_map,
0417 get_token_id, get_token_value);
0418 }
0419 }
0420
0421 template <typename CharT, typename TreeNodeT, typename AssocContainerT>
0422 inline void
0423 tree_node_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &node,
0424 AssocContainerT const& id_to_name_map)
0425 {
0426 typedef typename TreeNodeT::const_iterator node_iter_t;
0427
0428 xml::attribute<CharT> nil;
0429 node_iter_t end = node.end();
0430 for (node_iter_t it = node.begin(); it != end; ++it)
0431 {
0432
0433 xml::attribute<CharT> id (
0434 impl::string_lit<CharT>::get("rule"),
0435 get_rulename(id_to_name_map, (*it).value.id()).c_str());
0436 xml::node<CharT> currnode (ostrm,
0437 impl::string_lit<CharT>::get("parsenode"),
0438 (*it).value.id() != parser_id() && id.has_value() ? id : nil);
0439
0440
0441 if ((*it).value.begin() != (*it).value.end())
0442 {
0443 std::basic_string<CharT> tokens ((*it).value.begin(), (*it).value.end());
0444
0445 if (tokens.size() > 0)
0446 {
0447
0448 xml::attribute<CharT> is_root (
0449 impl::string_lit<CharT>::get("is_root"),
0450 impl::string_lit<CharT>::get((*it).value.is_root() ? "1" : ""));
0451 xml::text<CharT>(ostrm,
0452 impl::string_lit<CharT>::get("value"), tokens.c_str(),
0453 is_root.has_value() ? is_root : nil);
0454 }
0455
0456 }
0457
0458 tree_node_to_xml(ostrm, (*it).children, id_to_name_map);
0459 }
0460 }
0461
0462 }
0463
0464
0465
0466 template <
0467 typename CharT, typename TreeNodeT, typename AssocContainerT,
0468 typename GetIdT, typename GetValueT
0469 >
0470 inline void
0471 basic_tree_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &tree,
0472 std::basic_string<CharT> const &input_line, AssocContainerT const& id_to_name,
0473 GetIdT const &get_token_id, GetValueT const &get_token_value)
0474 {
0475
0476 xml::document<CharT> doc (ostrm,
0477 impl::string_lit<CharT>::get("parsetree"),
0478 impl::string_lit<CharT>::get("parsetree.dtd"));
0479 xml::comment<CharT> input (ostrm, input_line.c_str());
0480 xml::attribute<CharT> ver (
0481 impl::string_lit<CharT>::get("version"),
0482 impl::string_lit<CharT>::get("1.0"));
0483 xml::node<CharT> mainnode (ostrm,
0484 impl::string_lit<CharT>::get("parsetree"), ver);
0485
0486 impl::tree_node_to_xml (ostrm, tree, id_to_name, get_token_id,
0487 get_token_value);
0488 }
0489
0490
0491 template <typename CharT, typename TreeNodeT, typename AssocContainerT>
0492 inline void
0493 basic_tree_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &tree,
0494 std::basic_string<CharT> const &input_line,
0495 AssocContainerT const& id_to_name)
0496 {
0497
0498 xml::document<CharT> doc (ostrm,
0499 impl::string_lit<CharT>::get("parsetree"),
0500 impl::string_lit<CharT>::get("parsetree.dtd"));
0501 xml::comment<CharT> input (ostrm, input_line.c_str());
0502 xml::attribute<CharT> ver (
0503 impl::string_lit<CharT>::get("version"),
0504 impl::string_lit<CharT>::get("1.0"));
0505 xml::node<CharT> mainnode (ostrm,
0506 impl::string_lit<CharT>::get("parsetree"), ver);
0507
0508 impl::tree_node_to_xml(ostrm, tree, id_to_name);
0509 }
0510
0511 template <typename CharT, typename TreeNodeT>
0512 inline void
0513 basic_tree_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &tree,
0514 std::basic_string<CharT> const &input_line)
0515 {
0516 return basic_tree_to_xml<CharT>(ostrm, tree, input_line,
0517 std::map<BOOST_SPIRIT_CLASSIC_NS::parser_id, std::basic_string<CharT> >());
0518 }
0519
0520 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
0521
0522 }}
0523
0524 #undef BOOST_SPIRIT_OSSTREAM
0525 #undef BOOST_SPIRIT_GETSTRING
0526
0527 #endif