1// std::ctype implementation details, newlib version -*- C++ -*- 2 3// Copyright (C) 2011-2015 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#include <locale> 30#include <cstdlib> 31#include <cstring> 32#include <cstdio> 33 34namespace std _GLIBCXX_VISIBILITY(default) 35{ 36_GLIBCXX_BEGIN_NAMESPACE_VERSION 37 38 // NB: The other ctype<char> specializations are in src/locale.cc and 39 // various /config/os/* files. 40 ctype_byname<char>::ctype_byname(const char* __s, size_t __refs) 41 : ctype<char>(0, false, __refs) 42 { 43 if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0) 44 { 45 this->_S_destroy_c_locale(this->_M_c_locale_ctype); 46 this->_S_create_c_locale(this->_M_c_locale_ctype, __s); 47 } 48 } 49 50 ctype_byname<char>::~ctype_byname() 51 { } 52 53#ifdef _GLIBCXX_USE_WCHAR_T 54 ctype<wchar_t>::__wmask_type 55 ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const throw() 56 { 57 __wmask_type __ret; 58 switch (__m) 59 { 60 case space: 61 __ret = wctype("space"); 62 break; 63 case print: 64 __ret = wctype("print"); 65 break; 66 case cntrl: 67 __ret = wctype("cntrl"); 68 break; 69 case upper: 70 __ret = wctype("upper"); 71 break; 72 case lower: 73 __ret = wctype("lower"); 74 break; 75 case alpha: 76 __ret = wctype("alpha"); 77 break; 78 case digit: 79 __ret = wctype("digit"); 80 break; 81 case punct: 82 __ret = wctype("punct"); 83 break; 84 case xdigit: 85 __ret = wctype("xdigit"); 86 break; 87 case alnum: 88 __ret = wctype("alnum"); 89 break; 90 case graph: 91 __ret = wctype("graph"); 92 break; 93 default: 94 // Different from the generic version, xdigit and print in 95 // newlib are defined as bitwise-OR result of bitmasks: 96 // xdigit = _X | _N; 97 // print = _P | _U | _L | _N | _B; 98 // in which _X and _B don't correspond to any ctype mask. 99 // In order to get the wmask correctly converted when __m is 100 // equal to _X or _B, the two cases are specifically handled 101 // here. 102 if (__m & xdigit) 103 __ret = wctype("xdigit"); 104 else if (__m & print) 105 __ret = wctype("print"); 106 else 107 __ret = __wmask_type(); 108 } 109 return __ret; 110 }; 111 112 wchar_t 113 ctype<wchar_t>::do_toupper(wchar_t __c) const 114 { return towupper(__c); } 115 116 const wchar_t* 117 ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const 118 { 119 while (__lo < __hi) 120 { 121 *__lo = towupper(*__lo); 122 ++__lo; 123 } 124 return __hi; 125 } 126 127 wchar_t 128 ctype<wchar_t>::do_tolower(wchar_t __c) const 129 { return towlower(__c); } 130 131 const wchar_t* 132 ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const 133 { 134 while (__lo < __hi) 135 { 136 *__lo = towlower(*__lo); 137 ++__lo; 138 } 139 return __hi; 140 } 141 142 bool 143 ctype<wchar_t>:: 144 do_is(mask __m, wchar_t __c) const 145 { 146 bool __ret = false; 147 // Newlib C library has a compact encoding that uses 8 bits only. 148 const size_t __bitmasksize = 7; 149 for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur) 150 if (__m & _M_bit[__bitcur] 151 && iswctype(__c, _M_wmask[__bitcur])) 152 { 153 __ret = true; 154 break; 155 } 156 return __ret; 157 } 158 159 const wchar_t* 160 ctype<wchar_t>:: 161 do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __vec) const 162 { 163 for (; __lo < __hi; ++__vec, ++__lo) 164 { 165 // Newlib C library has a compact encoding that uses 8 bits only. 166 const size_t __bitmasksize = 7; 167 mask __m = 0; 168 for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur) 169 if (iswctype(*__lo, _M_wmask[__bitcur])) 170 __m |= _M_bit[__bitcur]; 171 *__vec = __m; 172 } 173 return __hi; 174 } 175 176 const wchar_t* 177 ctype<wchar_t>:: 178 do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const 179 { 180 while (__lo < __hi && !this->do_is(__m, *__lo)) 181 ++__lo; 182 return __lo; 183 } 184 185 const wchar_t* 186 ctype<wchar_t>:: 187 do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const 188 { 189 while (__lo < __hi && this->do_is(__m, *__lo) != 0) 190 ++__lo; 191 return __lo; 192 } 193 194 wchar_t 195 ctype<wchar_t>:: 196 do_widen(char __c) const 197 { return _M_widen[static_cast<unsigned char>(__c)]; } 198 199 const char* 200 ctype<wchar_t>:: 201 do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const 202 { 203 while (__lo < __hi) 204 { 205 *__dest = _M_widen[static_cast<unsigned char>(*__lo)]; 206 ++__lo; 207 ++__dest; 208 } 209 return __hi; 210 } 211 212 char 213 ctype<wchar_t>:: 214 do_narrow(wchar_t __wc, char __dfault) const 215 { 216 if (__wc >= 0 && __wc < 128 && _M_narrow_ok) 217 return _M_narrow[__wc]; 218 const int __c = wctob(__wc); 219 return (__c == EOF ? __dfault : static_cast<char>(__c)); 220 } 221 222 const wchar_t* 223 ctype<wchar_t>:: 224 do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault, 225 char* __dest) const 226 { 227 if (_M_narrow_ok) 228 while (__lo < __hi) 229 { 230 if (*__lo >= 0 && *__lo < 128) 231 *__dest = _M_narrow[*__lo]; 232 else 233 { 234 const int __c = wctob(*__lo); 235 *__dest = (__c == EOF ? __dfault : static_cast<char>(__c)); 236 } 237 ++__lo; 238 ++__dest; 239 } 240 else 241 while (__lo < __hi) 242 { 243 const int __c = wctob(*__lo); 244 *__dest = (__c == EOF ? __dfault : static_cast<char>(__c)); 245 ++__lo; 246 ++__dest; 247 } 248 return __hi; 249 } 250 251 void 252 ctype<wchar_t>::_M_initialize_ctype() throw() 253 { 254 wint_t __i; 255 for (__i = 0; __i < 128; ++__i) 256 { 257 const int __c = wctob(__i); 258 if (__c == EOF) 259 break; 260 else 261 _M_narrow[__i] = static_cast<char>(__c); 262 } 263 if (__i == 128) 264 _M_narrow_ok = true; 265 else 266 _M_narrow_ok = false; 267 for (size_t __i = 0; 268 __i < sizeof(_M_widen) / sizeof(wint_t); ++__i) 269 _M_widen[__i] = btowc(__i); 270 271 for (size_t __i = 0; __i <= 7; ++__i) 272 { 273 _M_bit[__i] = static_cast<mask>(1 << __i); 274 _M_wmask[__i] = _M_convert_to_wmask(_M_bit[__i]); 275 } 276 } 277#endif // _GLIBCXX_USE_WCHAR_T 278 279_GLIBCXX_END_NAMESPACE_VERSION 280} // namespace 281