/ src / codecvt_members.cc
codecvt_members.cc
  1  // std::codecvt implementation details, generic version -*- C++ -*-
  2  
  3  // Copyright (C) 2002, 2005 Free Software Foundation, Inc.
  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
  8  // Free Software Foundation; either version 2, or (at your option)
  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  
 16  // You should have received a copy of the GNU General Public License along
 17  // with this library; see the file COPYING.  If not, write to the Free
 18  // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
 19  // USA.
 20  
 21  // As a special exception, you may use this file as part of a free software
 22  // library without restriction.  Specifically, if other files instantiate
 23  // templates or use macros or inline functions from this file, or you compile
 24  // this file and link it with other files to produce an executable, this
 25  // file does not by itself cause the resulting executable to be covered by
 26  // the GNU General Public License.  This exception does not however
 27  // invalidate any other reasons why the executable file might be covered by
 28  // the GNU General Public License.
 29  
 30  //
 31  // ISO C++ 14882: 22.2.1.5 - Template class codecvt
 32  //
 33  
 34  // Written by Benjamin Kosnik <bkoz@redhat.com>
 35  
 36  #include <locale>
 37  
 38  _GLIBCXX_BEGIN_NAMESPACE(std)
 39  
 40    // Specializations.
 41  #ifdef _GLIBCXX_USE_WCHAR_T
 42    codecvt_base::result
 43    codecvt<wchar_t, char, mbstate_t>::
 44    do_out(state_type& __state, const intern_type* __from, 
 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    {
 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
 52      state_type __tmp_state(__state);
 53  
 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.
 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
 76        {
 77  	extern_type __buf[MB_LEN_MAX];
 78  	while (__from < __from_end && __to < __to_end)
 79  	  {
 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  	      }
 91  	    
 92  	    memcpy(__to, __buf, __conv);
 93  	    __state = __tmp_state;
 94  	    __to += __conv;
 95  	    __from++;
 96  	  }
 97        }
 98  
 99      if (__ret == ok && __from < __from_end)
100        __ret = partial;
101  
102      __from_next = __from;
103      __to_next = __to;
104      return __ret; 
105    }
106    
107    codecvt_base::result
108    codecvt<wchar_t, char, mbstate_t>::
109    do_in(state_type& __state, const extern_type* __from, 
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    {
114      result __ret = ok;
115      // This temporary state object is neccessary so __state won't be modified
116      // if [__from, __from_end) is a partial multibyte character.
117      state_type __tmp_state(__state);
118  
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)
123        {
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;
147        }
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;
156      return __ret; 
157    }
158  
159    int 
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;
169    }  
170  
171    int 
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    }
179    
180    int 
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)
189        {
190  	size_t __conv = mbrtowc(NULL, __from, __end - __from, &__tmp_state);
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--;
212        }
213  
214      return __ret; 
215    }
216  #endif
217  
218  _GLIBCXX_END_NAMESPACE