Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:29

0001 #ifndef BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP
0002 #define BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP
0003 
0004 // MS compatible compilers support #pragma once
0005 #if defined(_MSC_VER)
0006 # pragma once
0007 #endif
0008 
0009 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
0010 // wchar_from_mb.hpp
0011 
0012 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
0013 // Use, modification and distribution is subject to the Boost Software
0014 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0015 // http://www.boost.org/LICENSE_1_0.txt)
0016 
0017 //  See http://www.boost.org for updates, documentation, and revision history.
0018 
0019 #include <cctype>
0020 #include <cstddef> // size_t
0021 #ifndef BOOST_NO_CWCHAR
0022 #include <cwchar>  // mbstate_t
0023 #endif
0024 #include <algorithm> // copy
0025 
0026 #include <boost/config.hpp>
0027 #if defined(BOOST_NO_STDC_NAMESPACE)
0028 namespace std{
0029     using ::mbstate_t;
0030 } // namespace std
0031 #endif
0032 #include <boost/assert.hpp>
0033 #include <boost/core/ignore_unused.hpp>
0034 #include <boost/array.hpp>
0035 #include <boost/iterator/iterator_adaptor.hpp>
0036 #include <boost/archive/detail/utf8_codecvt_facet.hpp>
0037 #include <boost/archive/iterators/dataflow_exception.hpp>
0038 #include <boost/serialization/throw_exception.hpp>
0039 
0040 #include <iostream>
0041 
0042 namespace boost {
0043 namespace archive {
0044 namespace iterators {
0045 
0046 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
0047 // class used by text archives to translate char strings to wchar_t
0048 // strings of the currently selected locale
0049 template<class Base>
0050 class wchar_from_mb
0051     : public boost::iterator_adaptor<
0052         wchar_from_mb<Base>,
0053         Base,
0054         wchar_t,
0055         single_pass_traversal_tag,
0056         wchar_t
0057     >
0058 {
0059     friend class boost::iterator_core_access;
0060     typedef typename boost::iterator_adaptor<
0061         wchar_from_mb<Base>,
0062         Base,
0063         wchar_t,
0064         single_pass_traversal_tag,
0065         wchar_t
0066     > super_t;
0067 
0068     typedef wchar_from_mb<Base> this_t;
0069 
0070     void drain();
0071 
0072     wchar_t dereference() const {
0073         if(m_output.m_next == m_output.m_next_available)
0074             return static_cast<wchar_t>(0);
0075         return * m_output.m_next;
0076     }
0077 
0078     void increment(){
0079         if(m_output.m_next == m_output.m_next_available)
0080             return;
0081         if(++m_output.m_next == m_output.m_next_available){
0082             if(m_input.m_done)
0083                 return;
0084             drain();
0085         }
0086     }
0087 
0088     bool equal(this_t const & rhs) const {
0089         return dereference() == rhs.dereference();
0090     }
0091 
0092     boost::archive::detail::utf8_codecvt_facet m_codecvt_facet;
0093     std::mbstate_t m_mbs;
0094 
0095     template<typename T>
0096     struct sliding_buffer {
0097         boost::array<T, 32> m_buffer;
0098         typename boost::array<T, 32>::const_iterator m_next_available;
0099         typename boost::array<T, 32>::iterator m_next;
0100         bool m_done;
0101         // default ctor
0102         sliding_buffer() :
0103             m_next_available(m_buffer.begin()),
0104             m_next(m_buffer.begin()),
0105             m_done(false)
0106         {}
0107         // copy ctor
0108         sliding_buffer(const sliding_buffer & rhs) :
0109             m_next_available(
0110                 std::copy(
0111                     rhs.m_buffer.begin(),
0112                     rhs.m_next_available,
0113                     m_buffer.begin()
0114                 )
0115             ),
0116             m_next(
0117                 m_buffer.begin() + (rhs.m_next - rhs.m_buffer.begin())
0118             ),
0119             m_done(rhs.m_done)
0120         {}
0121     };
0122 
0123     sliding_buffer<typename iterator_value<Base>::type> m_input;
0124     sliding_buffer<typename iterator_value<this_t>::type> m_output;
0125 
0126 public:
0127     // make composable by using templated constructor
0128     template<class T>
0129     wchar_from_mb(T start) :
0130         super_t(Base(static_cast< T >(start))),
0131         m_mbs(std::mbstate_t())
0132     {
0133         BOOST_ASSERT(std::mbsinit(&m_mbs));
0134         drain();
0135     }
0136     // default constructor used as an end iterator
0137     wchar_from_mb(){}
0138 
0139     // copy ctor
0140     wchar_from_mb(const wchar_from_mb & rhs) :
0141         super_t(rhs.base_reference()),
0142         m_mbs(rhs.m_mbs),
0143         m_input(rhs.m_input),
0144         m_output(rhs.m_output)
0145     {}
0146 };
0147 
0148 template<class Base>
0149 void wchar_from_mb<Base>::drain(){
0150     BOOST_ASSERT(! m_input.m_done);
0151     for(;;){
0152         typename boost::iterators::iterator_reference<Base>::type c = *(this->base_reference());
0153         // a null character in a multibyte stream is takes as end of string
0154         if(0 == c){
0155             m_input.m_done = true;
0156             break;
0157         }
0158         ++(this->base_reference());
0159         * const_cast<typename iterator_value<Base>::type *>(
0160             (m_input.m_next_available++)
0161         ) = c;
0162         // if input buffer is full - we're done for now
0163         if(m_input.m_buffer.end() == m_input.m_next_available)
0164             break;
0165     }
0166     const typename boost::iterators::iterator_value<Base>::type * input_new_start;
0167     typename iterator_value<this_t>::type * next_available;
0168 
0169     BOOST_ATTRIBUTE_UNUSED // redundant with ignore_unused below but clarifies intention
0170     std::codecvt_base::result r = m_codecvt_facet.in(
0171         m_mbs,
0172         m_input.m_buffer.begin(),
0173         m_input.m_next_available,
0174         input_new_start,
0175         m_output.m_buffer.begin(),
0176         m_output.m_buffer.end(),
0177         next_available
0178     );
0179     BOOST_ASSERT(std::codecvt_base::ok == r);
0180     m_output.m_next_available = next_available;
0181     m_output.m_next = m_output.m_buffer.begin();
0182 
0183     // we're done with some of the input so shift left.
0184     m_input.m_next_available = std::copy(
0185         input_new_start,
0186         m_input.m_next_available,
0187         m_input.m_buffer.begin()
0188     );
0189     m_input.m_next = m_input.m_buffer.begin();
0190 }
0191 
0192 } // namespace iterators
0193 } // namespace archive
0194 } // namespace boost
0195 
0196 #endif // BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP