1 // std::ctype implementation details, GNU version -*- C++ -*-
2 
3 // Copyright (C) 2001-2016 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 <bits/c++locale_internal.h>
33 #include <cstdlib>
34 #include <cstring>
35 #include <cstdio>
36 
37 namespace std _GLIBCXX_VISIBILITY(default)
38 {
39   // NB: The other ctype<char> specializations are in src/locale.cc and
40   // various /config/os/* files.
41 
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     // Darwin uses the same codes for 'char' as 'wchar_t', so this routine
60     // never gets called.
61     return __m;
62   };
63 
64   wchar_t
do_toupper(wchar_t __c) const65   ctype<wchar_t>::do_toupper(wchar_t __c) const
66   { return towupper(__c); }
67 
68   const wchar_t*
do_toupper(wchar_t * __lo,const wchar_t * __hi) const69   ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const
70   {
71     while (__lo < __hi)
72       {
73         *__lo = towupper(*__lo);
74         ++__lo;
75       }
76     return __hi;
77   }
78 
79   wchar_t
do_tolower(wchar_t __c) const80   ctype<wchar_t>::do_tolower(wchar_t __c) const
81   { return towlower(__c); }
82 
83   const wchar_t*
do_tolower(wchar_t * __lo,const wchar_t * __hi) const84   ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const
85   {
86     while (__lo < __hi)
87       {
88         *__lo = towlower(*__lo);
89         ++__lo;
90       }
91     return __hi;
92   }
93 
94   wchar_t
95   ctype<wchar_t>::
do_widen(char __c) const96   do_widen(char __c) const
97   { return _M_widen[static_cast<unsigned char>(__c)]; }
98 
99   const char*
100   ctype<wchar_t>::
do_widen(const char * __lo,const char * __hi,wchar_t * __dest) const101   do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const
102   {
103     while (__lo < __hi)
104       {
105 	*__dest = _M_widen[static_cast<unsigned char>(*__lo)];
106 	++__lo;
107 	++__dest;
108       }
109     return __hi;
110   }
111 
112   char
113   ctype<wchar_t>::
do_narrow(wchar_t __wc,char __dfault) const114   do_narrow(wchar_t __wc, char __dfault) const
115   {
116     if (__wc >= 0 && __wc < 128 && _M_narrow_ok)
117       return _M_narrow[__wc];
118     const int __c = wctob(__wc);
119     return (__c == EOF ? __dfault : static_cast<char>(__c));
120   }
121 
122   const wchar_t*
123   ctype<wchar_t>::
do_narrow(const wchar_t * __lo,const wchar_t * __hi,char __dfault,char * __dest) const124   do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault,
125 	    char* __dest) const
126   {
127     if (_M_narrow_ok)
128       while (__lo < __hi)
129 	{
130 	  if (*__lo >= 0 && *__lo < 128)
131 	    *__dest = _M_narrow[*__lo];
132 	  else
133 	    {
134 	      const int __c = wctob(*__lo);
135 	      *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
136 	    }
137 	  ++__lo;
138 	  ++__dest;
139 	}
140     else
141       while (__lo < __hi)
142 	{
143 	  const int __c = wctob(*__lo);
144 	  *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
145 	  ++__lo;
146 	  ++__dest;
147 	}
148     return __hi;
149   }
150 
151   void
_M_initialize_ctype()152   ctype<wchar_t>::_M_initialize_ctype() throw()
153   {
154     wint_t __i;
155     for (__i = 0; __i < 128; ++__i)
156       {
157 	const int __c = wctob(__i);
158 	if (__c == EOF)
159 	  break;
160 	else
161 	  _M_narrow[__i] = static_cast<char>(__c);
162       }
163     if (__i == 128)
164       _M_narrow_ok = true;
165     else
166       _M_narrow_ok = false;
167     for (size_t __i = 0;
168 	 __i < sizeof(_M_widen) / sizeof(wint_t); ++__i)
169       _M_widen[__i] = btowc(__i);
170   }
171 #endif //  _GLIBCXX_USE_WCHAR_T
172 }
173