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