]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/iostreams/test/detail/null_padded_codecvt.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / iostreams / test / detail / null_padded_codecvt.hpp
1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2 // (C) Copyright 2004-2007 Jonathan Turkanis
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
5
6 // See http://www.boost.org/libs/iostreams for documentation.
7
8 // Contains the definitions of two codecvt facets useful for testing code
9 // conversion. Both represent the "null padded" character encoding described as
10 // follows. A wide character can be represented by the encoding if its value V
11 // is within the range of an unsigned char. The first char of the sequence
12 // representing V is V % 3 + 1. This is followed by V % 3 null characters, and
13 // finally by V itself.
14
15 // The first codecvt facet, null_padded_codecvt, is statefull, with state_type
16 // equal to int.
17
18 // The second codecvt facet, stateless_null_padded_codecvt, is stateless. At
19 // each point in a conversion, no characters are consumed unless there is room
20 // in the output sequence to write an entire multibyte sequence.
21
22 #ifndef BOOST_IOSTREAMS_TEST_NULL_PADDED_CODECVT_HPP_INCLUDED
23 #define BOOST_IOSTREAMS_TEST_NULL_PADDED_CODECVT_HPP_INCLUDED
24
25 #include <boost/config.hpp> // NO_STDC_NAMESPACE
26 #include <boost/iostreams/detail/codecvt_helper.hpp>
27 #include <boost/iostreams/detail/config/wide_streams.hpp>
28 #include <cstddef> // mbstate_t.
29 #include <locale> // codecvt.
30 #include <boost/integer_traits.hpp> // const_max.
31
32 #ifdef BOOST_NO_STDC_NAMESPACE
33 namespace std { using ::mbstate_t; }
34 #endif
35
36 namespace boost { namespace iostreams { namespace test {
37
38 //------------------Definition of null_padded_codecvt_state-------------------//
39
40 class null_padded_codecvt_state {
41 public:
42 null_padded_codecvt_state(int val = 0) : val_(val) { }
43 operator int() const { return val_; }
44 int& val() { return val_; }
45 const int& val() const { return val_; }
46 private:
47 int val_;
48 };
49
50 } } }
51
52 BOOST_IOSTREAMS_CODECVT_SPEC(boost::iostreams::test::null_padded_codecvt_state)
53
54 namespace boost { namespace iostreams { namespace test {
55
56 //------------------Definition of null_padded_codevt--------------------------//
57
58 //
59 // state is initially 0. After a single character is consumed, state is set to
60 // the number of characters in the current multibyte sequence and decremented
61 // as each character is consumed until its value reaches 0 again.
62 //
63 class null_padded_codecvt
64 : public iostreams::detail::codecvt_helper<
65 wchar_t, char, null_padded_codecvt_state
66 >
67 {
68 public:
69 typedef null_padded_codecvt_state state_type;
70 private:
71 std::codecvt_base::result
72 do_in( state_type& state, const char* first1, const char* last1,
73 const char*& next1, wchar_t* first2, wchar_t* last2,
74 wchar_t*& next2 ) const
75 {
76 using namespace std;
77 if (state < 0 || state > 3)
78 return codecvt_base::error;
79 next1 = first1;
80 next2 = first2;
81 while (next2 != last2 && next1 != last1) {
82 while (next1 != last1) {
83 if (state == 0) {
84 if (*next1 < 1 || *next1 > 3)
85 return codecvt_base::error;
86 state = *next1++;
87 } else if (state == 1) {
88 *next2++ = (unsigned char) *next1++;
89 state = 0;
90 break;
91 } else {
92 if (*next1++ != 0)
93 return codecvt_base::error;
94 --state.val();
95 }
96 }
97 }
98 return next2 == last2 ?
99 codecvt_base::ok :
100 codecvt_base::partial;
101 }
102
103 std::codecvt_base::result
104 do_out( state_type& state, const wchar_t* first1, const wchar_t* last1,
105 const wchar_t*& next1, char* first2, char* last2,
106 char*& next2 ) const
107 {
108 using namespace std;
109 if (state < 0 || state > 3)
110 return codecvt_base::error;
111 next1 = first1;
112 next2 = first2;
113 while (next1 != last1 && next2 != last2) {
114 while (next2 != last2) {
115 if (state == 0) {
116 if (*next1 > integer_traits<unsigned char>::const_max)
117 return codecvt_base::noconv;
118 state = *next1 % 3 + 1;
119 *next2++ = static_cast<char>(state);
120 } else if (state == 1) {
121 state = 0;
122 *next2++ = static_cast<unsigned char>(*next1++);
123 break;
124 } else {
125 --state.val();
126 *next2++ = 0;
127 }
128 }
129 }
130 return next1 == last1 ?
131 codecvt_base::ok :
132 codecvt_base::partial;
133 }
134
135 std::codecvt_base::result
136 do_unshift( state_type& state,
137 char* /* first2 */,
138 char* last2,
139 char*& next2 ) const
140 {
141 using namespace std;
142 next2 = last2;
143 while (state.val()-- > 0)
144 if (next2 != last2)
145 *next2++ = 0;
146 else
147 return codecvt_base::partial;
148 return codecvt_base::ok;
149 }
150
151 bool do_always_noconv() const throw() { return false; }
152
153 int do_max_length() const throw() { return 4; }
154
155 int do_encoding() const throw() { return -1; }
156
157 int do_length( BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER state_type& state,
158 const char* first1, const char* last1,
159 std::size_t len2 ) const throw()
160 { // Implementation should follow that of do_in().
161 int st = state;
162 std::size_t result = 0;
163 const char* next1 = first1;
164 while (result < len2 && next1 != last1) {
165 while (next1 != last1) {
166 if (st == 0) {
167 if (*next1 < 1 || *next1 > 3)
168 return static_cast<int>(result); // error.
169 st = *next1++;
170 } else if (st == 1) {
171 ++result;
172 st = 0;
173 break;
174 } else {
175 if (*next1++ != 0)
176 return static_cast<int>(result); // error.
177 --st;
178 }
179 }
180 }
181 return static_cast<int>(result);
182 }
183 };
184
185 //------------------Definition of stateless_null_padded_codevt----------------//
186
187 class stateless_null_padded_codecvt
188 : public std::codecvt<wchar_t, char, std::mbstate_t>
189 {
190 std::codecvt_base::result
191 do_in( state_type&, const char* first1, const char* last1,
192 const char*& next1, wchar_t* first2, wchar_t* last2,
193 wchar_t*& next2 ) const
194 {
195 using namespace std;
196 for ( next1 = first1, next2 = first2;
197 next1 != last1 && next2 != last2; )
198 {
199 int len = (unsigned char) *next1;
200 if (len < 1 || len > 3)
201 return codecvt_base::error;
202 if (last1 - next1 < len + 1)
203 return codecvt_base::partial;
204 ++next1;
205 while (len-- > 1)
206 if (*next1++ != 0)
207 return codecvt_base::error;
208 *next2++ = (unsigned char) *next1++;
209 }
210 return next1 == last1 && next2 == last2 ?
211 codecvt_base::ok :
212 codecvt_base::partial;
213 }
214
215 std::codecvt_base::result
216 do_out( state_type&, const wchar_t* first1, const wchar_t* last1,
217 const wchar_t*& next1, char* first2, char* last2,
218 char*& next2 ) const
219 {
220 using namespace std;
221 for ( next1 = first1, next2 = first2;
222 next1 != last1 && next2 != last2; )
223 {
224 if (*next1 > integer_traits<unsigned char>::const_max)
225 return codecvt_base::noconv;
226 int skip = *next1 % 3 + 2;
227 if (last2 - next2 < skip)
228 return codecvt_base::partial;
229 *next2++ = static_cast<char>(--skip);
230 while (skip-- > 1)
231 *next2++ = 0;
232 *next2++ = (unsigned char) *next1++;
233 }
234 return codecvt_base::ok;
235 }
236
237 std::codecvt_base::result
238 do_unshift( state_type&,
239 char* /* first2 */,
240 char* /* last2 */,
241 char*& /* next2 */ ) const
242 {
243 return std::codecvt_base::ok;
244 }
245
246 bool do_always_noconv() const throw() { return false; }
247
248 int do_max_length() const throw() { return 4; }
249
250 int do_encoding() const throw() { return -1; }
251
252 int do_length( BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER state_type&,
253 const char* first1, const char* last1,
254 std::size_t len2 ) const throw()
255 { // Implementation should follow that of do_in().
256 std::size_t result = 0;
257 for ( const char* next1 = first1;
258 next1 != last1 && result < len2; ++result)
259 {
260 int len = (unsigned char) *next1;
261 if (len < 1 || len > 3 || last1 - next1 < len + 1)
262 return static_cast<int>(result); // error.
263 ++next1;
264 while (len-- > 1)
265 if (*next1++ != 0)
266 return static_cast<int>(result); // error.
267 ++next1;
268 }
269 return static_cast<int>(result);
270 }
271 };
272
273 } } } // End namespaces detail, iostreams, boost.
274
275 #endif // #ifndef BOOST_IOSTREAMS_TEST_NULL_PADDED_CODECVT_HPP_INCLUDED