]>
Commit | Line | Data |
---|---|---|
38cca750 BK |
1 | // std::codecvt implementation details, generic version -*- C++ -*- |
2 | ||
a5544970 | 3 | // Copyright (C) 2002-2019 Free Software Foundation, Inc. |
38cca750 BK |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
748086b7 | 8 | // Free Software Foundation; either version 3, or (at your option) |
38cca750 BK |
9 | // any later version. |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
748086b7 JJ |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | // You should have received a copy of the GNU General Public License and | |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
38cca750 BK |
24 | |
25 | // | |
26 | // ISO C++ 14882: 22.2.1.5 - Template class codecvt | |
27 | // | |
28 | ||
29 | // Written by Benjamin Kosnik <bkoz@redhat.com> | |
30 | ||
31 | #include <locale> | |
f56fe8ff PC |
32 | #include <cstdlib> // For MB_CUR_MAX |
33 | #include <climits> // For MB_LEN_MAX | |
538075fe | 34 | #include <cstring> |
38cca750 | 35 | |
12ffa228 BK |
36 | namespace std _GLIBCXX_VISIBILITY(default) |
37 | { | |
38 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
3cbc7af0 | 39 | |
38cca750 | 40 | // Specializations. |
3d7c150e | 41 | #ifdef _GLIBCXX_USE_WCHAR_T |
38cca750 BK |
42 | codecvt_base::result |
43 | codecvt<wchar_t, char, mbstate_t>:: | |
f92ab29f | 44 | do_out(state_type& __state, const intern_type* __from, |
38cca750 BK |
45 | const intern_type* __from_end, const intern_type*& __from_next, |
46 | extern_type* __to, extern_type* __to_end, | |
47 | extern_type*& __to_next) const | |
48 | { | |
e61c8e23 BK |
49 | result __ret = ok; |
50 | // The conversion must be done using a temporary destination buffer | |
51 | // since it is not possible to pass the size of the buffer to wcrtomb | |
e61c8e23 | 52 | state_type __tmp_state(__state); |
1f33554a | 53 | |
e61c8e23 BK |
54 | // The conversion must be done by calling wcrtomb in a loop rather |
55 | // than using wcsrtombs because wcsrtombs assumes that the input is | |
56 | // zero-terminated. | |
1f33554a PC |
57 | |
58 | // Either we can upper bound the total number of external characters to | |
59 | // something smaller than __to_end - __to or the conversion must be done | |
60 | // using a temporary destination buffer since it is not possible to | |
61 | // pass the size of the buffer to wcrtomb | |
62 | if (MB_CUR_MAX * (__from_end - __from) - (__to_end - __to) <= 0) | |
63 | while (__from < __from_end) | |
64 | { | |
65 | const size_t __conv = wcrtomb(__to, *__from, &__tmp_state); | |
66 | if (__conv == static_cast<size_t>(-1)) | |
67 | { | |
68 | __ret = error; | |
69 | break; | |
70 | } | |
71 | __state = __tmp_state; | |
72 | __to += __conv; | |
73 | __from++; | |
74 | } | |
75 | else | |
38cca750 | 76 | { |
1f33554a PC |
77 | extern_type __buf[MB_LEN_MAX]; |
78 | while (__from < __from_end && __to < __to_end) | |
e61c8e23 | 79 | { |
1f33554a PC |
80 | const size_t __conv = wcrtomb(__buf, *__from, &__tmp_state); |
81 | if (__conv == static_cast<size_t>(-1)) | |
82 | { | |
83 | __ret = error; | |
84 | break; | |
85 | } | |
86 | else if (__conv > static_cast<size_t>(__to_end - __to)) | |
87 | { | |
88 | __ret = partial; | |
89 | break; | |
90 | } | |
f92ab29f | 91 | |
1f33554a PC |
92 | memcpy(__to, __buf, __conv); |
93 | __state = __tmp_state; | |
94 | __to += __conv; | |
95 | __from++; | |
e61c8e23 | 96 | } |
38cca750 | 97 | } |
e61c8e23 BK |
98 | |
99 | if (__ret == ok && __from < __from_end) | |
100 | __ret = partial; | |
101 | ||
102 | __from_next = __from; | |
103 | __to_next = __to; | |
f92ab29f | 104 | return __ret; |
38cca750 | 105 | } |
f92ab29f | 106 | |
38cca750 BK |
107 | codecvt_base::result |
108 | codecvt<wchar_t, char, mbstate_t>:: | |
f92ab29f | 109 | do_in(state_type& __state, const extern_type* __from, |
38cca750 BK |
110 | const extern_type* __from_end, const extern_type*& __from_next, |
111 | intern_type* __to, intern_type* __to_end, | |
112 | intern_type*& __to_next) const | |
113 | { | |
e61c8e23 | 114 | result __ret = ok; |
1d77bc54 | 115 | // This temporary state object is necessary so __state won't be modified |
e61c8e23 BK |
116 | // if [__from, __from_end) is a partial multibyte character. |
117 | state_type __tmp_state(__state); | |
38cca750 | 118 | |
e61c8e23 BK |
119 | // Conversion must be done by calling mbrtowc in a loop rather than |
120 | // by calling mbsrtowcs because mbsrtowcs assumes that the input | |
121 | // sequence is zero-terminated. | |
122 | while (__from < __from_end && __to < __to_end) | |
38cca750 | 123 | { |
e61c8e23 BK |
124 | size_t __conv = mbrtowc(__to, __from, __from_end - __from, |
125 | &__tmp_state); | |
126 | if (__conv == static_cast<size_t>(-1)) | |
127 | { | |
128 | __ret = error; | |
129 | break; | |
130 | } | |
131 | else if (__conv == static_cast<size_t>(-2)) | |
132 | { | |
133 | // It is unclear what to return in this case (see DR 382). | |
134 | __ret = partial; | |
135 | break; | |
136 | } | |
137 | else if (__conv == 0) | |
138 | { | |
139 | // XXX Probably wrong for stateful encodings | |
140 | __conv = 1; | |
141 | *__to = L'\0'; | |
142 | } | |
143 | ||
144 | __state = __tmp_state; | |
145 | __to++; | |
146 | __from += __conv; | |
38cca750 | 147 | } |
e61c8e23 BK |
148 | |
149 | // It is not clear that __from < __from_end implies __ret != ok | |
150 | // (see DR 382). | |
151 | if (__ret == ok && __from < __from_end) | |
152 | __ret = partial; | |
153 | ||
154 | __from_next = __from; | |
155 | __to_next = __to; | |
f92ab29f | 156 | return __ret; |
e61c8e23 BK |
157 | } |
158 | ||
f92ab29f | 159 | int |
e61c8e23 BK |
160 | codecvt<wchar_t, char, mbstate_t>:: |
161 | do_encoding() const throw() | |
162 | { | |
163 | // XXX This implementation assumes that the encoding is | |
164 | // stateless and is either single-byte or variable-width. | |
165 | int __ret = 0; | |
166 | if (MB_CUR_MAX == 1) | |
167 | __ret = 1; | |
168 | return __ret; | |
f92ab29f | 169 | } |
e61c8e23 | 170 | |
f92ab29f | 171 | int |
e61c8e23 BK |
172 | codecvt<wchar_t, char, mbstate_t>:: |
173 | do_max_length() const throw() | |
174 | { | |
175 | // XXX Probably wrong for stateful encodings. | |
176 | int __ret = MB_CUR_MAX; | |
177 | return __ret; | |
178 | } | |
f92ab29f CG |
179 | |
180 | int | |
e61c8e23 BK |
181 | codecvt<wchar_t, char, mbstate_t>:: |
182 | do_length(state_type& __state, const extern_type* __from, | |
183 | const extern_type* __end, size_t __max) const | |
184 | { | |
185 | int __ret = 0; | |
186 | state_type __tmp_state(__state); | |
187 | ||
188 | while (__from < __end && __max) | |
38cca750 | 189 | { |
445877a9 | 190 | size_t __conv = mbrtowc(0, __from, __end - __from, &__tmp_state); |
e61c8e23 BK |
191 | if (__conv == static_cast<size_t>(-1)) |
192 | { | |
193 | // Invalid source character | |
194 | break; | |
195 | } | |
196 | else if (__conv == static_cast<size_t>(-2)) | |
197 | { | |
198 | // Remainder of input does not form a complete destination | |
199 | // character. | |
200 | break; | |
201 | } | |
202 | else if (__conv == 0) | |
203 | { | |
204 | // XXX Probably wrong for stateful encodings | |
205 | __conv = 1; | |
206 | } | |
207 | ||
208 | __state = __tmp_state; | |
209 | __from += __conv; | |
210 | __ret += __conv; | |
211 | __max--; | |
38cca750 | 212 | } |
e61c8e23 | 213 | |
f92ab29f | 214 | return __ret; |
38cca750 BK |
215 | } |
216 | #endif | |
3cbc7af0 | 217 | |
12ffa228 BK |
218 | _GLIBCXX_END_NAMESPACE_VERSION |
219 | } // namespace |