// (C) Copyright Jonathan Turkanis 2004. // Distributed under 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. // Disclaimer: Not a Boost library. #ifndef BOOST_IOSTREAMS_PUNCUATION_HPP_INCLUDED #define BOOST_IOSTREAMS_PUNCUATION_HPP_INCLUDED #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif #include #include #include #include #include #include // Member template friends. #include // Max tuple arity. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace io { namespace punc { const int spaces = 1; const int tabs = 100; const int flat = 0; const int break_after_open = 1 << 11; const int indent_after_open = break_after_open << 1; const int break_before_sep = indent_after_open << 1; const int break_after_sep = break_before_sep << 1; const int break_before_close = break_after_sep << 1; const int has_break = break_after_open | break_before_sep | break_after_sep | break_before_close; const int flags_mask = ~((1 << 11) - 1); int get_flags(int indent) { return indent & flags_mask; } int get_spaces(int indent) { return (indent & ~flags_mask) % 100; } int get_tabs(int indent) { int val = indent & ~flags_mask; return val != 0 ? static_cast((indent & ~flags_mask) / 100) : 1; } } // End namespace punc. using mpl::_; //------------------Definition of default_punctuation-------------------------// template struct default_punctuation { typedef std::basic_string string_type; static string_type open() { return ct().widen("("); } static string_type close() { return ct().widen(")"); } static string_type sep() { return ct().widen(","); } static const std::ctype& ct() { static const std::ctype& ct = std::use_facet< std::ctype >(std::locale::classic()); return ct; } }; template<> struct default_punctuation { typedef std::string string_type; static const char* open() { return "("; } static const char* close() { return ")"; } static const char* sep() { return ","; } }; template<> struct default_punctuation { typedef std::basic_string string_type; static string_type open() { return string_type(1, '('); } static string_type close() { return string_type(1, ')'); } static string_type sep() { return string_type(1, ','); } }; template<> struct default_punctuation { typedef std::basic_string string_type; static string_type open() { return string_type(1, '('); } static string_type close() { return string_type(1, ')'); } static string_type sep() { return string_type(1, ','); } }; template<> struct default_punctuation { typedef std::basic_string string_type; static const wchar_t* open() { return L"("; } static const wchar_t* close() { return L")"; } static const wchar_t* sep() { return L","; } }; //------------------Definition of no_punctuation------------------------------// template struct no_punctuation { typedef std::basic_string string_type; static string_type open() { return ct().widen(""); } static string_type close() { return ct().widen(""); } static string_type sep() { return ct().widen(""); } static const std::ctype& ct() { static const std::ctype& ct = std::use_facet< std::ctype >(std::locale::classic()); return ct; } }; template<> struct no_punctuation { typedef std::string string_type; static const char* open() { return ""; } static const char* close() { return ""; } static const char* sep() { return ""; } }; template<> struct no_punctuation { typedef std::basic_string string_type; static string_type open() { return string_type(); } static string_type close() { return string_type(); } static string_type sep() { return string_type(); } }; template<> struct no_punctuation { typedef std::basic_string string_type; static string_type open() { return string_type(); } static string_type close() { return string_type(); } static string_type sep() { return string_type(); } }; template<> struct no_punctuation { typedef std::basic_string string_type; static const wchar_t* open() { return L""; } static const wchar_t* close() { return L""; } static const wchar_t* sep() { return L""; } }; //------------------Definition of punctuation---------------------------------// template class punctuation { public: typedef std::basic_string string_type; punctuation() : indentation_(punc::flat) { push_back(default_punctuation::open()); push_back(default_punctuation::sep()); push_back(default_punctuation::close()); } punctuation( const string_type& open, const string_type& sep, const string_type& close, int indent = punc::flat ) : indentation_(indent) { push_back(open); push_back(sep); push_back(close); } const string_type& open() const { return punc_[0]; } const string_type& sep() const { return punc_[1]; } const string_type& close() const { return punc_.back(); } template const string_type& nth_sep() const { return punc_.size() > 3 ? punc_[N + 1] : sep(); } int flags() const { return punc::get_flags(indentation_); } int tabs() const { return punc::get_tabs(indentation_); } int spaces() const { return punc::get_spaces(indentation_); } static punctuation none() { return punctuation( no_punctuation::open(), no_punctuation::close(), no_punctuation::sep() ); } protected: void clear() { punc_.clear(); } void push_back(const string_type& s) { punc_.push_back(s); } private: std::vector punc_; int indentation_; }; //------------------Definition of range_punctuation---------------------------// template class range_punctuation : public punctuation { public: typedef typename punctuation::string_type string_type; typedef Formattable formattable_type; range_punctuation() { } range_punctuation( const string_type& open, const string_type& sep, const string_type& close, int indent = punc::flat ) : punctuation(open, sep, close, indent) { }; range_punctuation(const punctuation& punc) : punctuation(punc) { }; #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS private: template friend std::basic_ostream& operator<<(std::basic_ostream&, const range_punctuation&); template friend std::basic_ostream& operator<<(std::basic_ostream&, const tuple_punctuation&); template friend std::basic_istream& operator>>(std::basic_istream&, const range_punctuation&); template friend std::basic_istream& operator>>(std::basic_istream&, const tuple_punctuation&); template friend struct detail::get_punctuation_impl; #endif static int index() { static int index = std::ios_base::xalloc(); return index; } static void callback( std::ios_base::event event, std::ios_base& io, int index ) { typedef range_punctuation facet_type; if (event == std::ios_base::erase_event) delete static_cast(io.pword(index)); } }; //------------------Definition of tuple_punctuation---------------------// template class tuple_punctuation : public punctuation { public: typedef typename tuple_size::type size; typedef typename punctuation::string_type string_type; typedef Tuple tuple_type; // Local iteration defining constructors. #define BOOST_IOSTREAMS_PUSHBACK(z, n, text) this->push_back(BOOST_PP_CAT(s, n)); #define BOOST_PP_LOCAL_MACRO(n) \ tuple_punctuation( BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n), \ const std::basic_string& s), \ int indent = punc::flat) \ { \ this->clear(); \ BOOST_PP_REPEAT(BOOST_PP_INC(n), BOOST_IOSTREAMS_PUSHBACK, _) \ } \ /**/ #define BOOST_PP_LOCAL_LIMITS (3, BOOST_IOSTREAMS_TUPLE_MAX_ARITY ) #include BOOST_PP_LOCAL_ITERATE() #undef BOOST_IOSTREAMS_PUSHBACK #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS private: template friend std::basic_ostream& operator<<(std::basic_ostream&, const range_punctuation&); template friend std::basic_ostream& operator<<(std::basic_ostream&, const tuple_punctuation&); template friend std::basic_istream& operator>>(std::basic_istream&, const range_punctuation&); template friend std::basic_istream& operator>>(std::basic_istream&, const tuple_punctuation&); template friend struct detail::get_punctuation_impl; #endif static int index() { static int index = std::ios_base::xalloc(); return index; } static void callback( std::ios_base::event event, std::ios_base& ios, int index ) { typedef tuple_punctuation facet_type; if (event == std::ios_base::erase_event) delete static_cast(ios.pword(index)); } }; //------------------Definition of punctuate-----------------------------------// template range_punctuation punctuate( const Ch* open, const Ch* sep, const Ch* close, int indent = punc::flat ) { return range_punctuation(open, sep, close, indent); } template range_punctuation punctuate( const std::basic_string& open, const std::basic_string& sep, const std::basic_string& close, int indent = punc::flat ) { return range_punctuation(open, sep, close, indent); } template typename enable_if< is_tuple_like, tuple_punctuation >::type punctuate(const Ch* open, const Ch* close, int indent = punc::flat) { typedef typename tuple_size::type size; BOOST_STATIC_ASSERT(size::value <= 1); return tuple_punctuation(open, close, indent); } template typename enable_if< is_tuple_like, tuple_punctuation >::type punctuate( const std::basic_string& open, const std::basic_string& close, int indent = punc::flat ) { typedef typename tuple_size::type size; BOOST_STATIC_ASSERT(size::value <= 1); return tuple_punctuation(open, close, indent); } #define BOOST_PP_LOCAL_MACRO(n) \ template \ typename \ enable_if< \ is_tuple_like, \ tuple_punctuation \ >::type \ punctuate( BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n), const Ch* s), \ int indent = punc::flat ) \ { \ typedef typename tuple_size::type size; \ BOOST_STATIC_ASSERT(n == size::value); \ return tuple_punctuation \ (BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n), s), indent); \ } \ template \ typename enable_if< \ is_tuple_like, \ tuple_punctuation \ >::type \ punctuate( BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n), \ const std::basic_string& s), \ int indent = punc::flat ) \ { \ typedef typename tuple_size::type size; \ BOOST_STATIC_ASSERT(n == size::value); \ return tuple_punctuation \ (BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n), s), indent); \ } \ /**/ #define BOOST_PP_LOCAL_LIMITS (3, BOOST_IOSTREAMS_TUPLE_MAX_ARITY - 1) #include BOOST_PP_LOCAL_ITERATE() //------------------Definition of punctuate-----------------------------------// //------------------inserters and extractors for use with punctuate-----------// template std::basic_ostream& operator<<( std::basic_ostream& out, const range_punctuation& punc ) { using namespace std; typedef typename detail::normalize::type normalized; typedef range_punctuation facet_type; int index = facet_type::index(); facet_type* facet; if (!(facet = static_cast(out.pword(index)))) { out.register_callback(facet_type::callback, index); out.pword(index) = new facet_type(punc); } else { facet_type* new_facet = new facet_type(punc); delete facet; out.pword(index) = new_facet; } return out; } template std::basic_ostream& operator<<( std::basic_ostream& out, const tuple_punctuation& punc ) { using namespace std; typedef tuple_punctuation facet_type; int index = facet_type::index(); facet_type* facet; if (!(facet = static_cast(out.pword(index)))) { out.register_callback(facet_type::callback, index); out.pword(index) = new facet_type(punc); } else { facet_type* new_facet = new facet_type(punc); delete facet; out.pword(index) = new_facet; } return out; } template std::basic_istream& operator>>( std::basic_istream& in, const range_punctuation& punc ) { using namespace std; typedef typename detail::normalize::type normalized; typedef range_punctuation facet_type; int index = facet_type::index(); facet_type* facet; if (!(facet = static_cast(in.pword(index)))) { in.register_callback(facet_type::callback, index); in.pword(index) = new facet_type(punc); } else { facet_type* new_facet = new facet_type(punc); delete facet; in.pword(index) = new_facet; } return in; } template std::basic_istream& operator>>( std::basic_istream& in, const tuple_punctuation& punc ) { using namespace std; typedef tuple_punctuation facet_type; int index = facet_type::index(); facet_type* facet; if (!(facet = static_cast(in.pword(index)))) { in.register_callback(facet_type::callback, index); in.pword(index) = new facet_type(punc); } else { facet_type* new_facet = new facet_type(punc); delete facet; in.pword(index) = new_facet; } return in; } //------------------Definition of get_punctuation-----------------------------// namespace detail { template struct get_punctuation_impl; template<> struct get_punctuation_impl { template static punctuation get_punctuation(std::basic_ios& out, const Range&) { using namespace std; typedef range_punctuation::type, Ch> facet1; typedef range_punctuation::type, Ch> facet2; void* pv; if (pv = out.pword(facet1::index())) { return *static_cast(pv); } else if ( !is_same< detail::rebind, detail::normalize >::value && (pv = out.pword(facet2::index())) ) { return *static_cast(pv); } else { return punctuation(); } } }; template<> struct get_punctuation_impl { template static punctuation get_punctuation(std::basic_ios& out, const Tuple&) { using namespace std; typedef tuple_punctuation facet1; typedef range_punctuation facet2; typedef range_punctuation::type, Ch> facet3; void* pv; if (pv = out.pword(facet1::index())) { return *static_cast(pv); } if (pv = out.pword(facet2::index())) { return *static_cast(pv); } else if ( !is_same::value && (pv = out.pword(facet3::index())) ) { return *static_cast(pv); } else { return is_tuple_like::value ? punctuation() : punctuation::none(); } } }; } // End namespace detail. template punctuation get_punctuation(std::basic_ios& out, const Formattable& f) { typedef detail::get_punctuation_impl< is_single_pass_range::value > impl; return impl::get_punctuation(out, f); } } } // End namespace io, boost. #endif // #ifndef BOOST_IOSTREAMS_PUNCUATION_HPP_INCLUDED