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