$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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();
+}