]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/archive/iterators/wchar_from_mb.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / archive / iterators / wchar_from_mb.hpp
1 #ifndef BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP
2 #define BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP
3
4 // MS compatible compilers support #pragma once
5 #if defined(_MSC_VER)
6 # pragma once
7 #endif
8
9 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
10 // wchar_from_mb.hpp
11
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)
16
17 // See http://www.boost.org for updates, documentation, and revision history.
18
19 #include <boost/assert.hpp>
20 #include <cctype>
21 #include <cstddef> // size_t
22 #ifndef BOOST_NO_CWCHAR
23 #include <cwchar> // mbstate_t
24 #endif
25 #include <algorithm> // copy
26
27 #include <boost/config.hpp>
28 #if defined(BOOST_NO_STDC_NAMESPACE)
29 namespace std{
30 using ::mbstate_t;
31 } // namespace std
32 #endif
33 #include <boost/array.hpp>
34 #include <boost/iterator/iterator_adaptor.hpp>
35 #include <boost/archive/detail/utf8_codecvt_facet.hpp>
36 #include <boost/archive/iterators/dataflow_exception.hpp>
37 #include <boost/serialization/throw_exception.hpp>
38
39 #include <iostream>
40
41 namespace boost {
42 namespace archive {
43 namespace iterators {
44
45 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
46 // class used by text archives to translate char strings to wchar_t
47 // strings of the currently selected locale
48 template<class Base>
49 class wchar_from_mb
50 : public boost::iterator_adaptor<
51 wchar_from_mb<Base>,
52 Base,
53 wchar_t,
54 single_pass_traversal_tag,
55 wchar_t
56 >
57 {
58 friend class boost::iterator_core_access;
59 typedef typename boost::iterator_adaptor<
60 wchar_from_mb<Base>,
61 Base,
62 wchar_t,
63 single_pass_traversal_tag,
64 wchar_t
65 > super_t;
66
67 typedef wchar_from_mb<Base> this_t;
68
69 void drain();
70
71 wchar_t dereference() const {
72 if(m_output.m_next == m_output.m_next_available)
73 return static_cast<wchar_t>(0);
74 return * m_output.m_next;
75 }
76
77 void increment(){
78 if(m_output.m_next == m_output.m_next_available)
79 return;
80 if(++m_output.m_next == m_output.m_next_available){
81 if(m_input.m_done)
82 return;
83 drain();
84 }
85 }
86
87 bool equal(this_t const & rhs) const {
88 return dereference() == rhs.dereference();
89 }
90
91 boost::archive::detail::utf8_codecvt_facet m_codecvt_facet;
92 std::mbstate_t m_mbs;
93
94 template<typename T>
95 struct sliding_buffer {
96 boost::array<T, 32> m_buffer;
97 typename boost::array<T, 32>::const_iterator m_next_available;
98 typename boost::array<T, 32>::iterator m_next;
99 bool m_done;
100 // default ctor
101 sliding_buffer() :
102 m_next_available(m_buffer.begin()),
103 m_next(m_buffer.begin()),
104 m_done(false)
105 {}
106 // copy ctor
107 sliding_buffer(const sliding_buffer & rhs) :
108 m_next_available(
109 std::copy(
110 rhs.m_buffer.begin(),
111 rhs.m_next_available,
112 m_buffer.begin()
113 )
114 ),
115 m_next(
116 m_buffer.begin() + (rhs.m_next - rhs.m_buffer.begin())
117 ),
118 m_done(rhs.m_done)
119 {}
120 };
121
122 sliding_buffer<typename iterator_value<Base>::type> m_input;
123 sliding_buffer<typename iterator_value<this_t>::type> m_output;
124
125 public:
126 // make composible buy using templated constructor
127 template<class T>
128 wchar_from_mb(T start) :
129 super_t(Base(static_cast< T >(start))),
130 m_mbs(std::mbstate_t())
131 {
132 BOOST_ASSERT(std::mbsinit(&m_mbs));
133 drain();
134 }
135 // default constructor used as an end iterator
136 wchar_from_mb(){}
137
138 // copy ctor
139 wchar_from_mb(const wchar_from_mb & rhs) :
140 super_t(rhs.base_reference()),
141 m_mbs(rhs.m_mbs),
142 m_input(rhs.m_input),
143 m_output(rhs.m_output)
144 {}
145 };
146
147 template<class Base>
148 void wchar_from_mb<Base>::drain(){
149 BOOST_ASSERT(! m_input.m_done);
150 for(;;){
151 typename boost::iterators::iterator_reference<Base>::type c = *(this->base_reference());
152 // a null character in a multibyte stream is takes as end of string
153 if(0 == c){
154 m_input.m_done = true;
155 break;
156 }
157 ++(this->base_reference());
158 * const_cast<typename iterator_value<Base>::type *>(
159 (m_input.m_next_available++)
160 ) = c;
161 // if input buffer is full - we're done for now
162 if(m_input.m_buffer.end() == m_input.m_next_available)
163 break;
164 }
165 const typename boost::iterators::iterator_value<Base>::type * input_new_start;
166 typename iterator_value<this_t>::type * next_available;
167
168 std::codecvt_base::result r = m_codecvt_facet.in(
169 m_mbs,
170 m_input.m_buffer.begin(),
171 m_input.m_next_available,
172 input_new_start,
173 m_output.m_buffer.begin(),
174 m_output.m_buffer.end(),
175 next_available
176 );
177 BOOST_ASSERT(std::codecvt_base::ok == r);
178 m_output.m_next_available = next_available;
179 m_output.m_next = m_output.m_buffer.begin();
180
181 // we're done with some of the input so shift left.
182 m_input.m_next_available = std::copy(
183 input_new_start,
184 m_input.m_next_available,
185 m_input.m_buffer.begin()
186 );
187 m_input.m_next = m_input.m_buffer.begin();
188 }
189
190 } // namespace iterators
191 } // namespace archive
192 } // namespace boost
193
194 #endif // BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP