Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:53

0001 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
0002 // (C) Copyright 2003-2007 Jonathan Turkanis
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 // See http://www.boost.org/libs/iostreams for documentation.
0007 
0008 // Contains machinery for performing code conversion.
0009 
0010 #ifndef BOOST_IOSTREAMS_CODE_CONVERTER_HPP_INCLUDED
0011 #define BOOST_IOSTREAMS_CODE_CONVERTER_HPP_INCLUDED
0012 
0013 #if defined(_MSC_VER)
0014 # pragma once
0015 #endif
0016 
0017 #include <boost/iostreams/detail/config/wide_streams.hpp>
0018 #if defined(BOOST_IOSTREAMS_NO_WIDE_STREAMS) || \
0019     defined(BOOST_IOSTREAMS_NO_LOCALE) \
0020     /**/
0021 # error code conversion not supported on this platform
0022 #endif
0023 
0024 #include <algorithm>                       // max.
0025 #include <cstring>                         // memcpy.
0026 #include <exception>
0027 #include <boost/config.hpp>                // DEDUCED_TYPENAME, 
0028 #include <boost/iostreams/char_traits.hpp>
0029 #include <boost/iostreams/constants.hpp>   // default_filter_buffer_size.
0030 #include <boost/iostreams/detail/adapter/concept_adapter.hpp>
0031 #include <boost/iostreams/detail/adapter/direct_adapter.hpp>
0032 #include <boost/iostreams/detail/buffer.hpp>
0033 #include <boost/iostreams/detail/call_traits.hpp>
0034 #include <boost/iostreams/detail/codecvt_holder.hpp>
0035 #include <boost/iostreams/detail/codecvt_helper.hpp>
0036 #include <boost/iostreams/detail/double_object.hpp>
0037 #include <boost/iostreams/detail/execute.hpp>
0038 #include <boost/iostreams/detail/forward.hpp>
0039 #include <boost/iostreams/detail/functional.hpp>
0040 #include <boost/iostreams/detail/ios.hpp> // failure, openmode, int types, streamsize.
0041 #include <boost/iostreams/detail/optional.hpp>
0042 #include <boost/iostreams/detail/select.hpp>
0043 #include <boost/iostreams/traits.hpp>
0044 #include <boost/iostreams/operations.hpp>
0045 #include <boost/shared_ptr.hpp>
0046 #include <boost/static_assert.hpp>
0047 #include <boost/throw_exception.hpp>
0048 #include <boost/type_traits/is_convertible.hpp>
0049 #include <boost/type_traits/is_same.hpp>
0050 
0051 // Must come last.
0052 #include <boost/iostreams/detail/config/disable_warnings.hpp> // Borland 5.x
0053 
0054 namespace boost { namespace iostreams {
0055 
0056 struct code_conversion_error : BOOST_IOSTREAMS_FAILURE {
0057     code_conversion_error() 
0058         : BOOST_IOSTREAMS_FAILURE("code conversion error")
0059         { }
0060 };
0061 
0062 namespace detail {
0063 
0064 //--------------Definition of strncpy_if_same---------------------------------//
0065 
0066 // Helper template for strncpy_if_same, below.
0067 template<bool B>
0068 struct strncpy_if_same_impl;
0069 
0070 template<>
0071 struct strncpy_if_same_impl<true> {
0072     template<typename Ch>
0073     static Ch* copy(Ch* tgt, const Ch* src, std::streamsize n)
0074     { return BOOST_IOSTREAMS_CHAR_TRAITS(Ch)::copy(tgt, src, n); }
0075 };
0076 
0077 template<>
0078 struct strncpy_if_same_impl<false> {
0079     template<typename Src, typename Tgt>
0080     static Tgt* copy(Tgt* tgt, const Src*, std::streamsize) { return tgt; }
0081 };
0082 
0083 template<typename Src, typename Tgt>
0084 Tgt* strncpy_if_same(Tgt* tgt, const Src* src, std::streamsize n)
0085 {
0086     typedef strncpy_if_same_impl<is_same<Src, Tgt>::value> impl;
0087     return impl::copy(tgt, src, n);
0088 }
0089 
0090 //--------------Definition of conversion_buffer-------------------------------//
0091 
0092 // Buffer and conversion state for reading.
0093 template<typename Codecvt, typename Alloc>
0094 class conversion_buffer 
0095     : public buffer<
0096                  BOOST_DEDUCED_TYPENAME detail::codecvt_extern<Codecvt>::type,
0097                  Alloc
0098              > 
0099 {
0100 public:
0101     typedef typename Codecvt::state_type state_type;
0102     conversion_buffer() 
0103         : buffer<
0104               BOOST_DEDUCED_TYPENAME detail::codecvt_extern<Codecvt>::type,
0105               Alloc
0106           >(0) 
0107     { 
0108         reset(); 
0109     }
0110     state_type& state() { return state_; }
0111     void reset() 
0112     { 
0113         if (this->size()) 
0114             this->set(0, 0);
0115         state_ = state_type(); 
0116     }
0117 private:
0118     state_type state_;
0119 };
0120 
0121 //--------------Definition of converter_impl----------------------------------//
0122 
0123 // Contains member data, open/is_open/close and buffer management functions.
0124 template<typename Device, typename Codecvt, typename Alloc>
0125 struct code_converter_impl {
0126     typedef typename codecvt_extern<Codecvt>::type          extern_type;
0127     typedef typename category_of<Device>::type              device_category;
0128     typedef is_convertible<device_category, input>          can_read;
0129     typedef is_convertible<device_category, output>         can_write;
0130     typedef is_convertible<device_category, bidirectional>  is_bidir;
0131     typedef typename 
0132             iostreams::select<  // Disambiguation for Tru64.
0133                 is_bidir, bidirectional,
0134                 can_read, input,
0135                 can_write, output
0136             >::type                                         mode;      
0137     typedef typename
0138             mpl::if_<
0139                 is_direct<Device>,
0140                 direct_adapter<Device>,
0141                 Device
0142             >::type                                         device_type;
0143     typedef optional< concept_adapter<device_type> >        storage_type;
0144     typedef is_convertible<device_category, two_sequence>   is_double;
0145     typedef conversion_buffer<Codecvt, Alloc>               buffer_type;
0146 
0147     code_converter_impl() : cvt_(), flags_(0) { }
0148 
0149     ~code_converter_impl()
0150     { 
0151         try { 
0152             if (flags_ & f_open) close(); 
0153         } catch (...) { /* */ } 
0154     }
0155 
0156     template <class T>
0157     void open(const T& dev, std::streamsize buffer_size)
0158     {
0159         if (flags_ & f_open)
0160             boost::throw_exception(BOOST_IOSTREAMS_FAILURE("already open"));
0161         if (buffer_size == -1)
0162             buffer_size = default_filter_buffer_size;
0163         std::streamsize max_length = cvt_.get().max_length();
0164         buffer_size = (std::max)(buffer_size, 2 * max_length);
0165         if (can_read::value) {
0166             buf_.first().resize(buffer_size);
0167             buf_.first().set(0, 0);
0168         }
0169         if (can_write::value && !is_double::value) {
0170             buf_.second().resize(buffer_size);
0171             buf_.second().set(0, 0);
0172         }
0173         dev_.reset(concept_adapter<device_type>(dev));
0174         flags_ = f_open;
0175     }
0176 
0177     void close()
0178     {
0179         detail::execute_all(
0180             detail::call_member_close(*this, BOOST_IOS::in),
0181             detail::call_member_close(*this, BOOST_IOS::out)
0182         );
0183     }
0184 
0185     void close(BOOST_IOS::openmode which)
0186     {
0187         if (which == BOOST_IOS::in && (flags_ & f_input_closed) == 0) {
0188             flags_ |= f_input_closed;
0189             iostreams::close(dev(), BOOST_IOS::in);
0190         }
0191         if (which == BOOST_IOS::out && (flags_ & f_output_closed) == 0) {
0192             flags_ |= f_output_closed;
0193             detail::execute_all(
0194                 detail::flush_buffer(buf_.second(), dev(), can_write::value),
0195                 detail::call_close(dev(), BOOST_IOS::out),
0196                 detail::call_reset(dev_),
0197                 detail::call_reset(buf_.first()),
0198                 detail::call_reset(buf_.second())
0199             );
0200         }
0201     }
0202 
0203     bool is_open() const { return (flags_ & f_open) != 0;}
0204 
0205     device_type& dev() { return **dev_; }
0206 
0207     enum flag_type {
0208         f_open             = 1,
0209         f_input_closed     = f_open << 1,
0210         f_output_closed    = f_input_closed << 1
0211     };
0212 
0213     codecvt_holder<Codecvt>  cvt_;
0214     storage_type             dev_;
0215     double_object<
0216         buffer_type, 
0217         is_double
0218     >                        buf_;
0219     int                      flags_;
0220 };
0221 
0222 } // End namespace detail.
0223 
0224 //--------------Definition of converter---------------------------------------//
0225 
0226 #define BOOST_IOSTREAMS_CONVERTER_PARAMS() , std::streamsize buffer_size = -1
0227 #define BOOST_IOSTREAMS_CONVERTER_ARGS() , buffer_size
0228 
0229 template<typename Device, typename Codecvt, typename Alloc>
0230 struct code_converter_base {
0231     typedef detail::code_converter_impl<
0232                 Device, Codecvt, Alloc
0233             > impl_type;
0234     code_converter_base() : pimpl_(new impl_type) { }
0235     shared_ptr<impl_type> pimpl_;
0236 };
0237 
0238 template< typename Device, 
0239           typename Codecvt = detail::default_codecvt, 
0240           typename Alloc = std::allocator<char> >
0241 class code_converter 
0242     : protected code_converter_base<Device, Codecvt, Alloc>
0243 {
0244 private:
0245     typedef detail::code_converter_impl<
0246                 Device, Codecvt, Alloc
0247             >                                                       impl_type;
0248     typedef typename impl_type::device_type                         device_type;
0249     typedef typename impl_type::buffer_type                         buffer_type;
0250     typedef typename detail::codecvt_holder<Codecvt>::codecvt_type  codecvt_type;
0251     typedef typename detail::codecvt_intern<Codecvt>::type          intern_type;
0252     typedef typename detail::codecvt_extern<Codecvt>::type          extern_type;
0253     typedef typename detail::codecvt_state<Codecvt>::type           state_type;
0254 public:
0255     typedef intern_type                                             char_type;    
0256     struct category 
0257         : impl_type::mode, device_tag, closable_tag, localizable_tag
0258         { };
0259     BOOST_STATIC_ASSERT((
0260         is_same<
0261             extern_type, 
0262             BOOST_DEDUCED_TYPENAME char_type_of<Device>::type
0263         >::value
0264     ));
0265 public:
0266     code_converter() { }
0267     BOOST_IOSTREAMS_FORWARD( code_converter, open_impl, Device,
0268                              BOOST_IOSTREAMS_CONVERTER_PARAMS, 
0269                              BOOST_IOSTREAMS_CONVERTER_ARGS )
0270 
0271         // fstream-like interface.
0272 
0273     bool is_open() const { return this->pimpl_->is_open(); }
0274     void close(BOOST_IOS::openmode which = BOOST_IOS::in | BOOST_IOS::out )
0275     { impl().close(which); }
0276 
0277         // Device interface.
0278 
0279     std::streamsize read(char_type*, std::streamsize);
0280     std::streamsize write(const char_type*, std::streamsize);
0281     void imbue(const std::locale& loc) { impl().cvt_.imbue(loc); }
0282 
0283         // Direct device access.
0284 
0285     Device& operator*() { return detail::unwrap_direct(dev()); }
0286     Device* operator->() { return &detail::unwrap_direct(dev()); }
0287 private:
0288     template<typename T> // Used for forwarding.
0289     void open_impl(const T& t BOOST_IOSTREAMS_CONVERTER_PARAMS()) 
0290     { 
0291         impl().open(t BOOST_IOSTREAMS_CONVERTER_ARGS()); 
0292     }
0293 
0294     const codecvt_type& cvt() { return impl().cvt_.get(); }
0295     device_type& dev() { return impl().dev(); }
0296     buffer_type& in() { return impl().buf_.first(); }
0297     buffer_type& out() { return impl().buf_.second(); }
0298     impl_type& impl() { return *this->pimpl_; }
0299 };
0300 
0301 //--------------Implementation of converter-----------------------------------//
0302 
0303 // Implementation note: if end of stream contains a partial character,
0304 // it is ignored.
0305 template<typename Device, typename Codevt, typename Alloc>
0306 std::streamsize code_converter<Device, Codevt, Alloc>::read
0307     (char_type* s, std::streamsize n)
0308 {
0309     const extern_type*   next;        // Next external char.
0310     intern_type*         nint;        // Next internal char.
0311     std::streamsize      total = 0;   // Characters read.
0312     int                  status = iostreams::char_traits<char>::good();
0313     bool                 partial = false;
0314     buffer_type&         buf = in();
0315 
0316     do {
0317 
0318         // Fill buffer.
0319         if (buf.ptr() == buf.eptr() || partial) {
0320             status = buf.fill(dev());
0321             if (buf.ptr() == buf.eptr())
0322                 break;
0323             partial = false;
0324         }
0325 
0326         // Convert.
0327         std::codecvt_base::result result =
0328             cvt().in( buf.state(),
0329                       buf.ptr(), buf.eptr(), next,
0330                       s + total, s + n, nint );
0331         buf.ptr() += next - buf.ptr();
0332         total = static_cast<std::streamsize>(nint - s);
0333 
0334         switch (result) {
0335         case std::codecvt_base::partial:
0336             partial = true;
0337             break;
0338         case std::codecvt_base::ok:
0339             break;
0340         case std::codecvt_base::noconv:
0341             {
0342                 std::streamsize amt = 
0343                     std::min<std::streamsize>(next - buf.ptr(), n - total);
0344                 detail::strncpy_if_same(s + total, buf.ptr(), amt);
0345                 total += amt;
0346             }
0347             break;
0348         case std::codecvt_base::error:
0349         default:
0350             buf.state() = state_type();
0351             boost::throw_exception(code_conversion_error());
0352         }
0353 
0354     } while (total < n && status != EOF && status != WOULD_BLOCK);
0355 
0356     return total == 0 && status == EOF ? -1 : total;
0357 }
0358 
0359 template<typename Device, typename Codevt, typename Alloc>
0360 std::streamsize code_converter<Device, Codevt, Alloc>::write
0361     (const char_type* s, std::streamsize n)
0362 {
0363     buffer_type&        buf = out();
0364     extern_type*        next;              // Next external char.
0365     const intern_type*  nint;              // Next internal char.
0366     std::streamsize     total = 0;         // Characters written.
0367     bool                partial = false;
0368 
0369     while (total < n) {
0370 
0371         // Empty buffer.
0372         if (buf.eptr() == buf.end() || partial) {
0373             if (!buf.flush(dev()))
0374                 break;
0375             partial = false;
0376         }
0377        
0378         // Convert.
0379         std::codecvt_base::result result =
0380             cvt().out( buf.state(),
0381                        s + total, s + n, nint,
0382                        buf.eptr(), buf.end(), next );
0383         int progress = (int) (next - buf.eptr());
0384         buf.eptr() += progress;
0385 
0386         switch (result) {
0387         case std::codecvt_base::partial:
0388             partial = true;
0389             BOOST_FALLTHROUGH;
0390         case std::codecvt_base::ok:
0391             total = static_cast<std::streamsize>(nint - s);
0392             break;
0393         case std::codecvt_base::noconv:
0394             {
0395                 std::streamsize amt = 
0396                     std::min<std::streamsize>( nint - total - s, 
0397                                                buf.end() - buf.eptr() );
0398                 detail::strncpy_if_same(buf.eptr(), s + total, amt);
0399                 total += amt;
0400             }
0401             break;
0402         case std::codecvt_base::error:
0403         default:
0404             buf.state() = state_type();
0405             boost::throw_exception(code_conversion_error());
0406         }
0407     }
0408     return total;
0409 }
0410 
0411 //----------------------------------------------------------------------------//
0412 
0413 } } // End namespaces iostreams, boost.
0414 
0415 #include <boost/iostreams/detail/config/enable_warnings.hpp> // Borland 5.x
0416 
0417 #endif // #ifndef BOOST_IOSTREAMS_CODE_CONVERTER_HPP_INCLUDED