char.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2007 Marc Boris Duerner
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * As a special exception, you may use this file as part of a free
10  * software library without restriction. Specifically, if other files
11  * instantiate templates or use macros or inline functions from this
12  * file, or you compile this file and link it with other files to
13  * produce an executable, this file does not by itself cause the
14  * resulting executable to be covered by the GNU General Public
15  * License. This exception does not however invalidate any other
16  * reasons why the executable file might be covered by the GNU Library
17  * General Public License.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27  */
28 #ifndef CXXTOOLS_CHAR_H
29 #define CXXTOOLS_CHAR_H
30 
31 #include <cxxtools/config.h>
32 #include <string>
33 #include <cstring>
34 #include <ios>
35 #include <stdint.h>
36 
37 namespace cxxtools
38 {
39 
65  class Char
66  {
67  public:
68  typedef int32_t value_type;
69 
71  Char()
72  : _value(0)
73  {}
74 
77  : _value(ch)
78  {}
79 
92  char narrow(char def = '?') const;
93 
94  wchar_t toWchar() const
95  { return wchar_t(value()); }
96 
97  static Char null()
98  {
99  return Char(0);
100  }
101 
102  Char& operator=(const Char& ch)
103  { _value = ch._value; return *this; }
104 
110  { return _value; }
111 
120  operator value_type() const
121  { return _value; }
122 
125  friend bool operator==(const Char& a, const Char& b)
126  { return a.value() == b.value(); }
127  friend bool operator==(const Char& a, wchar_t b)
128  { return a.value() == b; }
129  friend bool operator==(wchar_t a, const Char& b)
130  { return a == b.value(); }
131  friend bool operator==(const Char& a, char b)
132  { return a.value() == b; }
133  friend bool operator==(char a, const Char& b)
134  { return a == b.value(); }
135 
138  friend bool operator!=(const Char& a, const Char& b)
139  { return a.value() != b.value(); }
140  friend bool operator!=(const Char& a, wchar_t b)
141  { return a.value() != b; }
142  friend bool operator!=(wchar_t a, const Char& b)
143  { return a != b.value(); }
144  friend bool operator!=(const Char& a, char b)
145  { return a.value() != b; }
146  friend bool operator!=(char a, const Char& b)
147  { return a != b.value(); }
148 
151  friend bool operator<(const Char& a, const Char& b)
152  { return a.value() < b.value(); }
153  friend bool operator<(const Char& a, wchar_t b)
154  { return a.value() < b; }
155  friend bool operator<(wchar_t a, const Char& b)
156  { return a < b.value(); }
157  friend bool operator<(const Char& a, char b)
158  { return a.value() < b; }
159  friend bool operator<(char a, const Char& b)
160  { return a < b.value(); }
161 
164  friend bool operator>(const Char& a, const Char& b)
165  { return a.value() > b.value(); }
166  friend bool operator>(const Char& a, wchar_t b)
167  { return a.value() > b; }
168  friend bool operator>(wchar_t a, const Char& b)
169  { return a > b.value(); }
170  friend bool operator>(const Char& a, char b)
171  { return a.value() > b; }
172  friend bool operator>(char a, const Char& b)
173  { return a > b.value(); }
174 
177  friend bool operator<=(const Char& a, const Char& b)
178  { return a.value() <= b.value(); }
179  friend bool operator<=(const Char& a, wchar_t b)
180  { return a.value() <= b; }
181  friend bool operator<=(wchar_t a, const Char& b)
182  { return a <= b.value(); }
183  friend bool operator<=(const Char& a, char b)
184  { return a.value() <= b; }
185  friend bool operator<=(char a, const Char& b)
186  { return a <= b.value(); }
187 
190  friend bool operator>=(const Char& a, const Char& b)
191  { return a.value() >= b.value(); }
192  friend bool operator>=(const Char& a, wchar_t b)
193  { return a.value() >= b; }
194  friend bool operator>=(wchar_t a, const Char& b)
195  { return a >= b.value(); }
196  friend bool operator>=(const Char& a, char b)
197  { return a.value() >= b; }
198  friend bool operator>=(char a, const Char& b)
199  { return a >= b.value(); }
200 
201  private:
202  value_type _value;
203  };
204 
206  struct MBState
207  {
208  MBState()
209  : n(0)
210  {}
211 
212  uint8_t n;
213  union {
214  Char::value_type wchars[4];
215  char mbytes[16];
216  } value;
217  };
219 
220  std::ostream& operator<< (std::ostream& out, Char ch);
221 
222 } // namespace cxxtools
223 
224 
225 namespace std {
226 
228  template<>
229  struct char_traits<cxxtools::Char>
230  {
231  typedef cxxtools::Char char_type;
232  typedef cxxtools::Char::value_type int_type;
233  typedef std::streamoff off_type;
234  typedef std::streampos pos_type;
235  typedef cxxtools::MBState state_type;
236 
237  inline static void assign(char_type& c1, const char_type& c2);
238 
239  inline static bool eq(const char_type& c1, const char_type& c2);
240 
241  inline static bool lt(const char_type& c1, const char_type& c2);
242 
243  inline static int compare(const char_type* c1, const char_type* c2, size_t n);
244 
245  inline static size_t length(const char_type* s);
246 
247  inline static const char_type* find(const char_type* s, size_t n, const char_type& a);
248 
249  inline static char_type* move(char_type* s1, const char_type* s2, int_type n);
250 
251  inline static char_type* copy(char_type* s1, const char_type* s2, size_t n);
252 
253  inline static char_type* assign(char_type* s, size_t n, char_type a);
254 
255  inline static char_type to_char_type(const int_type& c);
256 
257  inline static int_type to_int_type(const char_type& c);
258 
259  inline static bool eq_int_type(const int_type& c1, const int_type& c2);
260 
261  inline static int_type eof();
262 
263  inline static int_type not_eof(const int_type& c);
264  };
266 
267  inline void char_traits<cxxtools::Char>::assign(char_type& c1, const char_type& c2)
268  {
269  c1 = c2;
270  }
271 
272 
273  inline bool char_traits<cxxtools::Char>::eq(const char_type& c1, const char_type& c2)
274  {
275  return c1 == c2;
276  }
277 
278 
279  inline bool char_traits<cxxtools::Char>::lt(const char_type& c1, const char_type& c2)
280  {
281  return c1 < c2;
282  }
283 
284 
285  inline int char_traits<cxxtools::Char>::compare(const char_type* s1, const char_type* s2, size_t n)
286  {
287  while(n-- > 0)
288  {
289  if( !eq(*s1, *s2) )
290  return lt(*s1, *s2) ? -1 : +1;
291 
292  ++s1;
293  ++s2;
294  }
295 
296  return 0;
297  }
298 
299 
300  inline size_t char_traits<cxxtools::Char>::length(const char_type* s)
301  {
302  static const cxxtools::Char term(0);
303  std::size_t n = 0;
304  while( !eq(s[n], term) )
305  ++n;
306 
307  return n;
308  }
309 
310 
311  inline const char_traits<cxxtools::Char>::char_type*
312  char_traits<cxxtools::Char>::find(const char_type* s, size_t n, const char_type& a)
313  {
314  while(n-- > 0) {
315  if (*s == a)
316  return s;
317  ++s;
318  }
319 
320  return 0;
321  }
322 
323 
324  inline char_traits<cxxtools::Char>::char_type*
325  char_traits<cxxtools::Char>::move(char_type* s1, const char_type* s2, int_type n)
326  {
327  return (cxxtools::Char*)std::memmove(s1, s2, n * sizeof(cxxtools::Char));
328  }
329 
330 
331  inline char_traits<cxxtools::Char>::char_type*
332  char_traits<cxxtools::Char>::copy(char_type* s1, const char_type* s2, size_t n)
333  {
334  return (cxxtools::Char*)std::memcpy(s1, s2, n * sizeof(cxxtools::Char));
335  }
336 
337 
338  inline char_traits<cxxtools::Char>::char_type*
339  char_traits<cxxtools::Char>::assign(char_type* s, size_t n, char_type a)
340  {
341  while(n-- > 0) {
342  *(s++) = a;
343  }
344 
345  return s;
346  }
347 
348 
349  inline char_traits<cxxtools::Char>::char_type
350  char_traits<cxxtools::Char>::to_char_type(const int_type& c)
351  {
352  return char_type(c);
353  }
354 
355 
356  inline char_traits<cxxtools::Char>::int_type
357  char_traits<cxxtools::Char>::to_int_type(const char_type& c)
358  {
359  return c.value();
360  }
361 
362 
363  inline bool char_traits<cxxtools::Char>::eq_int_type(const int_type& c1, const int_type& c2)
364  {
365  return c1 == c2;
366  }
367 
368 
369  inline char_traits<cxxtools::Char>::int_type char_traits<cxxtools::Char>::eof()
370  {
371  return static_cast<char_traits<cxxtools::Char>::int_type>( cxxtools::Char::value_type(-1) );
372  }
373 
374 
375  inline char_traits<cxxtools::Char>::int_type char_traits<cxxtools::Char>::not_eof(const int_type& c)
376  {
377  return eq_int_type(c, eof()) ? 0 : c;
378  }
379 
380 } // namespace std
381 
382 namespace cxxtools {
383 
384  inline char Char::narrow(char def) const
385  {
386  if( _value == std::char_traits<Char>::eof() )
387  {
388  return std::char_traits<char>::eof();
389  }
390 
391  if( _value <= 0xff )
392  {
393  return (char)_value;
394  }
395 
396  return def;
397  }
398 } // namespace cxxtools
399 
400 #ifdef CXXTOOLS_WITH_STD_LOCALE
401 
402 #include <locale>
403 
404 namespace std {
405 
406 #if (defined _MSC_VER || defined __QNX__ || defined __xlC__)
407 
411  template <>
412  class ctype< cxxtools::Char > : public ctype_base {
413 
414 #else
415 
418  template <>
419  class ctype<cxxtools::Char> : public ctype_base, public locale::facet {
420 
421 #endif
422 
423  public:
424  typedef ctype_base::mask mask;
425 
426  static locale::id id;
427  virtual locale::id& __get_id (void) const { return id; }
428 
429  public:
430  explicit ctype(size_t refs = 0);
431 
432  virtual ~ctype();
433 
434  bool is(mask m, cxxtools::Char c) const
435  { return this->do_is(m, c); }
436 
437  const cxxtools::Char* is(const cxxtools::Char *lo, const cxxtools::Char *hi, mask *vec) const
438  { return this->do_is(lo, hi, vec); }
439 
440  const cxxtools::Char* scan_is(mask m, const cxxtools::Char* lo, const cxxtools::Char* hi) const
441  { return this->do_scan_is(m, lo, hi); }
442 
443  const cxxtools::Char* scan_not(mask m, const cxxtools::Char* lo, const cxxtools::Char* hi) const
444  { return this->do_scan_not(m, lo, hi); }
445 
447  { return this->do_toupper(c); }
448 
449  const cxxtools::Char* toupper(cxxtools::Char *lo, const cxxtools::Char* hi) const
450  { return this->do_toupper(lo, hi); }
451 
453  { return this->do_tolower(c); }
454 
455  const cxxtools::Char* tolower(cxxtools::Char* lo, const cxxtools::Char* hi) const
456  { return this->do_tolower(lo, hi); }
457 
458  cxxtools::Char widen(char c) const
459  { return this->do_widen(c); }
460 
461  const char* widen(const char* lo, const char* hi, cxxtools::Char* to) const
462  { return this->do_widen(lo, hi, to); }
463 
464  char narrow(cxxtools::Char c, char dfault) const
465  { return this->do_narrow(c, dfault); }
466 
467  const cxxtools::Char* narrow(const cxxtools::Char* lo, const cxxtools::Char* hi,
468  char dfault, char *to) const
469  { return this->do_narrow(lo, hi, dfault, to); }
470 
471  protected:
472  virtual bool do_is(mask m, cxxtools::Char c) const;
473 
474  virtual const cxxtools::Char* do_is(const cxxtools::Char* lo, const cxxtools::Char* hi,
475  mask* vec) const;
476 
477  virtual const cxxtools::Char* do_scan_is(mask m, const cxxtools::Char* lo,
478  const cxxtools::Char* hi) const;
479 
480  virtual const cxxtools::Char* do_scan_not(mask m, const cxxtools::Char* lo,
481  const cxxtools::Char* hi) const;
482 
483  virtual cxxtools::Char do_toupper(cxxtools::Char) const;
484 
485  virtual const cxxtools::Char* do_toupper(cxxtools::Char* lo, const cxxtools::Char* hi) const;
486 
487  virtual cxxtools::Char do_tolower(cxxtools::Char) const;
488 
489  virtual const cxxtools::Char* do_tolower(cxxtools::Char* lo, const cxxtools::Char* hi) const;
490 
491  virtual cxxtools::Char do_widen(char) const;
492 
493  virtual const char* do_widen(const char* lo, const char* hi,
494  cxxtools::Char* dest) const;
495 
496  virtual char do_narrow(cxxtools::Char, char dfault) const;
497 
498  virtual const cxxtools::Char* do_narrow(const cxxtools::Char* lo, const cxxtools::Char* hi,
499  char dfault, char* dest) const;
500 };
501 
502 } // namespace std
503 
504 #else
505 
506 namespace std {
507 
509 {
510  public:
511  enum {
512  alpha = 1 << 5,
513  cntrl = 1 << 2,
514  digit = 1 << 6,
515  lower = 1 << 4,
516  print = 1 << 1,
517  punct = 1 << 7,
518  space = 1 << 0,
519  upper = 1 << 3,
520  xdigit = 1 << 8,
521  alnum = alpha | digit,
522  graph = alnum | punct
523  };
524 
525  typedef unsigned short mask;
526 
527  ctype_base(size_t _refs = 0)
528  { }
529 };
530 
531 }
532 
533 #endif
534 
535 namespace cxxtools {
536 
537 std::ctype_base::mask ctypeMask(const Char& ch);
538 
539 inline int isalpha(const Char& ch)
540 {
541  return ctypeMask(ch) & std::ctype_base::alpha;
542 }
543 
544 inline int isalnum(const Char& ch)
545 {
546  return ctypeMask(ch) & std::ctype_base::alnum;
547 }
548 
549 inline int ispunct(const Char& ch)
550 {
551  return ctypeMask(ch) & std::ctype_base::punct;
552 }
553 
554 inline int iscntrl(const Char& ch)
555 {
556  return ctypeMask(ch) & std::ctype_base::cntrl;
557 }
558 
559 inline int isdigit(const Char& ch)
560 {
561  return ctypeMask(ch) & std::ctype_base::digit;
562 }
563 
564 inline int isxdigit(const Char& ch)
565 {
566  return ctypeMask(ch) & std::ctype_base::xdigit;
567 }
568 
569 inline int isgraph(const Char& ch)
570 {
571  return ctypeMask(ch) & std::ctype_base::graph;
572 }
573 
574 inline int islower(const Char& ch)
575 {
576  return ctypeMask(ch) & std::ctype_base::lower;
577 }
578 
579 inline int isupper(const Char& ch)
580 {
581  return ctypeMask(ch) & std::ctype_base::upper;
582 }
583 
584 inline int isprint(const Char& ch)
585 {
586  return ctypeMask(ch) & std::ctype_base::print;
587 }
588 
589 inline int isspace(const Char& ch)
590 {
591  return ctypeMask(ch) & std::ctype_base::space;
592 }
593 
594 Char tolower(const Char& ch);
595 
596 Char toupper(const Char& ch);
597 
598 } // namespace cxxtools
599 
600 #ifdef CXXTOOLS_WITH_STD_LOCALE
601 #include <cxxtools/facets.h>
602 #endif
603 
604 #endif