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
0005 #if defined(_MSC_VER)
0006 # pragma once
0007 #endif
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
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 }
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
0047
0048
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
0102 sliding_buffer() :
0103 m_next_available(m_buffer.begin()),
0104 m_next(m_buffer.begin()),
0105 m_done(false)
0106 {}
0107
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
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
0137 wchar_from_mb(){}
0138
0139
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
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
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
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
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 }
0193 }
0194 }
0195
0196 #endif