1// std::ctype implementation details, generic version -*- C++ -*-
2
3// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
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 3, 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// Under Section 7 of GPL version 3, you are granted additional
18// permissions described in the GCC Runtime Library Exception, version
19// 3.1, as published by the Free Software Foundation.
20
21// You should have received a copy of the GNU General Public License and
22// a copy of the GCC Runtime Library Exception along with this program;
23// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24// <http://www.gnu.org/licenses/>.
25
26//
27// ISO C++ 14882: 22.2.1.1.2  ctype virtual functions.
28//
29
30// Written by Benjamin Kosnik <bkoz@redhat.com>
31
32#include <locale>
33#include <cstdlib>
34#include <cstring>
35#include <cstdio>
36
37_GLIBCXX_BEGIN_NAMESPACE(std)
38
39  // NB: The other ctype<char> specializations are in src/locale.cc and
40  // various /config/os/* files.
41  ctype_byname<char>::ctype_byname(const char* __s, size_t __refs)
42  : ctype<char>(0, false, __refs)
43  {
44    if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
45      {
46	this->_S_destroy_c_locale(this->_M_c_locale_ctype);
47	this->_S_create_c_locale(this->_M_c_locale_ctype, __s);
48      }
49  }
50
51  ctype_byname<char>::~ctype_byname()
52  { }
53
54#ifdef _GLIBCXX_USE_WCHAR_T
55  ctype<wchar_t>::__wmask_type
56  ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const throw()
57  {
58    __wmask_type __ret;
59    switch (__m)
60      {
61      case space:
62	__ret = wctype("space");
63	break;
64      case print:
65	__ret = wctype("print");
66	break;
67      case cntrl:
68	__ret = wctype("cntrl");
69	break;
70      case upper:
71	__ret = wctype("upper");
72	break;
73      case lower:
74	__ret = wctype("lower");
75	break;
76      case alpha:
77	__ret = wctype("alpha");
78	break;
79      case digit:
80	__ret = wctype("digit");
81	break;
82      case punct:
83	__ret = wctype("punct");
84	break;
85      case xdigit:
86	__ret = wctype("xdigit");
87	break;
88      case alnum:
89	__ret = wctype("alnum");
90	break;
91      case graph:
92	__ret = wctype("graph");
93	break;
94      default:
95	__ret = __wmask_type();
96      }
97    return __ret;
98  };
99
100  wchar_t
101  ctype<wchar_t>::do_toupper(wchar_t __c) const
102  { return towupper(__c); }
103
104  const wchar_t*
105  ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const
106  {
107    while (__lo < __hi)
108      {
109        *__lo = towupper(*__lo);
110        ++__lo;
111      }
112    return __hi;
113  }
114
115  wchar_t
116  ctype<wchar_t>::do_tolower(wchar_t __c) const
117  { return towlower(__c); }
118
119  const wchar_t*
120  ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const
121  {
122    while (__lo < __hi)
123      {
124        *__lo = towlower(*__lo);
125        ++__lo;
126      }
127    return __hi;
128  }
129
130  bool
131  ctype<wchar_t>::
132  do_is(mask __m, char_type __c) const
133  {
134    bool __ret = false;
135    // Generically, 15 (instead of 10) since we don't know the numerical
136    // encoding of the various categories in /usr/include/ctype.h.
137    const size_t __bitmasksize = 15;
138    for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
139      if (__m & _M_bit[__bitcur]
140	  && iswctype(__c, _M_wmask[__bitcur]))
141	{
142	  __ret = true;
143	  break;
144	}
145    return __ret;
146  }
147
148  const wchar_t*
149  ctype<wchar_t>::
150  do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __vec) const
151  {
152    for (;__lo < __hi; ++__vec, ++__lo)
153      {
154	// Generically, 15 (instead of 10) since we don't know the numerical
155	// encoding of the various categories in /usr/include/ctype.h.
156	const size_t __bitmasksize = 15;
157	mask __m = 0;
158	for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
159	  if (iswctype(*__lo, _M_wmask[__bitcur]))
160	    __m |= _M_bit[__bitcur];
161	*__vec = __m;
162      }
163    return __hi;
164  }
165
166  const wchar_t*
167  ctype<wchar_t>::
168  do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const
169  {
170    while (__lo < __hi && !this->do_is(__m, *__lo))
171      ++__lo;
172    return __lo;
173  }
174
175  const wchar_t*
176  ctype<wchar_t>::
177  do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const
178  {
179    while (__lo < __hi && this->do_is(__m, *__lo) != 0)
180      ++__lo;
181    return __lo;
182  }
183
184  wchar_t
185  ctype<wchar_t>::
186  do_widen(char __c) const
187  { return _M_widen[static_cast<unsigned char>(__c)]; }
188
189  const char*
190  ctype<wchar_t>::
191  do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const
192  {
193    while (__lo < __hi)
194      {
195	*__dest = _M_widen[static_cast<unsigned char>(*__lo)];
196	++__lo;
197	++__dest;
198      }
199    return __hi;
200  }
201
202  char
203  ctype<wchar_t>::
204  do_narrow(wchar_t __wc, char __dfault) const
205  {
206    if (__wc >= 0 && __wc < 128 && _M_narrow_ok)
207      return _M_narrow[__wc];
208    const int __c = wctob(__wc);
209    return (__c == EOF ? __dfault : static_cast<char>(__c));
210  }
211
212  const wchar_t*
213  ctype<wchar_t>::
214  do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault,
215	    char* __dest) const
216  {
217    if (_M_narrow_ok)
218      while (__lo < __hi)
219	{
220	  if (*__lo >= 0 && *__lo < 128)
221	    *__dest = _M_narrow[*__lo];
222	  else
223	    {
224	      const int __c = wctob(*__lo);
225	      *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
226	    }
227	  ++__lo;
228	  ++__dest;
229	}
230    else
231      while (__lo < __hi)
232	{
233	  const int __c = wctob(*__lo);
234	  *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
235	  ++__lo;
236	  ++__dest;
237	}
238    return __hi;
239  }
240
241  void
242  ctype<wchar_t>::_M_initialize_ctype() throw()
243  {
244    wint_t __i;
245    for (__i = 0; __i < 128; ++__i)
246      {
247	const int __c = wctob(__i);
248	if (__c == EOF)
249	  break;
250	else
251	  _M_narrow[__i] = static_cast<char>(__c);
252      }
253    if (__i == 128)
254      _M_narrow_ok = true;
255    else
256      _M_narrow_ok = false;
257    for (size_t __i = 0;
258	 __i < sizeof(_M_widen) / sizeof(wint_t); ++__i)
259      _M_widen[__i] = btowc(__i);
260
261    for (size_t __i = 0; __i <= 15; ++__i)
262      {
263	_M_bit[__i] = static_cast<mask>(1 << __i);
264	_M_wmask[__i] = _M_convert_to_wmask(_M_bit[__i]);
265      }
266  }
267#endif //  _GLIBCXX_USE_WCHAR_T
268
269_GLIBCXX_END_NAMESPACE
270