]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/config/locale/generic/codecvt_members.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / config / locale / generic / codecvt_members.cc
CommitLineData
a314f26a 1// std::codecvt implementation details, generic version -*- C++ -*-
2
fbd26352 3// Copyright (C) 2002-2019 Free Software Foundation, Inc.
a314f26a 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
6bc9506f 8// Free Software Foundation; either version 3, or (at your option)
a314f26a 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
6bc9506f 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/>.
a314f26a 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>
b83f6bce 32#include <cstdlib> // For MB_CUR_MAX
33#include <climits> // For MB_LEN_MAX
c7599825 34#include <cstring>
a314f26a 35
2948dd21 36namespace std _GLIBCXX_VISIBILITY(default)
37{
38_GLIBCXX_BEGIN_NAMESPACE_VERSION
1069247d 39
a314f26a 40 // Specializations.
5a64d8cf 41#ifdef _GLIBCXX_USE_WCHAR_T
a314f26a 42 codecvt_base::result
43 codecvt<wchar_t, char, mbstate_t>::
33b7ef52 44 do_out(state_type& __state, const intern_type* __from,
a314f26a 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 {
4229b2e4 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
4229b2e4 52 state_type __tmp_state(__state);
d08559a9 53
4229b2e4 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.
d08559a9 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
a314f26a 76 {
d08559a9 77 extern_type __buf[MB_LEN_MAX];
78 while (__from < __from_end && __to < __to_end)
4229b2e4 79 {
d08559a9 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 }
33b7ef52 91
d08559a9 92 memcpy(__to, __buf, __conv);
93 __state = __tmp_state;
94 __to += __conv;
95 __from++;
4229b2e4 96 }
a314f26a 97 }
4229b2e4 98
99 if (__ret == ok && __from < __from_end)
100 __ret = partial;
101
102 __from_next = __from;
103 __to_next = __to;
33b7ef52 104 return __ret;
a314f26a 105 }
33b7ef52 106
a314f26a 107 codecvt_base::result
108 codecvt<wchar_t, char, mbstate_t>::
33b7ef52 109 do_in(state_type& __state, const extern_type* __from,
a314f26a 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 {
4229b2e4 114 result __ret = ok;
e13b1b3e 115 // This temporary state object is necessary so __state won't be modified
4229b2e4 116 // if [__from, __from_end) is a partial multibyte character.
117 state_type __tmp_state(__state);
a314f26a 118
4229b2e4 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)
a314f26a 123 {
4229b2e4 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;
a314f26a 147 }
4229b2e4 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;
33b7ef52 156 return __ret;
4229b2e4 157 }
158
33b7ef52 159 int
4229b2e4 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;
33b7ef52 169 }
4229b2e4 170
33b7ef52 171 int
4229b2e4 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 }
33b7ef52 179
180 int
4229b2e4 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)
a314f26a 189 {
9c371452 190 size_t __conv = mbrtowc(0, __from, __end - __from, &__tmp_state);
4229b2e4 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--;
a314f26a 212 }
4229b2e4 213
33b7ef52 214 return __ret;
a314f26a 215 }
216#endif
1069247d 217
2948dd21 218_GLIBCXX_END_NAMESPACE_VERSION
219} // namespace