]>
Commit | Line | Data |
---|---|---|
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 | #include <cwchar> // mbstate_t | |
23 | #include <algorithm> // copy | |
24 | ||
25 | #include <boost/config.hpp> | |
26 | #if defined(BOOST_NO_STDC_NAMESPACE) | |
27 | namespace std{ | |
28 | using ::mbstate_t; | |
29 | } // namespace std | |
30 | #endif | |
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> | |
36 | ||
37 | #include <iostream> | |
38 | ||
39 | namespace boost { | |
40 | namespace archive { | |
41 | namespace iterators { | |
42 | ||
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 | |
46 | template<class Base> | |
47 | class wchar_from_mb | |
48 | : public boost::iterator_adaptor< | |
49 | wchar_from_mb<Base>, | |
50 | Base, | |
51 | wchar_t, | |
52 | single_pass_traversal_tag, | |
53 | wchar_t | |
54 | > | |
55 | { | |
56 | friend class boost::iterator_core_access; | |
57 | typedef typename boost::iterator_adaptor< | |
58 | wchar_from_mb<Base>, | |
59 | Base, | |
60 | wchar_t, | |
61 | single_pass_traversal_tag, | |
62 | wchar_t | |
63 | > super_t; | |
64 | ||
65 | typedef wchar_from_mb<Base> this_t; | |
66 | ||
67 | void drain(); | |
68 | ||
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; | |
73 | } | |
74 | ||
75 | void increment(){ | |
76 | if(m_output.m_next == m_output.m_next_available) | |
77 | return; | |
78 | if(++m_output.m_next == m_output.m_next_available){ | |
79 | if(m_input.m_done) | |
80 | return; | |
81 | drain(); | |
82 | } | |
83 | } | |
84 | ||
85 | bool equal(this_t const & rhs) const { | |
86 | return dereference() == rhs.dereference(); | |
87 | } | |
88 | ||
89 | boost::archive::detail::utf8_codecvt_facet m_codecvt_facet; | |
90 | std::mbstate_t m_mbs; | |
91 | ||
92 | template<typename T> | |
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; | |
97 | bool m_done; | |
98 | // default ctor | |
99 | sliding_buffer() : | |
100 | m_next_available(m_buffer.begin()), | |
101 | m_next(m_buffer.begin()), | |
102 | m_done(false) | |
103 | {} | |
104 | // copy ctor | |
105 | sliding_buffer(const sliding_buffer & rhs) : | |
106 | m_next_available( | |
107 | std::copy( | |
108 | rhs.m_buffer.begin(), | |
109 | rhs.m_next_available, | |
110 | m_buffer.begin() | |
111 | ) | |
112 | ), | |
113 | m_next( | |
114 | m_buffer.begin() + (rhs.m_next - rhs.m_buffer.begin()) | |
115 | ), | |
116 | m_done(rhs.m_done) | |
117 | {} | |
118 | }; | |
119 | ||
120 | sliding_buffer<typename iterator_value<Base>::type> m_input; | |
121 | sliding_buffer<typename iterator_value<this_t>::type> m_output; | |
122 | ||
123 | public: | |
124 | // make composible buy using templated constructor | |
125 | template<class T> | |
126 | wchar_from_mb(T start) : | |
127 | super_t(Base(static_cast< T >(start))), | |
128 | m_mbs(std::mbstate_t()) | |
129 | { | |
130 | BOOST_ASSERT(std::mbsinit(&m_mbs)); | |
131 | drain(); | |
132 | } | |
133 | // default constructor used as an end iterator | |
134 | wchar_from_mb(){} | |
135 | ||
136 | // copy ctor | |
137 | wchar_from_mb(const wchar_from_mb & rhs) : | |
138 | super_t(rhs.base_reference()), | |
139 | m_mbs(rhs.m_mbs), | |
140 | m_input(rhs.m_input), | |
141 | m_output(rhs.m_output) | |
142 | {} | |
143 | }; | |
144 | ||
145 | template<class Base> | |
146 | void wchar_from_mb<Base>::drain(){ | |
147 | BOOST_ASSERT(! m_input.m_done); | |
148 | for(;;){ | |
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 | |
151 | if(0 == c){ | |
152 | m_input.m_done = true; | |
153 | break; | |
154 | } | |
155 | ++(this->base_reference()); | |
156 | * const_cast<typename iterator_value<Base>::type *>( | |
157 | (m_input.m_next_available++) | |
158 | ) = c; | |
159 | // if input buffer is full - we're done for now | |
160 | if(m_input.m_buffer.end() == m_input.m_next_available) | |
161 | break; | |
162 | } | |
163 | const typename boost::iterators::iterator_value<Base>::type * input_new_start; | |
164 | typename iterator_value<this_t>::type * next_available; | |
165 | ||
166 | std::codecvt_base::result r = m_codecvt_facet.in( | |
167 | m_mbs, | |
168 | m_input.m_buffer.begin(), | |
169 | m_input.m_next_available, | |
170 | input_new_start, | |
171 | m_output.m_buffer.begin(), | |
172 | m_output.m_buffer.end(), | |
173 | next_available | |
174 | ); | |
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(); | |
178 | ||
179 | // we're done with some of the input so shift left. | |
180 | m_input.m_next_available = std::copy( | |
181 | input_new_start, | |
182 | m_input.m_next_available, | |
183 | m_input.m_buffer.begin() | |
184 | ); | |
185 | m_input.m_next = m_input.m_buffer.begin(); | |
186 | } | |
187 | ||
188 | } // namespace iterators | |
189 | } // namespace archive | |
190 | } // namespace boost | |
191 | ||
192 | #endif // BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP |