|
Boost-Commit : |
From: hartmut.kaiser_at_[hidden]
Date: 2007-11-29 09:24:00
Author: hkaiser
Date: 2007-11-29 09:24:00 EST (Thu, 29 Nov 2007)
New Revision: 41459
URL: http://svn.boost.org/trac/boost/changeset/41459
Log:
Fixing #1480 (Boost:::Spirit bug in tree_to_xml.ipp).
Added:
trunk/libs/spirit/test/tree_to_xml.cpp (contents, props changed)
Text files modified:
trunk/boost/spirit/tree/impl/tree_to_xml.ipp | 39 ++++++++++++++++++++++++---------------
trunk/libs/spirit/test/Jamfile.v2 | 1 +
2 files changed, 25 insertions(+), 15 deletions(-)
Modified: trunk/boost/spirit/tree/impl/tree_to_xml.ipp
==============================================================================
--- trunk/boost/spirit/tree/impl/tree_to_xml.ipp (original)
+++ trunk/boost/spirit/tree/impl/tree_to_xml.ipp 2007-11-29 09:24:00 EST (Thu, 29 Nov 2007)
@@ -65,6 +65,7 @@
using namespace std; // some systems have size_t in ns std
size_t len = strlen(source);
std::auto_ptr<wchar_t> result (new wchar_t[len+1]);
+ result.get()[len] = '\0';
std::use_facet<ctype_t>(std::locale())
.widen(source, source + len, result.get());
@@ -118,8 +119,9 @@
{
}
- attribute (CharT const *key_, CharT const *value_) :
- key (key_), value(value_)
+ attribute (std::basic_string<CharT> const& key_,
+ std::basic_string<CharT> const& value_)
+ : key (key_), value(value_)
{
}
@@ -183,8 +185,8 @@
class node : public element<CharT>
{
public:
- node (std::basic_ostream<CharT> &ostrm_, CharT const *tag_,
- attribute<CharT> &attr)
+ node (std::basic_ostream<CharT> &ostrm_,
+ std::basic_string<CharT> const& tag_, attribute<CharT> &attr)
: element<CharT>(ostrm_), tag(tag_)
{
this->output_space();
@@ -192,7 +194,8 @@
<< impl::string_lit<CharT>::get("<") << tag_ << attr
<< impl::string_lit<CharT>::get(">\n");
}
- node (std::basic_ostream<CharT> &ostrm_, CharT const *tag_)
+ node (std::basic_ostream<CharT> &ostrm_,
+ std::basic_string<CharT> const& tag_)
: element<CharT>(ostrm_), tag(tag_)
{
this->output_space();
@@ -216,8 +219,9 @@
class text : public element<CharT>
{
public:
- text (std::basic_ostream<CharT> &ostrm_, CharT const *tag,
- CharT const *textlit)
+ text (std::basic_ostream<CharT> &ostrm_,
+ std::basic_string<CharT> const& tag,
+ std::basic_string<CharT> const& textlit)
: element<CharT>(ostrm_)
{
this->output_space();
@@ -228,8 +232,10 @@
<< impl::string_lit<CharT>::get(">\n");
}
- text (std::basic_ostream<CharT> &ostrm_, CharT const *tag,
- CharT const *textlit, attribute<CharT> &attr)
+ text (std::basic_ostream<CharT> &ostrm_,
+ std::basic_string<CharT> const& tag,
+ std::basic_string<CharT> const& textlit,
+ attribute<CharT> &attr)
: element<CharT>(ostrm_)
{
this->output_space();
@@ -240,9 +246,10 @@
<< impl::string_lit<CharT>::get(">\n");
}
- text (std::basic_ostream<CharT> &ostrm_, CharT const *tag,
- CharT const *textlit, attribute<CharT> &attr1,
- attribute<CharT> &attr2)
+ text (std::basic_ostream<CharT> &ostrm_,
+ std::basic_string<CharT> const& tag,
+ std::basic_string<CharT> const& textlit,
+ attribute<CharT> &attr1, attribute<CharT> &attr2)
: element<CharT>(ostrm_)
{
this->output_space();
@@ -259,7 +266,8 @@
class comment : public element<CharT>
{
public:
- comment (std::basic_ostream<CharT> &ostrm_, CharT const *commentlit)
+ comment (std::basic_ostream<CharT> &ostrm_,
+ std::basic_string<CharT> const& commentlit)
: element<CharT>(ostrm_, false)
{
if ('\0' != commentlit[0])
@@ -285,8 +293,9 @@
"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
}
- document (std::basic_ostream<CharT> &ostrm_, CharT const *mainnode,
- CharT const *dtd)
+ document (std::basic_ostream<CharT> &ostrm_,
+ std::basic_string<CharT> const& mainnode,
+ std::basic_string<CharT> const& dtd)
: element<CharT>(ostrm_)
{
this->get_indent() = -1;
Modified: trunk/libs/spirit/test/Jamfile.v2
==============================================================================
--- trunk/libs/spirit/test/Jamfile.v2 (original)
+++ trunk/libs/spirit/test/Jamfile.v2 2007-11-29 09:24:00 EST (Thu, 29 Nov 2007)
@@ -104,6 +104,7 @@
: [ spirit-run ast_calc_tests.cpp ]
[ spirit-run group_match_bug.cpp ]
[ spirit-run repeat_ast_tests.cpp ]
+ [ spirit-run tree_to_xml.cpp ]
[ compile mix_and_match_trees.cpp ]
;
Added: trunk/libs/spirit/test/tree_to_xml.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/tree_to_xml.cpp 2007-11-29 09:24:00 EST (Thu, 29 Nov 2007)
@@ -0,0 +1,179 @@
+/*=============================================================================
+ Copyright (c) 2001-2007 Hartmut Kaiser
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/spirit/core.hpp>
+#include <boost/spirit/tree/ast.hpp>
+#include <boost/spirit/tree/tree_to_xml.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+using namespace boost::spirit;
+
+///////////////////////////////////////////////////////////////////////////////
+struct calculator : public grammar<calculator>
+{
+ static const int integerID = 1;
+ static const int factorID = 2;
+ static const int termID = 3;
+ static const int expressionID = 4;
+
+ template <typename ScannerT>
+ struct definition
+ {
+ definition(calculator const& /*self*/)
+ {
+ // Start grammar definition
+ integer = leaf_node_d[ lexeme_d[
+ (!ch_p('-') >> +digit_p)
+ ] ];
+
+ factor = integer
+ | inner_node_d[ch_p('(') >> expression >> ch_p(')')]
+ | (root_node_d[ch_p('-')] >> factor);
+
+ term = factor >>
+ *( (root_node_d[ch_p('*')] >> factor)
+ | (root_node_d[ch_p('/')] >> factor)
+ );
+
+ expression = term >>
+ *( (root_node_d[ch_p('+')] >> term)
+ | (root_node_d[ch_p('-')] >> term)
+ );
+ // End grammar definition
+
+ // turn on the debugging info.
+ BOOST_SPIRIT_DEBUG_RULE(integer);
+ BOOST_SPIRIT_DEBUG_RULE(factor);
+ BOOST_SPIRIT_DEBUG_RULE(term);
+ BOOST_SPIRIT_DEBUG_RULE(expression);
+ }
+
+ rule<ScannerT, parser_context<>, parser_tag<expressionID> > expression;
+ rule<ScannerT, parser_context<>, parser_tag<termID> > term;
+ rule<ScannerT, parser_context<>, parser_tag<factorID> > factor;
+ rule<ScannerT, parser_context<>, parser_tag<integerID> > integer;
+
+ rule<ScannerT, parser_context<>, parser_tag<expressionID> > const&
+ start() const { return expression; }
+ };
+};
+
+///////////////////////////////////////////////////////////////////////////////
+/// this is a Boost.IoStreams source device usable to create a istream on
+/// top of a random access container (i.e. vector<>)
+template<typename Container>
+class container_device
+{
+public:
+ typedef typename Container::value_type char_type;
+ typedef boost::iostreams::sink_tag category;
+
+ container_device(Container& container)
+ : container_(container), pos_(0)
+ {}
+
+ /// Write up to n characters to the underlying data sink into the
+ /// buffer s, returning the number of characters written
+ std::streamsize write(const char_type* s, std::streamsize n)
+ {
+ std::streamsize result = 0;
+ if (pos_ != container_.size()) {
+ std::streamsize amt =
+ static_cast<std::streamsize>(container_.size() - pos_);
+ std::streamsize result = (std::min)(n, amt);
+ std::copy(s, s + result, container_.begin() + pos_);
+ pos_ += result;
+ }
+ if (result < n) {
+ container_.insert(container_.end(), s, s + n);
+ pos_ = container_.size();
+ }
+ return n;
+ }
+
+ Container& container() { return container_; }
+
+private:
+ typedef typename Container::size_type size_type;
+ Container& container_;
+ size_type pos_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+#define EXPECTED_XML_OUTPUT "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n\
+<!DOCTYPE parsetree SYSTEM \"parsetree.dtd\">\n\
+<!-- 1+2 -->\n\
+<parsetree version=\"1.0\">\n\
+ <parsenode>\n\
+ <value>+</value>\n\
+ <parsenode>\n\
+ <value>1</value>\n\
+ </parsenode>\n\
+ <parsenode>\n\
+ <value>2</value>\n\
+ </parsenode>\n\
+ </parsenode>\n\
+</parsetree>\n"
+
+#define EXPECTED_XML_OUTPUT_WIDE BOOST_PP_CAT(L, EXPECTED_XML_OUTPUT)
+
+bool test(wchar_t const *text)
+{
+ typedef std::wstring::iterator iterator_t;
+ typedef tree_match<iterator_t> parse_tree_match_t;
+ typedef parse_tree_match_t::tree_iterator iter_t;
+
+ std::wstring input(text);
+ calculator calc;
+ tree_parse_info<iterator_t> ast_info =
+ ast_parse(iterator_t(input.begin()), iterator_t(input.end()),
+ calc >> end_p, space_p);
+
+ std::wstring out;
+ {
+ typedef container_device<std::wstring> device_type;
+ boost::iostreams::stream<device_type> outsink(out);
+ basic_tree_to_xml<wchar_t>(outsink, ast_info.trees, input);
+ }
+ return out == EXPECTED_XML_OUTPUT_WIDE;
+}
+
+bool test(char const *text)
+{
+ typedef std::string::iterator iterator_t;
+ typedef tree_match<iterator_t> parse_tree_match_t;
+ typedef parse_tree_match_t::tree_iterator iter_t;
+
+ std::string input(text);
+ calculator calc;
+ tree_parse_info<iterator_t> ast_info =
+ ast_parse(iterator_t(input.begin()), iterator_t(input.end()),
+ calc >> end_p, space_p);
+
+ std::string out;
+ {
+ typedef container_device<std::string> device_type;
+ boost::iostreams::stream<device_type> outsink(out);
+ basic_tree_to_xml<char>(outsink, ast_info.trees, input);
+ }
+ return out == EXPECTED_XML_OUTPUT;
+}
+
+int main()
+{
+ BOOST_TEST(test(L"1+2"));
+ BOOST_TEST(test("1+2"));
+ return boost::report_errors();
+}
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk