xref: /openbsd-src/gnu/gcc/libstdc++-v3/include/bits/char_traits.h (revision 404b540a9034ac75a6199ad1a32d1bbc7a0d4210)
1*404b540aSrobert // Character Traits for use by standard string and iostream -*- C++ -*-
2*404b540aSrobert 
3*404b540aSrobert // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
4*404b540aSrobert // Free Software Foundation, Inc.
5*404b540aSrobert //
6*404b540aSrobert // This file is part of the GNU ISO C++ Library.  This library is free
7*404b540aSrobert // software; you can redistribute it and/or modify it under the
8*404b540aSrobert // terms of the GNU General Public License as published by the
9*404b540aSrobert // Free Software Foundation; either version 2, or (at your option)
10*404b540aSrobert // any later version.
11*404b540aSrobert 
12*404b540aSrobert // This library is distributed in the hope that it will be useful,
13*404b540aSrobert // but WITHOUT ANY WARRANTY; without even the implied warranty of
14*404b540aSrobert // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*404b540aSrobert // GNU General Public License for more details.
16*404b540aSrobert 
17*404b540aSrobert // You should have received a copy of the GNU General Public License along
18*404b540aSrobert // with this library; see the file COPYING.  If not, write to the Free
19*404b540aSrobert // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20*404b540aSrobert // USA.
21*404b540aSrobert 
22*404b540aSrobert // As a special exception, you may use this file as part of a free software
23*404b540aSrobert // library without restriction.  Specifically, if other files instantiate
24*404b540aSrobert // templates or use macros or inline functions from this file, or you compile
25*404b540aSrobert // this file and link it with other files to produce an executable, this
26*404b540aSrobert // file does not by itself cause the resulting executable to be covered by
27*404b540aSrobert // the GNU General Public License.  This exception does not however
28*404b540aSrobert // invalidate any other reasons why the executable file might be covered by
29*404b540aSrobert // the GNU General Public License.
30*404b540aSrobert 
31*404b540aSrobert /** @file char_traits.h
32*404b540aSrobert  *  This is an internal header file, included by other library headers.
33*404b540aSrobert  *  You should not attempt to use it directly.
34*404b540aSrobert  */
35*404b540aSrobert 
36*404b540aSrobert //
37*404b540aSrobert // ISO C++ 14882: 21  Strings library
38*404b540aSrobert //
39*404b540aSrobert 
40*404b540aSrobert #ifndef _CHAR_TRAITS_H
41*404b540aSrobert #define _CHAR_TRAITS_H 1
42*404b540aSrobert 
43*404b540aSrobert #pragma GCC system_header
44*404b540aSrobert 
45*404b540aSrobert #include <cstring>            // For memmove, memset, memchr
46*404b540aSrobert #include <bits/stl_algobase.h>// For copy, lexicographical_compare, fill_n
47*404b540aSrobert #include <bits/postypes.h>    // For streampos
48*404b540aSrobert 
49*404b540aSrobert _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
50*404b540aSrobert 
51*404b540aSrobert   /**
52*404b540aSrobert    *  @brief  Mapping from character type to associated types.
53*404b540aSrobert    *
54*404b540aSrobert    *  @note This is an implementation class for the generic version
55*404b540aSrobert    *  of char_traits.  It defines int_type, off_type, pos_type, and
56*404b540aSrobert    *  state_type.  By default these are unsigned long, streamoff,
57*404b540aSrobert    *  streampos, and mbstate_t.  Users who need a different set of
58*404b540aSrobert    *  types, but who don't need to change the definitions of any function
59*404b540aSrobert    *  defined in char_traits, can specialize __gnu_cxx::_Char_types
60*404b540aSrobert    *  while leaving __gnu_cxx::char_traits alone. */
61*404b540aSrobert   template <class _CharT>
62*404b540aSrobert     struct _Char_types
63*404b540aSrobert     {
64*404b540aSrobert       typedef unsigned long   int_type;
65*404b540aSrobert       typedef std::streampos  pos_type;
66*404b540aSrobert       typedef std::streamoff  off_type;
67*404b540aSrobert       typedef std::mbstate_t  state_type;
68*404b540aSrobert     };
69*404b540aSrobert 
70*404b540aSrobert 
71*404b540aSrobert   /**
72*404b540aSrobert    *  @brief  Base class used to implement std::char_traits.
73*404b540aSrobert    *
74*404b540aSrobert    *  @note For any given actual character type, this definition is
75*404b540aSrobert    *  probably wrong.  (Most of the member functions are likely to be
76*404b540aSrobert    *  right, but the int_type and state_type typedefs, and the eof()
77*404b540aSrobert    *  member function, are likely to be wrong.)  The reason this class
78*404b540aSrobert    *  exists is so users can specialize it.  Classes in namespace std
79*404b540aSrobert    *  may not be specialized for fundamentl types, but classes in
80*404b540aSrobert    *  namespace __gnu_cxx may be.
81*404b540aSrobert    *
82*404b540aSrobert    *  See http://gcc.gnu.org/onlinedocs/libstdc++/21_strings/howto.html#5
83*404b540aSrobert    *  for advice on how to make use of this class for "unusual" character
84*404b540aSrobert    *  types. Also, check out include/ext/pod_char_traits.h.
85*404b540aSrobert    */
86*404b540aSrobert   template<typename _CharT>
87*404b540aSrobert     struct char_traits
88*404b540aSrobert     {
89*404b540aSrobert       typedef _CharT                                    char_type;
90*404b540aSrobert       typedef typename _Char_types<_CharT>::int_type    int_type;
91*404b540aSrobert       typedef typename _Char_types<_CharT>::pos_type    pos_type;
92*404b540aSrobert       typedef typename _Char_types<_CharT>::off_type    off_type;
93*404b540aSrobert       typedef typename _Char_types<_CharT>::state_type  state_type;
94*404b540aSrobert 
95*404b540aSrobert       static void
assignchar_traits96*404b540aSrobert       assign(char_type& __c1, const char_type& __c2)
97*404b540aSrobert       { __c1 = __c2; }
98*404b540aSrobert 
99*404b540aSrobert       static bool
eqchar_traits100*404b540aSrobert       eq(const char_type& __c1, const char_type& __c2)
101*404b540aSrobert       { return __c1 == __c2; }
102*404b540aSrobert 
103*404b540aSrobert       static bool
ltchar_traits104*404b540aSrobert       lt(const char_type& __c1, const char_type& __c2)
105*404b540aSrobert       { return __c1 < __c2; }
106*404b540aSrobert 
107*404b540aSrobert       static int
108*404b540aSrobert       compare(const char_type* __s1, const char_type* __s2, std::size_t __n);
109*404b540aSrobert 
110*404b540aSrobert       static std::size_t
111*404b540aSrobert       length(const char_type* __s);
112*404b540aSrobert 
113*404b540aSrobert       static const char_type*
114*404b540aSrobert       find(const char_type* __s, std::size_t __n, const char_type& __a);
115*404b540aSrobert 
116*404b540aSrobert       static char_type*
117*404b540aSrobert       move(char_type* __s1, const char_type* __s2, std::size_t __n);
118*404b540aSrobert 
119*404b540aSrobert       static char_type*
120*404b540aSrobert       copy(char_type* __s1, const char_type* __s2, std::size_t __n);
121*404b540aSrobert 
122*404b540aSrobert       static char_type*
123*404b540aSrobert       assign(char_type* __s, std::size_t __n, char_type __a);
124*404b540aSrobert 
125*404b540aSrobert       static char_type
to_char_typechar_traits126*404b540aSrobert       to_char_type(const int_type& __c)
127*404b540aSrobert       { return static_cast<char_type>(__c); }
128*404b540aSrobert 
129*404b540aSrobert       static int_type
to_int_typechar_traits130*404b540aSrobert       to_int_type(const char_type& __c)
131*404b540aSrobert       { return static_cast<int_type>(__c); }
132*404b540aSrobert 
133*404b540aSrobert       static bool
eq_int_typechar_traits134*404b540aSrobert       eq_int_type(const int_type& __c1, const int_type& __c2)
135*404b540aSrobert       { return __c1 == __c2; }
136*404b540aSrobert 
137*404b540aSrobert       static int_type
eofchar_traits138*404b540aSrobert       eof()
139*404b540aSrobert       { return static_cast<int_type>(EOF); }
140*404b540aSrobert 
141*404b540aSrobert       static int_type
not_eofchar_traits142*404b540aSrobert       not_eof(const int_type& __c)
143*404b540aSrobert       { return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); }
144*404b540aSrobert     };
145*404b540aSrobert 
146*404b540aSrobert   template<typename _CharT>
147*404b540aSrobert     int
148*404b540aSrobert     char_traits<_CharT>::
compare(const char_type * __s1,const char_type * __s2,std::size_t __n)149*404b540aSrobert     compare(const char_type* __s1, const char_type* __s2, std::size_t __n)
150*404b540aSrobert     {
151*404b540aSrobert       for (std::size_t __i = 0; __i < __n; ++__i)
152*404b540aSrobert 	if (lt(__s1[__i], __s2[__i]))
153*404b540aSrobert 	  return -1;
154*404b540aSrobert 	else if (lt(__s2[__i], __s1[__i]))
155*404b540aSrobert 	  return 1;
156*404b540aSrobert       return 0;
157*404b540aSrobert     }
158*404b540aSrobert 
159*404b540aSrobert   template<typename _CharT>
160*404b540aSrobert     std::size_t
161*404b540aSrobert     char_traits<_CharT>::
length(const char_type * __p)162*404b540aSrobert     length(const char_type* __p)
163*404b540aSrobert     {
164*404b540aSrobert       std::size_t __i = 0;
165*404b540aSrobert       while (!eq(__p[__i], char_type()))
166*404b540aSrobert         ++__i;
167*404b540aSrobert       return __i;
168*404b540aSrobert     }
169*404b540aSrobert 
170*404b540aSrobert   template<typename _CharT>
171*404b540aSrobert     const typename char_traits<_CharT>::char_type*
172*404b540aSrobert     char_traits<_CharT>::
find(const char_type * __s,std::size_t __n,const char_type & __a)173*404b540aSrobert     find(const char_type* __s, std::size_t __n, const char_type& __a)
174*404b540aSrobert     {
175*404b540aSrobert       for (std::size_t __i = 0; __i < __n; ++__i)
176*404b540aSrobert         if (eq(__s[__i], __a))
177*404b540aSrobert           return __s + __i;
178*404b540aSrobert       return 0;
179*404b540aSrobert     }
180*404b540aSrobert 
181*404b540aSrobert   template<typename _CharT>
182*404b540aSrobert     typename char_traits<_CharT>::char_type*
183*404b540aSrobert     char_traits<_CharT>::
move(char_type * __s1,const char_type * __s2,std::size_t __n)184*404b540aSrobert     move(char_type* __s1, const char_type* __s2, std::size_t __n)
185*404b540aSrobert     {
186*404b540aSrobert       return static_cast<_CharT*>(std::memmove(__s1, __s2,
187*404b540aSrobert 					       __n * sizeof(char_type)));
188*404b540aSrobert     }
189*404b540aSrobert 
190*404b540aSrobert   template<typename _CharT>
191*404b540aSrobert     typename char_traits<_CharT>::char_type*
192*404b540aSrobert     char_traits<_CharT>::
copy(char_type * __s1,const char_type * __s2,std::size_t __n)193*404b540aSrobert     copy(char_type* __s1, const char_type* __s2, std::size_t __n)
194*404b540aSrobert     {
195*404b540aSrobert       std::copy(__s2, __s2 + __n, __s1);
196*404b540aSrobert       return __s1;
197*404b540aSrobert     }
198*404b540aSrobert 
199*404b540aSrobert   template<typename _CharT>
200*404b540aSrobert     typename char_traits<_CharT>::char_type*
201*404b540aSrobert     char_traits<_CharT>::
assign(char_type * __s,std::size_t __n,char_type __a)202*404b540aSrobert     assign(char_type* __s, std::size_t __n, char_type __a)
203*404b540aSrobert     {
204*404b540aSrobert       std::fill_n(__s, __n, __a);
205*404b540aSrobert       return __s;
206*404b540aSrobert     }
207*404b540aSrobert 
208*404b540aSrobert _GLIBCXX_END_NAMESPACE
209*404b540aSrobert 
210*404b540aSrobert _GLIBCXX_BEGIN_NAMESPACE(std)
211*404b540aSrobert 
212*404b540aSrobert   // 21.1
213*404b540aSrobert   /**
214*404b540aSrobert    *  @brief  Basis for explicit traits specializations.
215*404b540aSrobert    *
216*404b540aSrobert    *  @note  For any given actual character type, this definition is
217*404b540aSrobert    *  probably wrong.  Since this is just a thin wrapper around
218*404b540aSrobert    *  __gnu_cxx::char_traits, it is possible to achieve a more
219*404b540aSrobert    *  appropriate definition by specializing __gnu_cxx::char_traits.
220*404b540aSrobert    *
221*404b540aSrobert    *  See http://gcc.gnu.org/onlinedocs/libstdc++/21_strings/howto.html#5
222*404b540aSrobert    *  for advice on how to make use of this class for "unusual" character
223*404b540aSrobert    *  types. Also, check out include/ext/pod_char_traits.h.
224*404b540aSrobert   */
225*404b540aSrobert   template<class _CharT>
226*404b540aSrobert     struct char_traits : public __gnu_cxx::char_traits<_CharT>
227*404b540aSrobert     { };
228*404b540aSrobert 
229*404b540aSrobert 
230*404b540aSrobert   /// @brief  21.1.3.1  char_traits specializations
231*404b540aSrobert   template<>
232*404b540aSrobert     struct char_traits<char>
233*404b540aSrobert     {
234*404b540aSrobert       typedef char              char_type;
235*404b540aSrobert       typedef int               int_type;
236*404b540aSrobert       typedef streampos         pos_type;
237*404b540aSrobert       typedef streamoff         off_type;
238*404b540aSrobert       typedef mbstate_t         state_type;
239*404b540aSrobert 
240*404b540aSrobert       static void
241*404b540aSrobert       assign(char_type& __c1, const char_type& __c2)
242*404b540aSrobert       { __c1 = __c2; }
243*404b540aSrobert 
244*404b540aSrobert       static bool
245*404b540aSrobert       eq(const char_type& __c1, const char_type& __c2)
246*404b540aSrobert       { return __c1 == __c2; }
247*404b540aSrobert 
248*404b540aSrobert       static bool
249*404b540aSrobert       lt(const char_type& __c1, const char_type& __c2)
250*404b540aSrobert       { return __c1 < __c2; }
251*404b540aSrobert 
252*404b540aSrobert       static int
253*404b540aSrobert       compare(const char_type* __s1, const char_type* __s2, size_t __n)
254*404b540aSrobert       { return memcmp(__s1, __s2, __n); }
255*404b540aSrobert 
256*404b540aSrobert       static size_t
257*404b540aSrobert       length(const char_type* __s)
258*404b540aSrobert       { return strlen(__s); }
259*404b540aSrobert 
260*404b540aSrobert       static const char_type*
261*404b540aSrobert       find(const char_type* __s, size_t __n, const char_type& __a)
262*404b540aSrobert       { return static_cast<const char_type*>(memchr(__s, __a, __n)); }
263*404b540aSrobert 
264*404b540aSrobert       static char_type*
265*404b540aSrobert       move(char_type* __s1, const char_type* __s2, size_t __n)
266*404b540aSrobert       { return static_cast<char_type*>(memmove(__s1, __s2, __n)); }
267*404b540aSrobert 
268*404b540aSrobert       static char_type*
269*404b540aSrobert       copy(char_type* __s1, const char_type* __s2, size_t __n)
270*404b540aSrobert       { return static_cast<char_type*>(memcpy(__s1, __s2, __n)); }
271*404b540aSrobert 
272*404b540aSrobert       static char_type*
273*404b540aSrobert       assign(char_type* __s, size_t __n, char_type __a)
274*404b540aSrobert       { return static_cast<char_type*>(memset(__s, __a, __n)); }
275*404b540aSrobert 
276*404b540aSrobert       static char_type
277*404b540aSrobert       to_char_type(const int_type& __c)
278*404b540aSrobert       { return static_cast<char_type>(__c); }
279*404b540aSrobert 
280*404b540aSrobert       // To keep both the byte 0xff and the eof symbol 0xffffffff
281*404b540aSrobert       // from ending up as 0xffffffff.
282*404b540aSrobert       static int_type
283*404b540aSrobert       to_int_type(const char_type& __c)
284*404b540aSrobert       { return static_cast<int_type>(static_cast<unsigned char>(__c)); }
285*404b540aSrobert 
286*404b540aSrobert       static bool
287*404b540aSrobert       eq_int_type(const int_type& __c1, const int_type& __c2)
288*404b540aSrobert       { return __c1 == __c2; }
289*404b540aSrobert 
290*404b540aSrobert       static int_type
291*404b540aSrobert       eof() { return static_cast<int_type>(EOF); }
292*404b540aSrobert 
293*404b540aSrobert       static int_type
294*404b540aSrobert       not_eof(const int_type& __c)
295*404b540aSrobert       { return (__c == eof()) ? 0 : __c; }
296*404b540aSrobert   };
297*404b540aSrobert 
298*404b540aSrobert 
299*404b540aSrobert #ifdef _GLIBCXX_USE_WCHAR_T
300*404b540aSrobert   /// @brief  21.1.3.2  char_traits specializations
301*404b540aSrobert   template<>
302*404b540aSrobert     struct char_traits<wchar_t>
303*404b540aSrobert     {
304*404b540aSrobert       typedef wchar_t           char_type;
305*404b540aSrobert       typedef wint_t            int_type;
306*404b540aSrobert       typedef streamoff         off_type;
307*404b540aSrobert       typedef wstreampos        pos_type;
308*404b540aSrobert       typedef mbstate_t         state_type;
309*404b540aSrobert 
310*404b540aSrobert       static void
311*404b540aSrobert       assign(char_type& __c1, const char_type& __c2)
312*404b540aSrobert       { __c1 = __c2; }
313*404b540aSrobert 
314*404b540aSrobert       static bool
315*404b540aSrobert       eq(const char_type& __c1, const char_type& __c2)
316*404b540aSrobert       { return __c1 == __c2; }
317*404b540aSrobert 
318*404b540aSrobert       static bool
319*404b540aSrobert       lt(const char_type& __c1, const char_type& __c2)
320*404b540aSrobert       { return __c1 < __c2; }
321*404b540aSrobert 
322*404b540aSrobert       static int
323*404b540aSrobert       compare(const char_type* __s1, const char_type* __s2, size_t __n)
324*404b540aSrobert       { return wmemcmp(__s1, __s2, __n); }
325*404b540aSrobert 
326*404b540aSrobert       static size_t
327*404b540aSrobert       length(const char_type* __s)
328*404b540aSrobert       { return wcslen(__s); }
329*404b540aSrobert 
330*404b540aSrobert       static const char_type*
331*404b540aSrobert       find(const char_type* __s, size_t __n, const char_type& __a)
332*404b540aSrobert       { return wmemchr(__s, __a, __n); }
333*404b540aSrobert 
334*404b540aSrobert       static char_type*
335*404b540aSrobert       move(char_type* __s1, const char_type* __s2, size_t __n)
336*404b540aSrobert       { return wmemmove(__s1, __s2, __n); }
337*404b540aSrobert 
338*404b540aSrobert       static char_type*
339*404b540aSrobert       copy(char_type* __s1, const char_type* __s2, size_t __n)
340*404b540aSrobert       { return wmemcpy(__s1, __s2, __n); }
341*404b540aSrobert 
342*404b540aSrobert       static char_type*
343*404b540aSrobert       assign(char_type* __s, size_t __n, char_type __a)
344*404b540aSrobert       { return wmemset(__s, __a, __n); }
345*404b540aSrobert 
346*404b540aSrobert       static char_type
347*404b540aSrobert       to_char_type(const int_type& __c) { return char_type(__c); }
348*404b540aSrobert 
349*404b540aSrobert       static int_type
350*404b540aSrobert       to_int_type(const char_type& __c) { return int_type(__c); }
351*404b540aSrobert 
352*404b540aSrobert       static bool
353*404b540aSrobert       eq_int_type(const int_type& __c1, const int_type& __c2)
354*404b540aSrobert       { return __c1 == __c2; }
355*404b540aSrobert 
356*404b540aSrobert       static int_type
357*404b540aSrobert       eof() { return static_cast<int_type>(WEOF); }
358*404b540aSrobert 
359*404b540aSrobert       static int_type
360*404b540aSrobert       not_eof(const int_type& __c)
361*404b540aSrobert       { return eq_int_type(__c, eof()) ? 0 : __c; }
362*404b540aSrobert   };
363*404b540aSrobert #endif //_GLIBCXX_USE_WCHAR_T
364*404b540aSrobert 
365*404b540aSrobert _GLIBCXX_END_NAMESPACE
366*404b540aSrobert 
367*404b540aSrobert #endif
368