OSDN Git Service

2007-02-18 Paolo Carlini <pcarlini@suse.de>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / config / locale / generic / codecvt_members.cc
1 // std::codecvt implementation details, generic version -*- C++ -*-
2
3 // Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
4 // Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library.  This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 2, or (at your option)
10 // any later version.
11
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING.  If not, write to the Free
19 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 // USA.
21
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction.  Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License.  This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
30
31 //
32 // ISO C++ 14882: 22.2.1.5 - Template class codecvt
33 //
34
35 // Written by Benjamin Kosnik <bkoz@redhat.com>
36
37 #include <locale>
38 #include <cstdlib>  // For MB_CUR_MAX
39 #include <climits>  // For MB_LEN_MAX
40
41 _GLIBCXX_BEGIN_NAMESPACE(std)
42
43   // Specializations.
44 #ifdef _GLIBCXX_USE_WCHAR_T
45   codecvt_base::result
46   codecvt<wchar_t, char, mbstate_t>::
47   do_out(state_type& __state, const intern_type* __from, 
48          const intern_type* __from_end, const intern_type*& __from_next,
49          extern_type* __to, extern_type* __to_end,
50          extern_type*& __to_next) const
51   {
52     result __ret = ok;
53     // The conversion must be done using a temporary destination buffer
54     // since it is not possible to pass the size of the buffer to wcrtomb
55     state_type __tmp_state(__state);
56
57     // The conversion must be done by calling wcrtomb in a loop rather
58     // than using wcsrtombs because wcsrtombs assumes that the input is
59     // zero-terminated.
60
61     // Either we can upper bound the total number of external characters to
62     // something smaller than __to_end - __to or the conversion must be done
63     // using a temporary destination buffer since it is not possible to
64     // pass the size of the buffer to wcrtomb
65     if (MB_CUR_MAX * (__from_end - __from) - (__to_end - __to) <= 0)
66       while (__from < __from_end)
67         {
68           const size_t __conv = wcrtomb(__to, *__from, &__tmp_state);
69           if (__conv == static_cast<size_t>(-1))
70             {
71               __ret = error;
72               break;
73             }
74           __state = __tmp_state;
75           __to += __conv;
76           __from++;
77         }
78     else
79       {
80         extern_type __buf[MB_LEN_MAX];
81         while (__from < __from_end && __to < __to_end)
82           {
83             const size_t __conv = wcrtomb(__buf, *__from, &__tmp_state);
84             if (__conv == static_cast<size_t>(-1))
85               {
86                 __ret = error;
87                 break;
88               }
89             else if (__conv > static_cast<size_t>(__to_end - __to))
90               {
91                 __ret = partial;
92                 break;
93               }
94             
95             memcpy(__to, __buf, __conv);
96             __state = __tmp_state;
97             __to += __conv;
98             __from++;
99           }
100       }
101
102     if (__ret == ok && __from < __from_end)
103       __ret = partial;
104
105     __from_next = __from;
106     __to_next = __to;
107     return __ret; 
108   }
109   
110   codecvt_base::result
111   codecvt<wchar_t, char, mbstate_t>::
112   do_in(state_type& __state, const extern_type* __from, 
113         const extern_type* __from_end, const extern_type*& __from_next,
114         intern_type* __to, intern_type* __to_end,
115         intern_type*& __to_next) const
116   {
117     result __ret = ok;
118     // This temporary state object is neccessary so __state won't be modified
119     // if [__from, __from_end) is a partial multibyte character.
120     state_type __tmp_state(__state);
121
122     // Conversion must be done by calling mbrtowc in a loop rather than
123     // by calling mbsrtowcs because mbsrtowcs assumes that the input
124     // sequence is zero-terminated.
125     while (__from < __from_end && __to < __to_end)
126       {
127         size_t __conv = mbrtowc(__to, __from, __from_end - __from,
128                                 &__tmp_state);
129         if (__conv == static_cast<size_t>(-1))
130           {
131             __ret = error;
132             break;
133           }
134         else if (__conv == static_cast<size_t>(-2))
135           {
136             // It is unclear what to return in this case (see DR 382).
137             __ret = partial;
138             break;
139           }
140         else if (__conv == 0)
141           {
142             // XXX Probably wrong for stateful encodings
143             __conv = 1;
144             *__to = L'\0';
145           }
146
147         __state = __tmp_state;
148         __to++;
149         __from += __conv;
150       }
151
152     // It is not clear that __from < __from_end implies __ret != ok
153     // (see DR 382).
154     if (__ret == ok && __from < __from_end)
155       __ret = partial;
156
157     __from_next = __from;
158     __to_next = __to;
159     return __ret; 
160   }
161
162   int 
163   codecvt<wchar_t, char, mbstate_t>::
164   do_encoding() const throw()
165   {
166     // XXX This implementation assumes that the encoding is
167     // stateless and is either single-byte or variable-width.
168     int __ret = 0;
169     if (MB_CUR_MAX == 1)
170       __ret = 1;
171     return __ret;
172   }  
173
174   int 
175   codecvt<wchar_t, char, mbstate_t>::
176   do_max_length() const throw()
177   {
178     // XXX Probably wrong for stateful encodings.
179     int __ret = MB_CUR_MAX;
180     return __ret;
181   }
182   
183   int 
184   codecvt<wchar_t, char, mbstate_t>::
185   do_length(state_type& __state, const extern_type* __from,
186             const extern_type* __end, size_t __max) const
187   {
188     int __ret = 0;
189     state_type __tmp_state(__state);
190
191     while (__from < __end && __max)
192       {
193         size_t __conv = mbrtowc(NULL, __from, __end - __from, &__tmp_state);
194         if (__conv == static_cast<size_t>(-1))
195           {
196             // Invalid source character
197             break;
198           }
199         else if (__conv == static_cast<size_t>(-2))
200           {
201             // Remainder of input does not form a complete destination
202             // character.
203             break;
204           }
205         else if (__conv == 0)
206           {
207             // XXX Probably wrong for stateful encodings
208             __conv = 1;
209           }
210
211         __state = __tmp_state;
212         __from += __conv;
213         __ret += __conv;
214         __max--;
215       }
216
217     return __ret; 
218   }
219 #endif
220
221 _GLIBCXX_END_NAMESPACE