1 #ifndef BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP
2 #define BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP
4 // MS compatible compilers support #pragma once
9 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
12 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
13 // Use, modification and distribution is subject to the Boost Software
14 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
15 // http://www.boost.org/LICENSE_1_0.txt)
17 // See http://www.boost.org for updates, documentation, and revision history.
19 #include <boost/assert.hpp>
21 #include <cstddef> // size_t
22 #include <cwchar> // mbstate_t
23 #include <algorithm> // copy
25 #include <boost/config.hpp>
26 #if defined(BOOST_NO_STDC_NAMESPACE)
31 #include <boost/array.hpp>
32 #include <boost/iterator/iterator_adaptor.hpp>
33 #include <boost/archive/detail/utf8_codecvt_facet.hpp>
34 #include <boost/archive/iterators/dataflow_exception.hpp>
35 #include <boost/serialization/throw_exception.hpp>
43 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
44 // class used by text archives to translate char strings to wchar_t
45 // strings of the currently selected locale
48 : public boost::iterator_adaptor<
52 single_pass_traversal_tag,
56 friend class boost::iterator_core_access;
57 typedef typename boost::iterator_adaptor<
61 single_pass_traversal_tag,
65 typedef wchar_from_mb<Base> this_t;
69 wchar_t dereference() const {
70 if(m_output.m_next == m_output.m_next_available)
71 return static_cast<wchar_t>(0);
72 return * m_output.m_next;
76 if(m_output.m_next == m_output.m_next_available)
78 if(++m_output.m_next == m_output.m_next_available){
85 bool equal(this_t const & rhs) const {
86 return dereference() == rhs.dereference();
89 boost::archive::detail::utf8_codecvt_facet m_codecvt_facet;
93 struct sliding_buffer {
94 boost::array<T, 32> m_buffer;
95 typename boost::array<T, 32>::const_iterator m_next_available;
96 typename boost::array<T, 32>::iterator m_next;
100 m_next_available(m_buffer.begin()),
101 m_next(m_buffer.begin()),
105 sliding_buffer(const sliding_buffer & rhs) :
108 rhs.m_buffer.begin(),
109 rhs.m_next_available,
114 m_buffer.begin() + (rhs.m_next - rhs.m_buffer.begin())
120 sliding_buffer<typename iterator_value<Base>::type> m_input;
121 sliding_buffer<typename iterator_value<this_t>::type> m_output;
124 // make composible buy using templated constructor
126 wchar_from_mb(T start) :
127 super_t(Base(static_cast< T >(start))),
128 m_mbs(std::mbstate_t())
130 BOOST_ASSERT(std::mbsinit(&m_mbs));
133 // default constructor used as an end iterator
137 wchar_from_mb(const wchar_from_mb & rhs) :
138 super_t(rhs.base_reference()),
140 m_input(rhs.m_input),
141 m_output(rhs.m_output)
146 void wchar_from_mb<Base>::drain(){
147 BOOST_ASSERT(! m_input.m_done);
149 typename boost::iterators::iterator_reference<Base>::type c = *(this->base_reference());
150 // a null character in a multibyte stream is takes as end of string
152 m_input.m_done = true;
155 ++(this->base_reference());
156 * const_cast<typename iterator_value<Base>::type *>(
157 (m_input.m_next_available++)
159 // if input buffer is full - we're done for now
160 if(m_input.m_buffer.end() == m_input.m_next_available)
163 const typename boost::iterators::iterator_value<Base>::type * input_new_start;
164 typename iterator_value<this_t>::type * next_available;
166 std::codecvt_base::result r = m_codecvt_facet.in(
168 m_input.m_buffer.begin(),
169 m_input.m_next_available,
171 m_output.m_buffer.begin(),
172 m_output.m_buffer.end(),
175 BOOST_ASSERT(std::codecvt_base::ok == r);
176 m_output.m_next_available = next_available;
177 m_output.m_next = m_output.m_buffer.begin();
179 // we're done with some of the input so shift left.
180 m_input.m_next_available = std::copy(
182 m_input.m_next_available,
183 m_input.m_buffer.begin()
185 m_input.m_next = m_input.m_buffer.begin();
188 } // namespace iterators
189 } // namespace archive
192 #endif // BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP