Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-19 09:47:39

0001 //  Copyright (c) 2001-2011 Hartmut Kaiser
0002 //
0003 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 #if !defined(BOOST_SPIRIT_KARMA_STREAM_MAY_01_2007_0310PM)
0007 #define BOOST_SPIRIT_KARMA_STREAM_MAY_01_2007_0310PM
0008 
0009 #if defined(_MSC_VER)
0010 #pragma once
0011 #endif
0012 
0013 #include <boost/spirit/home/support/common_terminals.hpp>
0014 #include <boost/spirit/home/support/info.hpp>
0015 #include <boost/spirit/home/support/container.hpp>
0016 #include <boost/spirit/home/support/detail/hold_any.hpp>
0017 #include <boost/spirit/home/support/detail/get_encoding.hpp>
0018 #include <boost/spirit/home/support/detail/is_spirit_tag.hpp>
0019 #include <boost/spirit/home/karma/domain.hpp>
0020 #include <boost/spirit/home/karma/meta_compiler.hpp>
0021 #include <boost/spirit/home/karma/delimit_out.hpp>
0022 #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
0023 #include <boost/spirit/home/karma/stream/detail/format_manip.hpp>
0024 #include <boost/spirit/home/karma/detail/generate_to.hpp>
0025 #include <boost/spirit/home/karma/detail/get_casetag.hpp>
0026 #include <boost/spirit/home/karma/detail/extract_from.hpp>
0027 #include <boost/fusion/include/at.hpp>
0028 #include <boost/fusion/include/vector.hpp>
0029 #include <boost/fusion/include/cons.hpp>
0030 #include <boost/core/enable_if.hpp>
0031 #include <boost/mpl/bool.hpp>
0032 #include <boost/type_traits/is_same.hpp>
0033 #include <ostream>
0034 
0035 ///////////////////////////////////////////////////////////////////////////////
0036 namespace boost { namespace spirit
0037 {
0038     namespace tag
0039     {
0040         template <typename Char = char>
0041         struct stream_tag 
0042         {
0043             BOOST_SPIRIT_IS_TAG()
0044         };
0045     }
0046 
0047     namespace karma
0048     {
0049         ///////////////////////////////////////////////////////////////////////
0050         // This one is the class that the user can instantiate directly in 
0051         // order to create a customized int generator
0052         template <typename Char = char>
0053         struct stream_generator
0054           : spirit::terminal<tag::stream_tag<Char> > 
0055         {};
0056     }
0057 
0058     ///////////////////////////////////////////////////////////////////////////
0059     // Enablers
0060     ///////////////////////////////////////////////////////////////////////////
0061     template <>
0062     struct use_terminal<karma::domain, tag::stream>     // enables stream
0063       : mpl::true_ {};
0064 
0065     template <>
0066     struct use_terminal<karma::domain, tag::wstream>    // enables wstream
0067       : mpl::true_ {};
0068 
0069     template <typename A0>
0070     struct use_terminal<karma::domain                   // enables stream(...)
0071       , terminal_ex<tag::stream, fusion::vector1<A0> >
0072     > : mpl::true_ {};
0073 
0074     template <typename A0>
0075     struct use_terminal<karma::domain                   // enables wstream(...)
0076       , terminal_ex<tag::wstream, fusion::vector1<A0> >
0077     > : mpl::true_ {};
0078 
0079     template <>                                         // enables stream(f)
0080     struct use_lazy_terminal<
0081         karma::domain, tag::stream, 1   /*arity*/
0082     > : mpl::true_ {};
0083 
0084     template <>                                         // enables wstream(f)
0085     struct use_lazy_terminal<
0086         karma::domain, tag::wstream, 1  /*arity*/
0087     > : mpl::true_ {};
0088 
0089     // enables stream_generator<char_type>
0090     template <typename Char>
0091     struct use_terminal<karma::domain, tag::stream_tag<Char> >
0092       : mpl::true_ {};
0093 
0094     template <typename Char, typename A0>
0095     struct use_terminal<karma::domain
0096       , terminal_ex<tag::stream_tag<Char>, fusion::vector1<A0> >
0097     > : mpl::true_ {};
0098 
0099     template <typename Char>
0100     struct use_lazy_terminal<
0101         karma::domain, tag::stream_tag<Char>, 1  /*arity*/
0102     > : mpl::true_ {};
0103 
0104 }}
0105 
0106 ///////////////////////////////////////////////////////////////////////////////
0107 namespace boost { namespace spirit { namespace karma
0108 {
0109 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
0110     using spirit::stream;
0111     using spirit::wstream;
0112 #endif
0113     using spirit::stream_type;
0114     using spirit::wstream_type;
0115 
0116 namespace detail
0117 {
0118 #ifdef _MSC_VER
0119 #  pragma warning(push)
0120 #  pragma warning(disable: 4512) // assignment operator could not be generated.
0121 #endif
0122     template <typename OutputIterator, typename Char, typename CharEncoding
0123       , typename Tag>
0124     struct psbuf : std::basic_streambuf<Char>
0125     {
0126         psbuf(OutputIterator& sink) : sink_(sink) {}
0127 
0128     protected:
0129         typename psbuf::int_type overflow(typename psbuf::int_type ch) BOOST_OVERRIDE
0130         {
0131             if (psbuf::traits_type::eq_int_type(ch, psbuf::traits_type::eof()))
0132                 return psbuf::traits_type::not_eof(ch);
0133 
0134             return detail::generate_to(sink_, psbuf::traits_type::to_char_type(ch),
0135                                        CharEncoding(), Tag()) ? ch : psbuf::traits_type::eof();
0136         }
0137 
0138     private:
0139         OutputIterator& sink_;
0140     };
0141 #ifdef _MSC_VER
0142 #  pragma warning(pop)
0143 #endif
0144 }
0145 
0146     ///////////////////////////////////////////////////////////////////////////
0147     template <typename Char, typename CharEncoding, typename Tag>
0148     struct any_stream_generator
0149       : primitive_generator<any_stream_generator<Char, CharEncoding, Tag> >
0150     {
0151         template <typename Context, typename Unused = unused_type>
0152         struct attribute
0153         {
0154             typedef spirit::basic_hold_any<Char> type;
0155         };
0156 
0157         // any_stream_generator has an attached attribute 
0158         template <
0159             typename OutputIterator, typename Context, typename Delimiter
0160           , typename Attribute
0161         >
0162         static bool generate(OutputIterator& sink, Context& context
0163           , Delimiter const& d, Attribute const& attr)
0164         {
0165             if (!traits::has_optional_value(attr))
0166                 return false;
0167 
0168             // use existing operator<<()
0169             typedef typename attribute<Context>::type attribute_type;
0170 
0171             {
0172                 detail::psbuf<OutputIterator, Char, CharEncoding, Tag> pseudobuf(sink);
0173                 std::basic_ostream<Char> ostr(&pseudobuf);
0174                 ostr << traits::extract_from<attribute_type>(attr, context) << std::flush;
0175 
0176                 if (!ostr.good())
0177                     return false;
0178             }
0179 
0180             return karma::delimit_out(sink, d);   // always do post-delimiting
0181         }
0182 
0183         // this is a special overload to detect if the output iterator has been
0184         // generated by a format_manip object.
0185         template <
0186             typename T, typename Traits, typename Properties, typename Context
0187           , typename Delimiter, typename Attribute
0188         >
0189         static bool generate(
0190             karma::detail::output_iterator<
0191                 karma::ostream_iterator<T, Char, Traits>, Properties
0192             >& sink, Context& context, Delimiter const& d
0193           , Attribute const& attr)
0194         {
0195             typedef karma::detail::output_iterator<
0196                 karma::ostream_iterator<T, Char, Traits>, Properties
0197             > output_iterator;
0198 
0199             if (!traits::has_optional_value(attr))
0200                 return false;
0201 
0202             // use existing operator<<()
0203             typedef typename attribute<Context>::type attribute_type;
0204 
0205             {
0206                 detail::psbuf<output_iterator, Char, CharEncoding, Tag> pseudobuf(sink);
0207                 std::basic_ostream<Char> ostr(&pseudobuf);
0208                 ostr.imbue(sink.get_ostream().getloc());
0209                 ostr << traits::extract_from<attribute_type>(attr, context) 
0210                      << std::flush;
0211                 if (!ostr.good())
0212                     return false;
0213             }
0214 
0215             return karma::delimit_out(sink, d);  // always do post-delimiting
0216         }
0217 
0218         // this any_stream has no parameter attached, it needs to have been
0219         // initialized from a value/variable
0220         template <typename OutputIterator, typename Context
0221           , typename Delimiter>
0222         static bool
0223         generate(OutputIterator&, Context&, Delimiter const&, unused_type)
0224         {
0225             // It is not possible (doesn't make sense) to use stream generators
0226             // without providing any attribute, as the generator doesn't 'know'
0227             // what to output. The following assertion fires if this situation
0228             // is detected in your code.
0229             BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, stream_not_usable_without_attribute, ());
0230             return false;
0231         }
0232 
0233         template <typename Context>
0234         info what(Context& /*context*/) const
0235         {
0236             return info("stream");
0237         }
0238     };
0239 
0240     template <typename T, typename Char, typename CharEncoding, typename Tag>
0241     struct lit_stream_generator
0242       : primitive_generator<lit_stream_generator<T, Char, CharEncoding, Tag> >
0243     {
0244         template <typename Context, typename Unused>
0245         struct attribute 
0246         {
0247             typedef unused_type type;
0248         };
0249 
0250         lit_stream_generator(typename add_reference<T>::type t)
0251           : t_(t)
0252         {}
0253 
0254         // lit_stream_generator has an attached parameter
0255 
0256         // this overload will be used in the normal case (not called from
0257         // format_manip).
0258         template <
0259             typename OutputIterator, typename Context, typename Delimiter
0260           , typename Attribute>
0261         bool generate(OutputIterator& sink, Context&, Delimiter const& d
0262           , Attribute const&) const
0263         {
0264             detail::psbuf<OutputIterator, Char, CharEncoding, Tag> pseudobuf(sink);
0265             std::basic_ostream<Char> ostr(&pseudobuf);
0266             ostr << t_ << std::flush;             // use existing operator<<()
0267 
0268             if (ostr.good()) 
0269                 return karma::delimit_out(sink, d); // always do post-delimiting
0270             return false;
0271         }
0272 
0273         // this is a special overload to detect if the output iterator has been
0274         // generated by a format_manip object.
0275         template <
0276             typename T1, typename Traits, typename Properties
0277           , typename Context, typename Delimiter, typename Attribute>
0278         bool generate(
0279             karma::detail::output_iterator<
0280                 karma::ostream_iterator<T1, Char, Traits>, Properties
0281             >& sink, Context&, Delimiter const& d, Attribute const&) const
0282         {
0283             typedef karma::detail::output_iterator<
0284                 karma::ostream_iterator<T1, Char, Traits>, Properties
0285             > output_iterator;
0286 
0287             {
0288                 detail::psbuf<output_iterator, Char, CharEncoding, Tag> pseudobuf(sink);
0289                 std::basic_ostream<Char> ostr(&pseudobuf);
0290                 ostr.imbue(sink.get_ostream().getloc());
0291                 ostr << t_ << std::flush;             // use existing operator<<()
0292 
0293                 if (!ostr.good())
0294                     return false;
0295             }
0296 
0297             return karma::delimit_out(sink, d); // always do post-delimiting
0298         }
0299 
0300         template <typename Context>
0301         info what(Context& /*context*/) const
0302         {
0303             return info("any-stream");
0304         }
0305 
0306         T t_;
0307     };
0308 
0309     ///////////////////////////////////////////////////////////////////////////
0310     // Generator generators: make_xxx function (objects)
0311     ///////////////////////////////////////////////////////////////////////////
0312     template <typename Char, typename Modifiers>
0313     struct make_stream
0314     {
0315         static bool const lower =
0316             has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0317 
0318         static bool const upper =
0319             has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0320 
0321         typedef any_stream_generator<
0322             Char
0323           , typename spirit::detail::get_encoding_with_case<
0324                 Modifiers, unused_type, lower || upper>::type
0325           , typename detail::get_casetag<Modifiers, lower || upper>::type
0326         > result_type;
0327 
0328         result_type operator()(unused_type, unused_type) const
0329         {
0330             return result_type();
0331         }
0332     };
0333 
0334     // stream
0335     template <typename Modifiers>
0336     struct make_primitive<tag::stream, Modifiers> 
0337       : make_stream<char, Modifiers> {};
0338 
0339     // wstream
0340     template <typename Modifiers>
0341     struct make_primitive<tag::wstream, Modifiers> 
0342       : make_stream<wchar_t, Modifiers> {};
0343 
0344     // any_stream_generator<char_type>
0345     template <typename Char, typename Modifiers>
0346     struct make_primitive<tag::stream_tag<Char>, Modifiers> 
0347       : make_stream<Char, Modifiers> {};
0348 
0349     ///////////////////////////////////////////////////////////////////////////
0350     template <typename Char, typename A0, typename Modifiers>
0351     struct make_any_stream
0352     {
0353         static bool const lower =
0354             has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0355 
0356         static bool const upper =
0357             has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0358 
0359         typedef typename add_const<A0>::type const_attribute;
0360         typedef lit_stream_generator<
0361             const_attribute, Char
0362           , typename spirit::detail::get_encoding_with_case<
0363                 Modifiers, unused_type, lower || upper>::type
0364           , typename detail::get_casetag<Modifiers, lower || upper>::type
0365         > result_type;
0366 
0367         template <typename Terminal>
0368         result_type operator()(Terminal const& term, unused_type) const
0369         {
0370             return result_type(fusion::at_c<0>(term.args));
0371         }
0372     };
0373 
0374     // stream(...)
0375     template <typename Modifiers, typename A0>
0376     struct make_primitive<
0377             terminal_ex<tag::stream, fusion::vector1<A0> >, Modifiers>
0378       : make_any_stream<char, A0, Modifiers> {};
0379 
0380     // wstream(...)
0381     template <typename Modifiers, typename A0>
0382     struct make_primitive<
0383             terminal_ex<tag::wstream, fusion::vector1<A0> >, Modifiers>
0384       : make_any_stream<wchar_t, A0, Modifiers> {};
0385 
0386     // any_stream_generator<char_type>(...)
0387     template <typename Char, typename Modifiers, typename A0>
0388     struct make_primitive<
0389             terminal_ex<tag::stream_tag<Char>, fusion::vector1<A0> >
0390           , Modifiers>
0391       : make_any_stream<Char, A0, Modifiers> {};
0392 
0393 }}}
0394 
0395 #endif