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/api.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 
76  Char(char ch)
77  : _value(value_type(static_cast<unsigned char>(ch)))
78  {}
79 
81  Char(unsigned char ch)
82  : _value( value_type(ch) )
83  {}
84 
86  Char(wchar_t ch)
87  : _value( value_type(static_cast<uint16_t>(ch)) )
88  {}
89 
91  explicit Char(value_type ch)
92  : _value(ch)
93  {}
94 
107  char narrow(char def = '?') const;
108 
109  wchar_t toWchar() const
110  { return wchar_t(value()); }
111 
112  static Char null()
113  {
114  return Char(0);
115  }
116 
117  Char& operator=(const Char& ch)
118  { _value = ch._value; return *this; }
119 
125  { return _value; }
126 
135  operator value_type() const
136  { return _value; }
137 
140  friend bool operator==(const Char& a, const Char& b)
141  { return a.value() == b.value(); }
142  friend bool operator==(const Char& a, wchar_t b)
143  { return a.value() == b; }
144  friend bool operator==(wchar_t a, const Char& b)
145  { return a == b.value(); }
146  friend bool operator==(const Char& a, char b)
147  { return a.value() == b; }
148  friend bool operator==(char a, const Char& b)
149  { return a == b.value(); }
150 
153  friend bool operator!=(const Char& a, const Char& b)
154  { return a.value() != b.value(); }
155  friend bool operator!=(const Char& a, wchar_t b)
156  { return a.value() != b; }
157  friend bool operator!=(wchar_t a, const Char& b)
158  { return a != b.value(); }
159  friend bool operator!=(const Char& a, char b)
160  { return a.value() != b; }
161  friend bool operator!=(char a, const Char& b)
162  { return a != b.value(); }
163 
166  friend bool operator<(const Char& a, const Char& b)
167  { return a.value() < b.value(); }
168  friend bool operator<(const Char& a, wchar_t b)
169  { return a.value() < b; }
170  friend bool operator<(wchar_t a, const Char& b)
171  { return a < b.value(); }
172  friend bool operator<(const Char& a, char b)
173  { return a.value() < b; }
174  friend bool operator<(char a, const Char& b)
175  { return a < b.value(); }
176 
179  friend bool operator>(const Char& a, const Char& b)
180  { return a.value() > b.value(); }
181  friend bool operator>(const Char& a, wchar_t b)
182  { return a.value() > b; }
183  friend bool operator>(wchar_t a, const Char& b)
184  { return a > b.value(); }
185  friend bool operator>(const Char& a, char b)
186  { return a.value() > b; }
187  friend bool operator>(char a, const Char& b)
188  { return a > b.value(); }
189 
192  friend bool operator<=(const Char& a, const Char& b)
193  { return a.value() <= b.value(); }
194  friend bool operator<=(const Char& a, wchar_t b)
195  { return a.value() <= b; }
196  friend bool operator<=(wchar_t a, const Char& b)
197  { return a <= b.value(); }
198  friend bool operator<=(const Char& a, char b)
199  { return a.value() <= b; }
200  friend bool operator<=(char a, const Char& b)
201  { return a <= b.value(); }
202 
205  friend bool operator>=(const Char& a, const Char& b)
206  { return a.value() >= b.value(); }
207  friend bool operator>=(const Char& a, wchar_t b)
208  { return a.value() >= b; }
209  friend bool operator>=(wchar_t a, const Char& b)
210  { return a >= b.value(); }
211  friend bool operator>=(const Char& a, char b)
212  { return a.value() >= b; }
213  friend bool operator>=(char a, const Char& b)
214  { return a >= b.value(); }
215 
216  private:
217  value_type _value;
218  };
219 
220  struct MBState
221  {
223  : n(0)
224  {}
225 
226  int n;
227  union {
229  char mbytes[16];
230  } value;
231  };
232 
233  CXXTOOLS_API std::ostream& operator<< (std::ostream& out, Char ch);
234 
235 } // namespace cxxtools
236 
237 
238 namespace std {
239 
241  template<>
242  struct char_traits<cxxtools::Char>
243  {
244  typedef cxxtools::Char char_type;
245  typedef cxxtools::Char::value_type int_type;
246  typedef std::streamoff off_type;
247  typedef std::streampos pos_type;
248  typedef cxxtools::MBState state_type;
249 
250  inline static void assign(char_type& c1, const char_type& c2);
251 
252  inline static bool eq(const char_type& c1, const char_type& c2);
253 
254  inline static bool lt(const char_type& c1, const char_type& c2);
255 
256  inline static int compare(const char_type* c1, const char_type* c2, size_t n);
257 
258  inline static size_t length(const char_type* s);
259 
260  inline static const char_type* find(const char_type* s, size_t n, const char_type& a);
261 
262  inline static char_type* move(char_type* s1, const char_type* s2, int_type n);
263 
264  inline static char_type* copy(char_type* s1, const char_type* s2, size_t n);
265 
266  inline static char_type* assign(char_type* s, size_t n, char_type a);
267 
268  inline static char_type to_char_type(const int_type& c);
269 
270  inline static int_type to_int_type(const char_type& c);
271 
272  inline static bool eq_int_type(const int_type& c1, const int_type& c2);
273 
274  inline static int_type eof();
275 
276  inline static int_type not_eof(const int_type& c);
277  };
278 
279  inline void char_traits<cxxtools::Char>::assign(char_type& c1, const char_type& c2)
280  {
281  c1 = c2;
282  }
283 
284 
285  inline bool char_traits<cxxtools::Char>::eq(const char_type& c1, const char_type& c2)
286  {
287  return c1 == c2;
288  }
289 
290 
291  inline bool char_traits<cxxtools::Char>::lt(const char_type& c1, const char_type& c2)
292  {
293  return c1 < c2;
294  }
295 
296 
297  inline int char_traits<cxxtools::Char>::compare(const char_type* s1, const char_type* s2, size_t n)
298  {
299  while(n-- > 0)
300  {
301  if( !eq(*s1, *s2) )
302  return lt(*s1, *s2) ? -1 : +1;
303 
304  ++s1;
305  ++s2;
306  }
307 
308  return 0;
309  }
310 
311 
312  inline size_t char_traits<cxxtools::Char>::length(const char_type* s)
313  {
314  static const cxxtools::Char term(0);
315  std::size_t n = 0;
316  while( !eq(s[n], term) )
317  ++n;
318 
319  return n;
320  }
321 
322 
323  inline const char_traits<cxxtools::Char>::char_type*
324  char_traits<cxxtools::Char>::find(const char_type* s, size_t n, const char_type& a)
325  {
326  while(n-- > 0) {
327  if (*s == a)
328  return s;
329  ++s;
330  }
331 
332  return 0;
333  }
334 
335 
336  inline char_traits<cxxtools::Char>::char_type*
337  char_traits<cxxtools::Char>::move(char_type* s1, const char_type* s2, int_type n)
338  {
339  return (cxxtools::Char*)std::memmove(s1, s2, n * sizeof(cxxtools::Char));
340  }
341 
342 
343  inline char_traits<cxxtools::Char>::char_type*
344  char_traits<cxxtools::Char>::copy(char_type* s1, const char_type* s2, size_t n)
345  {
346  return (cxxtools::Char*)std::memcpy(s1, s2, n * sizeof(cxxtools::Char));
347  }
348 
349 
350  inline char_traits<cxxtools::Char>::char_type*
351  char_traits<cxxtools::Char>::assign(char_type* s, size_t n, char_type a)
352  {
353  while(n-- > 0) {
354  *(s++) = a;
355  }
356 
357  return s;
358  }
359 
360 
361  inline char_traits<cxxtools::Char>::char_type
362  char_traits<cxxtools::Char>::to_char_type(const int_type& c)
363  {
364  return char_type(c);
365  }
366 
367 
368  inline char_traits<cxxtools::Char>::int_type
369  char_traits<cxxtools::Char>::to_int_type(const char_type& c)
370  {
371  return c.value();
372  }
373 
374 
375  inline bool char_traits<cxxtools::Char>::eq_int_type(const int_type& c1, const int_type& c2)
376  {
377  return c1 == c2;
378  }
379 
380 
381  inline char_traits<cxxtools::Char>::int_type char_traits<cxxtools::Char>::eof()
382  {
383  return static_cast<char_traits<cxxtools::Char>::int_type>( cxxtools::Char::value_type(-1) );
384  }
385 
386 
387  inline char_traits<cxxtools::Char>::int_type char_traits<cxxtools::Char>::not_eof(const int_type& c)
388  {
389  return eq_int_type(c, eof()) ? 0 : c;
390  }
391 
392 } // namespace std
393 
394 namespace cxxtools {
395 
396  inline char Char::narrow(char def) const
397  {
398  if( _value == std::char_traits<Char>::eof() )
399  {
400  return std::char_traits<char>::eof();
401  }
402 
403  if( _value <= 0xff )
404  {
405  return (char)_value;
406  }
407 
408  return def;
409  }
410 } // namespace cxxtools
411 
412 #ifdef CXXTOOLS_WITH_STD_LOCALE
413 
414 #include <locale>
415 
416 namespace std {
417 
418 #if (defined _MSC_VER || defined __QNX__ || defined __xlC__)
419 
423  template <>
424  class CXXTOOLS_API ctype< cxxtools::Char > : public ctype_base {
425 
426 #else
427 
430  template <>
431  class CXXTOOLS_API ctype<cxxtools::Char> : public ctype_base, public locale::facet {
432 
433 #endif
434 
435  public:
436  typedef ctype_base::mask mask;
437 
438  static locale::id id;
439  virtual locale::id& __get_id (void) const { return id; }
440 
441  public:
442  explicit ctype(size_t refs = 0);
443 
444  virtual ~ctype();
445 
446  bool is(mask m, cxxtools::Char c) const
447  { return this->do_is(m, c); }
448 
449  const cxxtools::Char* is(const cxxtools::Char *lo, const cxxtools::Char *hi, mask *vec) const
450  { return this->do_is(lo, hi, vec); }
451 
452  const cxxtools::Char* scan_is(mask m, const cxxtools::Char* lo, const cxxtools::Char* hi) const
453  { return this->do_scan_is(m, lo, hi); }
454 
455  const cxxtools::Char* scan_not(mask m, const cxxtools::Char* lo, const cxxtools::Char* hi) const
456  { return this->do_scan_not(m, lo, hi); }
457 
458  cxxtools::Char toupper(cxxtools::Char c) const
459  { return this->do_toupper(c); }
460 
461  const cxxtools::Char* toupper(cxxtools::Char *lo, const cxxtools::Char* hi) const
462  { return this->do_toupper(lo, hi); }
463 
464  cxxtools::Char tolower(cxxtools::Char c) const
465  { return this->do_tolower(c); }
466 
467  const cxxtools::Char* tolower(cxxtools::Char* lo, const cxxtools::Char* hi) const
468  { return this->do_tolower(lo, hi); }
469 
470  cxxtools::Char widen(char c) const
471  { return this->do_widen(c); }
472 
473  const char* widen(const char* lo, const char* hi, cxxtools::Char* to) const
474  { return this->do_widen(lo, hi, to); }
475 
476  char narrow(cxxtools::Char c, char dfault) const
477  { return this->do_narrow(c, dfault); }
478 
479  const cxxtools::Char* narrow(const cxxtools::Char* lo, const cxxtools::Char* hi,
480  char dfault, char *to) const
481  { return this->do_narrow(lo, hi, dfault, to); }
482 
483  protected:
484  virtual bool do_is(mask m, cxxtools::Char c) const;
485 
486  virtual const cxxtools::Char* do_is(const cxxtools::Char* lo, const cxxtools::Char* hi,
487  mask* vec) const;
488 
489  virtual const cxxtools::Char* do_scan_is(mask m, const cxxtools::Char* lo,
490  const cxxtools::Char* hi) const;
491 
492  virtual const cxxtools::Char* do_scan_not(mask m, const cxxtools::Char* lo,
493  const cxxtools::Char* hi) const;
494 
495  virtual cxxtools::Char do_toupper(cxxtools::Char) const;
496 
497  virtual const cxxtools::Char* do_toupper(cxxtools::Char* lo, const cxxtools::Char* hi) const;
498 
499  virtual cxxtools::Char do_tolower(cxxtools::Char) const;
500 
501  virtual const cxxtools::Char* do_tolower(cxxtools::Char* lo, const cxxtools::Char* hi) const;
502 
503  virtual cxxtools::Char do_widen(char) const;
504 
505  virtual const char* do_widen(const char* lo, const char* hi,
506  cxxtools::Char* dest) const;
507 
508  virtual char do_narrow(cxxtools::Char, char dfault) const;
509 
510  virtual const cxxtools::Char* do_narrow(const cxxtools::Char* lo, const cxxtools::Char* hi,
511  char dfault, char* dest) const;
512 };
513 
514 } // namespace std
515 
516 #else
517 
518 namespace std {
519 
520 class ctype_base
521 {
522  public:
523  enum {
524  alpha = 1 << 5,
525  cntrl = 1 << 2,
526  digit = 1 << 6,
527  lower = 1 << 4,
528  print = 1 << 1,
529  punct = 1 << 7,
530  space = 1 << 0,
531  upper = 1 << 3,
532  xdigit = 1 << 8,
533  alnum = alpha | digit,
534  graph = alnum | punct
535  };
536 
537  typedef unsigned short mask;
538 
539  ctype_base(size_t _refs = 0)
540  { }
541 };
542 
543 }
544 
545 #endif
546 
547 namespace cxxtools {
548 
549 CXXTOOLS_API std::ctype_base::mask ctypeMask(const Char& ch);
550 
551 inline int isalpha(const Char& ch)
552 {
553  return ctypeMask(ch) & std::ctype_base::alpha;
554 }
555 
556 inline int isalnum(const Char& ch)
557 {
558  return ctypeMask(ch) & std::ctype_base::alnum;
559 }
560 
561 inline int ispunct(const Char& ch)
562 {
563  return ctypeMask(ch) & std::ctype_base::punct;
564 }
565 
566 inline int iscntrl(const Char& ch)
567 {
568  return ctypeMask(ch) & std::ctype_base::cntrl;
569 }
570 
571 inline int isdigit(const Char& ch)
572 {
573  return ctypeMask(ch) & std::ctype_base::digit;
574 }
575 
576 inline int isxdigit(const Char& ch)
577 {
578  return ctypeMask(ch) & std::ctype_base::xdigit;
579 }
580 
581 inline int isgraph(const Char& ch)
582 {
583  return ctypeMask(ch) & std::ctype_base::graph;
584 }
585 
586 inline int islower(const Char& ch)
587 {
588  return ctypeMask(ch) & std::ctype_base::lower;
589 }
590 
591 inline int isupper(const Char& ch)
592 {
593  return ctypeMask(ch) & std::ctype_base::upper;
594 }
595 
596 inline int isprint(const Char& ch)
597 {
598  return ctypeMask(ch) & std::ctype_base::print;
599 }
600 
601 inline int isspace(const Char& ch)
602 {
603  return ctypeMask(ch) & std::ctype_base::space;
604 }
605 
606 CXXTOOLS_API Char tolower(const Char& ch);
607 
608 CXXTOOLS_API Char toupper(const Char& ch);
609 
610 } // namespace cxxtools
611 
612 #ifdef CXXTOOLS_WITH_STD_LOCALE
613 #include <cxxtools/facets.h>
614 #endif
615 
616 #endif