Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r55871 - in sandbox/explore: boost/explore libs/explore/doc libs/explore/test
From: jeff_at_[hidden]
Date: 2009-08-29 21:41:47


Author: jefffaust
Date: 2009-08-29 21:41:46 EDT (Sat, 29 Aug 2009)
New Revision: 55871
URL: http://svn.boost.org/trac/boost/changeset/55871

Log:
Add custom() manipulator for containers with custom streaming.
Text files modified:
   sandbox/explore/boost/explore/container_stream_state.hpp | 11 ++++---
   sandbox/explore/boost/explore/manipulators.hpp | 45 +++++++++++++++++++++++++++---
   sandbox/explore/boost/explore/pair.hpp | 2
   sandbox/explore/boost/explore/stream_container.hpp | 2
   sandbox/explore/libs/explore/doc/custom_containers.qbk | 47 ++++++++++++++++++++++++-------
   sandbox/explore/libs/explore/test/user_defined_container.cpp | 59 +++++++++++++++++++++++++++++++++++++--
   6 files changed, 140 insertions(+), 26 deletions(-)

Modified: sandbox/explore/boost/explore/container_stream_state.hpp
==============================================================================
--- sandbox/explore/boost/explore/container_stream_state.hpp (original)
+++ sandbox/explore/boost/explore/container_stream_state.hpp 2009-08-29 21:41:46 EDT (Sat, 29 Aug 2009)
@@ -10,6 +10,7 @@
 #ifndef BOOST_EXPLORE_CONTAINER_STREAM_STATE_H
 #define BOOST_EXPLORE_CONTAINER_STREAM_STATE_H
 
+#include <cassert>
 #include <string>
 #include <vector>
 
@@ -84,12 +85,10 @@
         void set_itemwidth(std::size_t iw) { at(m_itemwidth) = iw; }
 
         void set_level(size_t l) { m_level = l; }
+ void level_up() { ++m_level; }
+ void level_down() { --m_level; }
 
- std::size_t depth() const
- {
- // we start at 0, increment before use, so we must decrement upon query.
- return m_depth - 1;
- }
+ std::size_t depth() const { return m_depth; }
 
     private:
         friend struct detail::depth_guard<Elem>;
@@ -125,6 +124,8 @@
         template<typename T>
         T& at(std::vector<T>& c)
         {
+ assert(m_depth <= m_level);
+
             if( c.size() <= m_level )
             {
                 c.resize(m_level+1);

Modified: sandbox/explore/boost/explore/manipulators.hpp
==============================================================================
--- sandbox/explore/boost/explore/manipulators.hpp (original)
+++ sandbox/explore/boost/explore/manipulators.hpp 2009-08-29 21:41:46 EDT (Sat, 29 Aug 2009)
@@ -52,7 +52,7 @@
             void (*pfun)(std::ios_base&, T);
             T arg;
         };
-
+
         // stream manipfunc
         template<typename Elem, typename Tr, typename T>
         std::basic_ostream<Elem, Tr>& operator<<(std::basic_ostream<Elem, Tr>& ostr, const manipfunc<T>& manip)
@@ -60,7 +60,38 @@
             (*manip.pfun)(ostr, manip.arg);
             return ostr;
         }
-
+
+ struct handle_custom_stream
+ {
+ handle_custom_stream()
+ : m_state(0)
+ {
+ }
+
+ ~handle_custom_stream()
+ {
+ if( m_state && m_state->depth() > 0 ) // only needed if nested
+ {
+ m_state->level_down();
+ }
+ }
+
+ container_stream_state<char>* m_state;
+ };
+
+ template<typename Elem, typename Tr>
+ std::basic_ostream<Elem, Tr>& operator<<(std::basic_ostream<Elem, Tr>& ostr, handle_custom_stream& cs)
+ {
+ container_stream_state<Elem>* state = explore::get_stream_state<container_stream_state<Elem> >(ostr);
+ cs.m_state = state;
+ if( state->depth() > 0 ) // only needed if nested
+ {
+ state->level_up();
+ }
+
+ return ostr;
+ }
+
         // function ptr for separator manipulator
         template<typename Elem>
         void separatorFn(std::ios_base& ostr, const Elem* sep)
@@ -107,7 +138,7 @@
         {
             explore::get_stream_state<container_stream_state<char> >(ostr)->set_level(l);
         }
-
+
         // function ptr object for setrows
         //template<typename Elem>
         void setrowsFn(std::ios_base& ostr, std::size_t sz)
@@ -165,12 +196,16 @@
         return detail::manipfunc<const Elem*>(&detail::assoc_endFn, end);
     }
 
- // manipulator
     detail::manipfunc<std::size_t> level(std::size_t l)
     {
         return detail::manipfunc<std::size_t>(&detail::levelFn, l);
     }
 
+ detail::handle_custom_stream custom()
+ {
+ return detail::handle_custom_stream();
+ }
+
     detail::manipfunc<std::size_t> setrows(std::size_t sz)
     {
         return detail::manipfunc<std::size_t>(detail::setrowsFn, sz);
@@ -246,7 +281,7 @@
             T seperatorVal_;
             T endVal_;
         };
-
+
         template<typename Elem, typename Tr, typename T>
         std::basic_ostream<Elem, Tr>& operator<<(std::basic_ostream<Elem, Tr>& ostr, const delimiters_manipulator<T>& manip)
         {

Modified: sandbox/explore/boost/explore/pair.hpp
==============================================================================
--- sandbox/explore/boost/explore/pair.hpp (original)
+++ sandbox/explore/boost/explore/pair.hpp 2009-08-29 21:41:46 EDT (Sat, 29 Aug 2009)
@@ -22,7 +22,7 @@
         using namespace boost::explore;
         container_stream_state<Elem>* state = get_stream_state<container_stream_state<Elem> >(ostr);
         detail::depth_guard<Elem> guard(state);
- state->set_level(state->depth());
+ state->set_level(state->depth()-1);
         return ostr << state->start() << p.first << state->separator() << p.second << state->end();
     }
 }

Modified: sandbox/explore/boost/explore/stream_container.hpp
==============================================================================
--- sandbox/explore/boost/explore/stream_container.hpp (original)
+++ sandbox/explore/boost/explore/stream_container.hpp 2009-08-29 21:41:46 EDT (Sat, 29 Aug 2009)
@@ -25,7 +25,7 @@
         // grab the extra data embedded in the stream object.
         container_stream_state<Elem>* state = explore::get_stream_state<container_stream_state<Elem> >(ostr);
         detail::depth_guard<Elem> guard(state);
- state->set_level(state->depth());
+ state->set_level(state->depth()-1);
 
         // starting delimiter
         ostr << state->start();

Modified: sandbox/explore/libs/explore/doc/custom_containers.qbk
==============================================================================
--- sandbox/explore/libs/explore/doc/custom_containers.qbk (original)
+++ sandbox/explore/libs/explore/doc/custom_containers.qbk 2009-08-29 21:41:46 EDT (Sat, 29 Aug 2009)
@@ -20,16 +20,8 @@
           m_vec.push_back(2);
           m_vec.push_back(3);
       }
-
- std::vector<int>::const_iterator begin() const
- {
- return m_vec.begin();
- }
-
- std::vector<int>::const_iterator end() const
- {
- return m_vec.end();
- }
+
+ friend std::ostream& operator<<(std::ostream& ostr, const user_vector& u);
 
    private:
       std::vector<int> m_vec;
@@ -39,7 +31,7 @@
 
    std::ostream& operator<<(std::ostream& ostr, const user_vector& u)
    {
- return explore::stream_container(ostr, u.begin(), u.end());
+ return explore::stream_container(ostr, u.m_vec.begin(), u.m_vec.end());
    }
 
 With our new overloaded operator<<, the following code
@@ -58,4 +50,37 @@
       return explore::stream_container(ostr, u.begin(), u.end(), explore::stream_associative_value());
    }
 
+If the custom container has a stream operator that defines manipulators that should always be in effect for that container, then it becomes necessary to use the custom() manipulator. For example:
+
+ ostream& operator<<(ostream& ostr, const user_vector& u)
+ {
+ return ostr << explore::custom() << explore::delimiters("/", "::", "/") << u.m_vec.m_data;
+ }
+
+The desire here is to use the delimiters "/" for begin/end and "::" for the separator, independent of what depth the container is streamed at. The "custom" manipulator allows this to work. If this is not specified, you will receive a debug assertion. With this new overload, the code:
+
+ user_vector v;
+ std::cout << v;
+
+prints
+
+ /1::2::3/
+
+But more interestingly:
+
+ std::vector<user_vector> v;
+ v.push_back(user_vector());
+ v.push_back(user_vector());
+
+ std::cout << explore::delimiters("{\n ", "\n ", "\n}") << v;
+
+prints
+
+ {
+ /1::2::3/
+ /1::2::3/
+ }
+
+So the same delimiters are always used for the custom container, even when that container is nested in another.
+
 [endsect]

Modified: sandbox/explore/libs/explore/test/user_defined_container.cpp
==============================================================================
--- sandbox/explore/libs/explore/test/user_defined_container.cpp (original)
+++ sandbox/explore/libs/explore/test/user_defined_container.cpp 2009-08-29 21:41:46 EDT (Sat, 29 Aug 2009)
@@ -11,6 +11,7 @@
 #include <boost/test/unit_test.hpp>
 #include <sstream>
 #include <vector>
+#include <boost/assign.hpp>
 #include <boost/explore.hpp>
 
 class user_vector
@@ -18,9 +19,8 @@
 public:
     user_vector()
     {
- m_vec.push_back(1);
- m_vec.push_back(2);
- m_vec.push_back(3);
+ using namespace boost::assign;
+ m_vec += 1,2,3;
     }
 
     std::vector<int>::const_iterator start() const
@@ -51,3 +51,56 @@
     BOOST_CHECK_EQUAL(str_out.str(), "[1, 2, 3]");
 }
 
+class my_container
+{
+public:
+ my_container()
+ {
+ using namespace boost::assign;
+ m_data += 1, 2, 3, 4, 5, 6;
+ }
+
+ friend std::ostream& operator<<(std::ostream& ostr, const my_container& c);
+
+private:
+ std::vector<int> m_data;
+};
+
+std::ostream& operator<<(std::ostream& ostr, const my_container& c)
+{
+ using namespace boost::explore;
+ return ostr << custom() << delimiters("/", "::", "/") << c.m_data;
+}
+
+BOOST_AUTO_TEST_CASE( custom_stream_test )
+{
+ using namespace boost::assign;
+ using namespace boost::explore;
+ std::stringstream str_out;
+
+ my_container mc;
+ str_out << mc;
+ BOOST_CHECK_EQUAL(str_out.str(), "/1::2::3::4::5::6/");
+
+ str_out.str("");
+
+ std::vector<my_container> vmc;
+ vmc += mc, mc;
+ str_out << delimiters("{\n ", "\n ", "\n}") << vmc;
+ BOOST_CHECK_EQUAL(str_out.str(),
+ "{\n"
+ " /1::2::3::4::5::6/\n"
+ " /1::2::3::4::5::6/\n"
+ "}");
+
+ str_out.str("");
+
+ std::vector<std::vector<my_container> > vvmc;
+ vvmc += vmc, vmc;
+ str_out << level(1) << delimiters("[", " xxx ", "]") << vvmc;
+ BOOST_CHECK_EQUAL(str_out.str(),
+ "{\n"
+ " [/1::2::3::4::5::6/ xxx /1::2::3::4::5::6/]\n"
+ " [/1::2::3::4::5::6/ xxx /1::2::3::4::5::6/]\n"
+ "}");
+}


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