197403Sobrien// std::ctype implementation details, generic version -*- C++ -*-
297403Sobrien
3169691Skan// Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
497403Sobrien//
597403Sobrien// This file is part of the GNU ISO C++ Library.  This library is free
697403Sobrien// software; you can redistribute it and/or modify it under the
797403Sobrien// terms of the GNU General Public License as published by the
897403Sobrien// Free Software Foundation; either version 2, or (at your option)
997403Sobrien// any later version.
1097403Sobrien
1197403Sobrien// This library is distributed in the hope that it will be useful,
1297403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of
1397403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1497403Sobrien// GNU General Public License for more details.
1597403Sobrien
1697403Sobrien// You should have received a copy of the GNU General Public License along
1797403Sobrien// with this library; see the file COPYING.  If not, write to the Free
18169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
1997403Sobrien// USA.
2097403Sobrien
2197403Sobrien// As a special exception, you may use this file as part of a free software
2297403Sobrien// library without restriction.  Specifically, if other files instantiate
2397403Sobrien// templates or use macros or inline functions from this file, or you compile
2497403Sobrien// this file and link it with other files to produce an executable, this
2597403Sobrien// file does not by itself cause the resulting executable to be covered by
2697403Sobrien// the GNU General Public License.  This exception does not however
2797403Sobrien// invalidate any other reasons why the executable file might be covered by
2897403Sobrien// the GNU General Public License.
2997403Sobrien
3097403Sobrien//
3197403Sobrien// ISO C++ 14882: 22.2.1.1.2  ctype virtual functions.
3297403Sobrien//
3397403Sobrien
3497403Sobrien// Written by Benjamin Kosnik <bkoz@redhat.com>
3597403Sobrien
3697403Sobrien#include <locale>
3797403Sobrien
38169691Skan_GLIBCXX_BEGIN_NAMESPACE(std)
39169691Skan
4097403Sobrien  // NB: The other ctype<char> specializations are in src/locale.cc and
4197403Sobrien  // various /config/os/* files.
4297403Sobrien  template<>
4397403Sobrien    ctype_byname<char>::ctype_byname(const char* __s, size_t __refs)
4497403Sobrien    : ctype<char>(0, false, __refs)
4597403Sobrien    {
46132720Skan      if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
47132720Skan	{
48132720Skan	  this->_S_destroy_c_locale(this->_M_c_locale_ctype);
49132720Skan	  this->_S_create_c_locale(this->_M_c_locale_ctype, __s);
50132720Skan	}
5197403Sobrien    }
5297403Sobrien
53132720Skan#ifdef _GLIBCXX_USE_WCHAR_T
5497403Sobrien  ctype<wchar_t>::__wmask_type
5597403Sobrien  ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const
5697403Sobrien  {
5797403Sobrien    __wmask_type __ret;
5897403Sobrien    switch (__m)
5997403Sobrien      {
6097403Sobrien      case space:
6197403Sobrien	__ret = wctype("space");
6297403Sobrien	break;
6397403Sobrien      case print:
6497403Sobrien	__ret = wctype("print");
6597403Sobrien	break;
6697403Sobrien      case cntrl:
6797403Sobrien	__ret = wctype("cntrl");
6897403Sobrien	break;
6997403Sobrien      case upper:
7097403Sobrien	__ret = wctype("upper");
7197403Sobrien	break;
7297403Sobrien      case lower:
7397403Sobrien	__ret = wctype("lower");
7497403Sobrien	break;
7597403Sobrien      case alpha:
7697403Sobrien	__ret = wctype("alpha");
7797403Sobrien	break;
7897403Sobrien      case digit:
7997403Sobrien	__ret = wctype("digit");
8097403Sobrien	break;
8197403Sobrien      case punct:
8297403Sobrien	__ret = wctype("punct");
8397403Sobrien	break;
8497403Sobrien      case xdigit:
8597403Sobrien	__ret = wctype("xdigit");
8697403Sobrien	break;
8797403Sobrien      case alnum:
8897403Sobrien	__ret = wctype("alnum");
8997403Sobrien	break;
9097403Sobrien      case graph:
9197403Sobrien	__ret = wctype("graph");
9297403Sobrien	break;
9397403Sobrien      default:
94169691Skan	__ret = __wmask_type();
9597403Sobrien      }
9697403Sobrien    return __ret;
9797403Sobrien  };
9897403Sobrien
9997403Sobrien  wchar_t
10097403Sobrien  ctype<wchar_t>::do_toupper(wchar_t __c) const
10197403Sobrien  { return towupper(__c); }
10297403Sobrien
10397403Sobrien  const wchar_t*
10497403Sobrien  ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const
10597403Sobrien  {
10697403Sobrien    while (__lo < __hi)
10797403Sobrien      {
10897403Sobrien        *__lo = towupper(*__lo);
10997403Sobrien        ++__lo;
11097403Sobrien      }
11197403Sobrien    return __hi;
11297403Sobrien  }
11397403Sobrien
11497403Sobrien  wchar_t
11597403Sobrien  ctype<wchar_t>::do_tolower(wchar_t __c) const
11697403Sobrien  { return towlower(__c); }
11797403Sobrien
11897403Sobrien  const wchar_t*
11997403Sobrien  ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const
12097403Sobrien  {
12197403Sobrien    while (__lo < __hi)
12297403Sobrien      {
12397403Sobrien        *__lo = towlower(*__lo);
12497403Sobrien        ++__lo;
12597403Sobrien      }
12697403Sobrien    return __hi;
12797403Sobrien  }
12897403Sobrien
12997403Sobrien  bool
13097403Sobrien  ctype<wchar_t>::
13197403Sobrien  do_is(mask __m, char_type __c) const
132122182Skan  {
133122182Skan    bool __ret = false;
134132720Skan    // Generically, 15 (instead of 10) since we don't know the numerical
135132720Skan    // encoding of the various categories in /usr/include/ctype.h.
136132720Skan    const size_t __bitmasksize = 15;
137122182Skan    for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
138132720Skan      if (__m & _M_bit[__bitcur]
139132720Skan	  && iswctype(__c, _M_wmask[__bitcur]))
140132720Skan	{
141132720Skan	  __ret = true;
142132720Skan	  break;
143132720Skan	}
144122182Skan    return __ret;
145122182Skan  }
14697403Sobrien
14797403Sobrien  const wchar_t*
14897403Sobrien  ctype<wchar_t>::
149122182Skan  do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __vec) const
15097403Sobrien  {
151122182Skan    for (;__lo < __hi; ++__vec, ++__lo)
152122182Skan      {
153132720Skan	// Generically, 15 (instead of 10) since we don't know the numerical
154132720Skan	// encoding of the various categories in /usr/include/ctype.h.
155132720Skan	const size_t __bitmasksize = 15;
156122182Skan	mask __m = 0;
157122182Skan	for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
158132720Skan	  if (iswctype(*__lo, _M_wmask[__bitcur]))
159132720Skan	    __m |= _M_bit[__bitcur];
160122182Skan	*__vec = __m;
161122182Skan      }
162122182Skan    return __hi;
16397403Sobrien  }
16497403Sobrien
16597403Sobrien  const wchar_t*
16697403Sobrien  ctype<wchar_t>::
16797403Sobrien  do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const
16897403Sobrien  {
16997403Sobrien    while (__lo < __hi && !this->do_is(__m, *__lo))
17097403Sobrien      ++__lo;
17197403Sobrien    return __lo;
17297403Sobrien  }
17397403Sobrien
17497403Sobrien  const wchar_t*
17597403Sobrien  ctype<wchar_t>::
17697403Sobrien  do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const
17797403Sobrien  {
17897403Sobrien    while (__lo < __hi && this->do_is(__m, *__lo) != 0)
17997403Sobrien      ++__lo;
18097403Sobrien    return __lo;
18197403Sobrien  }
18297403Sobrien
18397403Sobrien  wchar_t
18497403Sobrien  ctype<wchar_t>::
18597403Sobrien  do_widen(char __c) const
186132720Skan  { return _M_widen[static_cast<unsigned char>(__c)]; }
18797403Sobrien
18897403Sobrien  const char*
18997403Sobrien  ctype<wchar_t>::
19097403Sobrien  do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const
19197403Sobrien  {
192132720Skan    while (__lo < __hi)
193132720Skan      {
194132720Skan	*__dest = _M_widen[static_cast<unsigned char>(*__lo)];
195132720Skan	++__lo;
196132720Skan	++__dest;
197132720Skan      }
19897403Sobrien    return __hi;
19997403Sobrien  }
20097403Sobrien
20197403Sobrien  char
20297403Sobrien  ctype<wchar_t>::
20397403Sobrien  do_narrow(wchar_t __wc, char __dfault) const
20497403Sobrien  {
205132720Skan    if (__wc >= 0 && __wc < 128 && _M_narrow_ok)
206132720Skan      return _M_narrow[__wc];
207132720Skan    const int __c = wctob(__wc);
20897403Sobrien    return (__c == EOF ? __dfault : static_cast<char>(__c));
20997403Sobrien  }
21097403Sobrien
21197403Sobrien  const wchar_t*
21297403Sobrien  ctype<wchar_t>::
21397403Sobrien  do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault,
21497403Sobrien	    char* __dest) const
21597403Sobrien  {
216132720Skan    if (_M_narrow_ok)
217132720Skan      while (__lo < __hi)
218132720Skan	{
219132720Skan	  if (*__lo >= 0 && *__lo < 128)
220132720Skan	    *__dest = _M_narrow[*__lo];
221132720Skan	  else
222132720Skan	    {
223132720Skan	      const int __c = wctob(*__lo);
224132720Skan	      *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
225132720Skan	    }
226132720Skan	  ++__lo;
227132720Skan	  ++__dest;
228132720Skan	}
229132720Skan    else
230132720Skan      while (__lo < __hi)
231132720Skan	{
232132720Skan	  const int __c = wctob(*__lo);
233132720Skan	  *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
234132720Skan	  ++__lo;
235132720Skan	  ++__dest;
236132720Skan	}
237132720Skan    return __hi;
238132720Skan  }
239132720Skan
240132720Skan  void
241132720Skan  ctype<wchar_t>::_M_initialize_ctype()
242132720Skan  {
243132720Skan    wint_t __i;
244132720Skan    for (__i = 0; __i < 128; ++__i)
245102782Skan      {
246132720Skan	const int __c = wctob(__i);
247132720Skan	if (__c == EOF)
248132720Skan	  break;
249102782Skan	else
250132720Skan	  _M_narrow[__i] = static_cast<char>(__c);
251102782Skan      }
252132720Skan    if (__i == 128)
253132720Skan      _M_narrow_ok = true;
254132720Skan    else
255132720Skan      _M_narrow_ok = false;
256132720Skan    for (size_t __i = 0;
257132720Skan	 __i < sizeof(_M_widen) / sizeof(wint_t); ++__i)
258132720Skan      _M_widen[__i] = btowc(__i);
259132720Skan
260132720Skan    for (size_t __i = 0; __i <= 15; ++__i)
261132720Skan      {
262132720Skan	_M_bit[__i] = static_cast<mask>(1 << __i);
263132720Skan	_M_wmask[__i] = _M_convert_to_wmask(_M_bit[__i]);
264132720Skan      }
26597403Sobrien  }
266132720Skan#endif //  _GLIBCXX_USE_WCHAR_T
267169691Skan
268169691Skan_GLIBCXX_END_NAMESPACE
269