Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
wctype.cpp
Go to the documentation of this file.
1
29#define _RWSTD_LIB_SRC
30
31#include <rw/_defs.h>
32
33#ifndef _RWSTD_NO_WCHAR_T
34
35#include <ctype.h>
36#include <limits.h>
37#include <locale.h>
38
39#ifndef _RWSTD_NO_WCHAR_H
40# include <wchar.h> // for wctob()
41#endif // _RWSTD_NO_WCHAR_H
42
43#include <stdlib.h> // for wctomb()
44#include <string.h> // for memset()
45#include <wctype.h> // for iswspace(), ...
46
47#include <loc/_ctype.h>
48#include <loc/_locale.h>
49#include <loc/_localedef.h>
50
51#include "setlocale.h"
52#include "use_facet.h"
53
54#ifdef _RWSTD_NO_EQUAL_CTYPE_MASK
55# include "once.h" // for __rw_once()
56#endif // _RWSTD_NO_EQUAL_CTYPE_MASK
57
58// utf8 encoding maximum size
59#undef _UTF8_MB_CUR_MAX
60#define _UTF8_MB_CUR_MAX 6
61
62
64
65typedef _STD::ctype_base::mask MaskT;
66
67extern const MaskT __rw_classic_tab [];
68extern const unsigned char __rw_upper_tab [];
69extern const unsigned char __rw_lower_tab [];
70
71
72static const wchar_t*
73__rw_get_mask (__rw_ctype_t *impl,
74 const wchar_t *beg,
75 const wchar_t *end,
76 MaskT mask,
77 MaskT *vec,
78 bool scan_is,
79 bool use_libstd,
80 const char *locname)
81{
82 _RWSTD_ASSERT (!end || beg <= end);
83
84 if (use_libstd && impl != 0) {
85
86 for (; beg != end; ++beg) {
87
88 // using binary search look up the character and its mask
89 _RWSTD_SIZE_T low = 0;
90 _RWSTD_SIZE_T high = (_RWSTD_SIZE_T)impl->wmask_s;
91
92 if (vec)
93 *vec = MaskT ();
94
95 while (low <= high) {
96
97 const _RWSTD_SIZE_T cur = (low + high) / 2;
98 const __rw_mask_elm next_elm = impl->wmask_tab (cur);
99
100 if (next_elm.ch == *beg) {
101
102 // character found
103 // if vec is non-0, fill it with the character's mask
104 // otherwise, if scanning for a match and the char's
105 // mask matches, or if scanning for a mismatch and
106 // the char's mask does not match, return the pointer
107 // to the current character; otherwise continue
108 if (vec)
109 *vec = MaskT (next_elm.mask & mask);
110 else if ( scan_is && next_elm.mask & mask
111 || !scan_is && !(next_elm.mask & mask))
112 return beg;
113
114 break;
115 }
116
117 // convert both sides to a sufficiently large type
118 // with the same signedness
119 if ( _RWSTD_STATIC_CAST (_RWSTD_UINT32_T, next_elm.ch)
120 < _RWSTD_STATIC_CAST (_RWSTD_UINT32_T, *beg))
121 low = cur + 1;
122 else
123 high = cur - 1;
124 }
125
126 if (vec)
127 ++vec;
128 }
129
130 return beg;
131 }
132
133 const __rw_setlocale clocale (locname, LC_CTYPE);
134
135 for (; beg != end; ++beg) {
136
137 int m = 0;
138
139 // does the value of *beg fit into the range of an unsigned char?
140 const bool fits_char =
141 _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, *beg) <= _RWSTD_UCHAR_MAX;
142
143 // `fits_char' is not used if all wide character
144 // classification functions use below are present
145 _RWSTD_UNUSED (fits_char);
146
147 if (mask & __rw_space) {
148#ifndef _RWSTD_NO_ISWSPACE
149 if ((::iswspace)(*beg))
150#else
151 if (fits_char && (::isspace)(*beg))
152#endif // _RWSTD_NO_ISWSPACE
153 m |= __rw_space;
154 }
155
156 if (mask & __rw_print) {
157#ifndef _RWSTD_NO_ISWPRINT
158 if ((::iswprint)(*beg))
159#else
160 if (fits_char && (::isprint)(*beg))
161#endif // _RWSTD_NO_ISWPRINT
162 m |= __rw_print;
163 }
164
165 if (mask & __rw_cntrl) {
166#ifndef _RWSTD_NO_ISWCNTRL
167 if ((::iswcntrl)(*beg))
168#else
169 if (fits_char && (::iscntrl)(*beg))
170#endif // _RWSTD_NO_ISWCNTRL
171 m |= __rw_cntrl;
172 }
173
174 if (mask & __rw_upper) {
175#ifndef _RWSTD_NO_ISWUPPER
176 if ((::iswupper)(*beg))
177#else
178 if (fits_char && (::isupper)(*beg))
179#endif // _RWSTD_NO_ISWUPPER
180 m |= __rw_upper;
181 }
182
183 if (mask & __rw_lower) {
184#ifndef _RWSTD_NO_ISWLOWER
185 if ((::iswlower)(*beg))
186#else
187 if (fits_char && (::islower)(*beg))
188#endif // _RWSTD_NO_ISWLOWER
189 m |= __rw_lower;
190 }
191
192 if (mask & __rw_alpha) {
193#ifndef _RWSTD_NO_ISWALPHA
194 if ((::iswalpha)(*beg))
195#else
196 if (fits_char && (::isalpha)(*beg))
197#endif // _RWSTD_NO_ISWALPHA
198 m |= __rw_alpha;
199 }
200
201 if (mask & __rw_digit) {
202#ifndef _RWSTD_NO_ISWDIGIT
203 if ((::iswdigit)(*beg))
204#else
205 if (fits_char && (::isdigit)(*beg))
206#endif
207 m |= __rw_digit;
208 }
209
210 if (mask & __rw_punct) {
211#ifndef _RWSTD_NO_ISWPUNCT
212 if ((::iswpunct)(*beg))
213#else
214 if (fits_char && (::ispunct)(*beg))
215#endif // _RWSTD_NO_ISWPUNCT
216 m |= __rw_punct;
217 }
218
219 if (mask & __rw_xdigit) {
220#ifndef _RWSTD_NO_ISWXDIGIT
221 if ((::iswxdigit)(*beg))
222#else
223 if (fits_char && (::isxdigit) (*beg))
224#endif // _RWSTD_NO_ISWXDIGIT
225 m |= __rw_xdigit;
226 }
227
228 if (mask & __rw_graph) {
229#ifndef _RWSTD_NO_ISWGRAPH
230 if ((::iswgraph)(*beg))
231#else
232 if (fits_char && (::isgraph)(*beg))
233#endif // _RWSTD_NO_ISWGRAPH
234 m |= __rw_graph;
235 }
236
237 if (vec)
238 *vec++ = MaskT (m);
239 else if (scan_is && m & mask || !scan_is && !(m & mask))
240 break;
241 }
242
243 return beg;
244}
245
246
247static _STD::ctype_byname<wchar_t>::char_type
248__rw_toupper (__rw_ctype_t* impl,
249 wchar_t c, bool use_libstd,
250 const char* locname)
251{
252 if (use_libstd && impl != 0) {
253
254 _RWSTD_SIZE_T low = 0;
255 _RWSTD_SIZE_T high = (_RWSTD_SIZE_T)impl->wtoupper_s();
256 _RWSTD_SIZE_T cur;
257
258 __rw_upper_elm next_elm;
259
260 while (low <= high) {
261 cur = (low + high) / 2;
262 next_elm = impl->wtoupper_tab(cur);
263 if (next_elm.lower == c) {
264 c = next_elm.upper;
265 break;
266 }
267
268 // convert both sides to a sufficiently large type
269 // with the same signedness
270 if ( _RWSTD_STATIC_CAST (_RWSTD_UINT32_T, next_elm.lower)
271 < _RWSTD_STATIC_CAST (_RWSTD_UINT32_T, c))
272 low = cur + 1;
273 else
274 high = cur - 1;
275 }
276 }
277 else {
278
279#ifndef _RWSTD_NO_TOWUPPER
280
281 const __rw_setlocale clocale (locname, LC_CTYPE);
282
283 c = (::towupper)(c);
284
285#else // if defined (_RWSTD_NO_TOWUPPER)
286
287 if (_RWSTD_STATIC_CAST (_RWSTD_SIZE_T, c) <= _RWSTD_UCHAR_MAX) {
288
289 const __rw_setlocale clocale (locname, LC_CTYPE);
290
291 c = (::toupper)(c);
292 }
293
294#endif // _RWSTD_NO_TOWUPPER
295
296 }
297
298 return c;
299}
300
301
302static _STD::ctype_byname<wchar_t>::char_type
303__rw_tolower (__rw_ctype_t* impl,
304 wchar_t c, bool use_libstd,
305 const char* locname)
306{
307 if (use_libstd && impl != 0) {
308
309 _RWSTD_SIZE_T low = 0;
310 _RWSTD_SIZE_T high = (_RWSTD_SIZE_T)impl->wtolower_s ();
311 _RWSTD_SIZE_T cur;
312
313 __rw_lower_elm next_elm;
314
315 while (low <= high) {
316 cur = (low + high) / 2;
317 next_elm = impl->wtolower_tab(cur);
318 if (next_elm.upper == c) {
319 c = next_elm.lower;
320 break;
321 }
322
323 // convert both sides to a sufficiently large type
324 // with the same signedness
325 if ( _RWSTD_STATIC_CAST (_RWSTD_UINT32_T, next_elm.upper)
326 < _RWSTD_STATIC_CAST (_RWSTD_UINT32_T, c))
327 low = cur + 1;
328 else
329 high = cur - 1;
330 }
331 }
332 else {
333
334#ifndef _RWSTD_NO_TOWLOWER
335
336 const __rw_setlocale clocale (locname, LC_CTYPE);
337
338 c = (::towlower)(c);
339
340#else // if defined (_RWSTD_NO_TOWLOWER)
341
342 if (_RWSTD_STATIC_CAST (_RWSTD_SIZE_T, c) <= _RWSTD_UCHAR_MAX) {
343
344 const __rw_setlocale clocale (locname, LC_CTYPE);
345
346 c = (::tolower)(c);
347 }
348
349#endif // _RWSTD_NO_TOWLOWER
350
351 }
352
353 return c;
354}
355
356
357#if 0 // FIXME: implement analogously to the above
358
359static void
360__rw_narrow (const __rw_codecvt_t *cvt, bool use_libstd,
361 const wchar_t *lo, const wchar_t *hi, char dfault, char *dst)
362{
363}
364
365
366static void
367__rw_widen (const __rw_codecvt_t *cvt, bool use_libstd,
368 const char *lo, const char *hi, wchar_t *dst)
369{
370}
371
372#endif // 0/1
373
374#ifdef _RWSTD_NO_EQUAL_CTYPE_MASK
375
376// table of wide character classes
377static _STD::ctype_base::mask
378__rw_classic_wide_tab [_STD::ctype<char>::table_size];
379
380// init-once flag for the classic wide tab
381static __rw_once_t
382__rw_classic_wide_tab_once_init = _RWSTD_ONCE_INIT;
383
384extern "C" {
385
386// one-time initializer for the classic wide_tab
387static void
388__rw_init_classic_wide_tab ()
389{
390# ifdef _RWSTDDEBUG
391
392 static int init;
393
394 // paranoid check: verify that one-time initialization works
395 _RWSTD_ASSERT (0 == init);
396
397 ++init;
398
399# endif // _RWSTDDEBUG
400
401 // init the classic wide tab
402 wchar_t wc_array [_STD::ctype<char>::table_size];
403
404 for (wchar_t wc = 0; wc < _STD::ctype<char>::table_size; ++wc)
405 wc_array [wc] = wc;
406
407 __rw_get_mask (0, wc_array, wc_array + _STD::ctype<char>::table_size,
408 __rw_all, __rw_classic_wide_tab, false, false, "C");
409}
410
411} // extern "C"
412
413#endif // _RWSTD_NO_EQUAL_CTYPE_MASK
414
415} // namespace __rw
416
417
419
420
421_RW::__rw_facet_id ctype<wchar_t>::id;
422
423
424ctype<wchar_t>::ctype (_RWSTD_SIZE_T ref)
425 : _RW::__rw_facet (ref)
426{
427#ifndef _RWSTD_NO_EQUAL_CTYPE_MASK
428 _C_mask_tab = _RW::__rw_classic_tab;
429#else
430 // initialize classic wide tab exactly once
431 _RW::__rw_once (&_RW::__rw_classic_wide_tab_once_init,
432 _RW::__rw_init_classic_wide_tab);
433
434 _C_mask_tab = _RW::__rw_classic_wide_tab;
435#endif
436 _C_upper_tab = _RWSTD_CONST_CAST (_UChar*, _RW::__rw_upper_tab);
437 _C_lower_tab = _RWSTD_CONST_CAST (_UChar*, _RW::__rw_lower_tab);
438 _C_delete_it = false;
439
440 memset (_C_narrow_tab, 0, sizeof _C_narrow_tab);
441 memset (_C_wide_tab, 0, sizeof _C_wide_tab);
442}
443
444
445ctype<wchar_t>::~ctype ()
446{
447 if (_C_delete_it) {
448 delete[] _RWSTD_CONST_CAST (mask*, _C_mask_tab);
449
450 if (_C_upper_tab != _RW::__rw_upper_tab) {
451 // lower_tab is allocated in the same block of memory
452 // as upper_tab and must not be deleted
453 delete[] _C_upper_tab;
454 }
455 }
456}
457
458
459bool ctype<wchar_t>::
460do_is (mask m, char_type c) const
461{
462 return _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, c) <= _C_tab_size
463 && (_C_mask_tab [_UChar (c)] & m);
464}
465
466
467const ctype<wchar_t>::char_type*
468ctype<wchar_t>::
469do_is (const char_type *lo, const char_type *hi, mask *mvec) const
470{
471 _RWSTD_ASSERT (lo <= hi);
472
473 for ( ; lo != hi; ++lo, ++mvec) {
474 *mvec = _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, *lo) < _C_tab_size ?
475 _C_mask_tab [_UChar (*lo)] : mask (0);
476 }
477
478 return hi;
479
480}
481
482
483ctype<wchar_t>::char_type
484ctype<wchar_t>::
485do_widen (char c) const
486{
487 // explicitly specifying template argument list to work around
488 // HP aCC 3 and 5 bug (STDCXX-445)
489 return _RWSTD_CONST_CAST (ctype<wchar_t>*, this)->
490 _C_wide_tab [_UChar (c)] = char_type (_UChar (c));
491}
492
493
494const char*
495ctype<wchar_t>::
496do_widen (const char *lo, const char *hi, char_type *dest) const
497{
498 _RWSTD_ASSERT (lo <= hi);
499 while (lo < hi) {
500 // call widen instead of do_widen to take advantage of the
501 // table optimization
502 *dest++ = widen (*lo++);
503 }
504 return hi;
505}
506
507
508ctype<wchar_t>::char_type
509ctype<wchar_t>::
510do_toupper (char_type c) const
511{
512 return _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, c) < _C_tab_size ?
513 _C_upper_tab [_UChar (c)] : c;
514}
515
516
517ctype<wchar_t>::char_type
518ctype<wchar_t>::
519do_tolower (char_type c) const
520{
521 return _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, c) < _C_tab_size ?
522 _C_lower_tab [_UChar (c)] : c;
523}
524
525
526const ctype<wchar_t>::char_type*
527ctype<wchar_t>::
528do_toupper (char_type *lo, const char_type *hi) const
529{
530 _RWSTD_ASSERT (lo <= hi);
531
532 for ( ; lo < hi; ++lo)
533 *lo = _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, *lo) < _C_tab_size ?
534 _C_upper_tab [_UChar (*lo)] : 0;
535
536 return lo;
537}
538
539
540const ctype<wchar_t>::char_type*
541ctype<wchar_t>::
542do_tolower (char_type *lo, const char_type *hi) const
543{
544 _RWSTD_ASSERT (lo <= hi);
545
546 for ( ; lo < hi; ++lo)
547 *lo = _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, *lo) < _C_tab_size ?
548 _C_lower_tab [_UChar (*lo)] : 0;
549
550 return lo;
551}
552
553
554const ctype<wchar_t>::char_type*
555ctype<wchar_t>::
556do_scan_is (mask m, const char_type *lo, const char_type *hi) const
557{
558 _RWSTD_ASSERT (lo <= hi);
559
560 for ( ; lo != hi; ++lo) {
561 if ( _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, *lo) <= _C_tab_size
562 && (_C_mask_tab [_UChar (*lo)] & m))
563 break;
564 }
565
566 return lo;
567}
568
569
570const ctype<wchar_t>::char_type*
571ctype<wchar_t>::
572do_scan_not (mask m, const char_type *lo, const char_type *hi) const
573{
574 _RWSTD_ASSERT (lo <= hi);
575 for ( ; lo != hi; ++lo) {
576 if ( _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, *lo) >= _C_tab_size
577 || !(_C_mask_tab [_UChar (*lo)] & m))
578 break;
579 }
580
581 return lo;
582}
583
584
585char
586ctype<wchar_t>::
587do_narrow (char_type c, char dfault) const
588{
589 return _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, c) <= _RWSTD_SCHAR_MAX ?
590 _RWSTD_STATIC_CAST (char, c) : dfault;
591}
592
593
594const ctype<wchar_t>::char_type*
595ctype<wchar_t>::
596do_narrow (const char_type *lo, const char_type *hi,
597 char dfault, char *dest) const
598{
599 _RWSTD_ASSERT (lo <= hi);
600 while (lo != hi) {
601 *dest++ = do_narrow (*lo++, dfault);
602 }
603 return hi;
604}
605
606
607ctype_byname<wchar_t>::
608ctype_byname (const char *name, _RWSTD_SIZE_T refs)
609 : ctype<wchar_t> (refs), _C_cvtimpl (0), _C_cvtsize (0)
610{
611 this->_C_set_name (name, _C_namebuf, sizeof _C_namebuf);
612
613 if ('C' == name [0] && '\0' == name [1])
614 return;
615
616 // delayed initialization not used for efficiency
617 _RW::__rw_ctype_t* impl =
618 _RWSTD_CONST_CAST (_RW::__rw_ctype_t*,
619 _RWSTD_STATIC_CAST (const _RW::__rw_ctype_t*,
620 _RW::__rw_get_facet_data (LC_CTYPE, _C_impsize, _C_name)));
621
622 _C_impdata = impl;
623
624 // Memory map the codecvt database and store it for future use
625 if (impl)
626 _C_cvtimpl = _RW::__rw_get_facet_data (LC_CTYPE, _C_cvtsize, 0,
627 impl->codeset_name ());
628
629 if (impl == 0 || (this->_C_opts & this->_C_use_libc)) {
630
631 // set locale first to avoid unnecessary allocation
632 // if `name' doesn't refer to a valid locale (and
633 // __rw_setlocale throws an exception)
634 const _RW::__rw_setlocale clocale (name, LC_CTYPE);
635
636 _C_delete_it = true;
637
638 // casts prevent bogus gcc 2.95.2 warning:
639 // size in array new must have integral type
640 _C_mask_tab = new mask [(_RWSTD_SIZE_T)_C_tab_size];
641
642 _TRY {
643 // avoid doing one extra allocation by allocating
644 // both the upper and lower tables in the same space
645 _C_upper_tab = new _UChar [(_RWSTD_SIZE_T)_C_tab_size * 2];
646 _C_lower_tab = _C_upper_tab + _C_tab_size;
647 }
648 _CATCH (...) {
649 delete[] _RWSTD_CONST_CAST (mask*, _C_mask_tab);
650 _RETHROW;
651 }
652
653 for (char_type i = 0; i <= char_type (_RWSTD_UCHAR_MAX); i++) {
654
655 int m = 0;
656
657#ifndef _RWSTD_NO_ISWSPACE
658 if ((::iswspace)(i))
659#else
660 if ((::isspace)(i))
661#endif // _RWSTD_NO_ISWSPACE
662 m |= _RW::__rw_space;
663
664#ifndef _RWSTD_NO_ISWPRINT
665 if ((::iswprint)(i))
666#else
667 if ((::isprint)(i))
668#endif // _RWSTD_NO_ISWPRINT
669 m |= _RW::__rw_print;
670
671#ifndef _RWSTD_NO_ISWCNTRL
672 if ((::iswcntrl)(i))
673#else
674 if ((::iscntrl)(i))
675#endif // _RWSTD_NO_ISWCNTRL
676 m |= _RW::__rw_cntrl;
677
678#ifndef _RWSTD_NO_ISWUPPER
679 if ((::iswupper)(i))
680#else
681 if ((::isupper)(i))
682#endif // _RWSTD_NO_ISWUPPER
683 m |= _RW::__rw_upper;
684
685#ifndef _RWSTD_NO_ISWLOWER
686 if ((::iswlower)(i))
687#else
688 if ((::islower)(i))
689#endif // _RWSTD_NO_ISWLOWER
690 m |= _RW::__rw_lower;
691
692#ifndef _RWSTD_NO_ISWALPHA
693 if ((::iswalpha)(i))
694#else
695 if ((::isalpha)(i))
696#endif // _RWSTD_NO_ISWALPHA
697 m |= _RW::__rw_alpha;
698
699#ifndef _RWSTD_NO_ISWDIGIT
700 if ((::iswdigit)(i))
701#else
702 if ((::isdigit)(i))
703#endif // _RWSTD_NO_ISWDIGIT
704 m |= _RW::__rw_digit;
705
706#ifndef _RWSTD_NO_ISWPUNCT
707 if ((::iswpunct)(i))
708#else
709 if ((::ispunct)(i))
710#endif // _RWSTD_NO_ISWPUNCT
711 m |= _RW::__rw_punct;
712
713#ifndef _RWSTD_NO_ISWXDIGIT
714 if ((::iswxdigit)(i))
715#else
716 if ((::isxdigit)(i))
717#endif // _RWSTD_NO_ISWXDIGIT
718 m |= _RW::__rw_xdigit;
719
720#ifndef _RWSTD_NO_ISWGRAPH
721 if ((::iswgraph)(i))
722#else
723 if ((::isgraph)(i))
724#endif // _RWSTD_NO_ISWGRAPH
725 m |= _RW::__rw_graph;
726
727 _RWSTD_CONST_CAST (mask*, _C_mask_tab) [i] = mask (m);
728
729 typedef _RWSTD_SIZE_T SizeT;
730
731#ifndef _RWSTD_NO_TOWUPPER
732 const SizeT upr = SizeT ((::towupper)(i));
733#else // if defined (_RWSTD_NO_TOWUPPER)
734 const SizeT upr = SizeT ((::toupper)(i));
735#endif // _RWSTD_NO_TOWUPPER
736
737#ifndef _RWSTD_NO_TOWLOWER
738 const SizeT lwr = SizeT ((::towlower)(i));
739#else // if defined (_RWSTD_NO_TOWLOWER)
740 const SizeT lwr = SizeT ((::tolower)(i));
741#endif // _RWSTD_NO_TOWLOWER
742
743 // optimize (and avoid warnings) when wint_t is unsigned
744 _C_upper_tab [i] = upr <= SizeT (_RWSTD_UCHAR_MAX) ?
745 _UChar (upr) : _UChar (0);
746
747 _C_lower_tab [i] = lwr <= SizeT (_RWSTD_UCHAR_MAX) ?
748 _UChar (lwr) : _UChar (0);
749 }
750 }
751 else {
752
753 _C_delete_it = false;
754
755 _C_mask_tab = (mask*)impl->mask_tab;
756 _C_upper_tab = impl->toupper_tab;
757 _C_lower_tab = impl->tolower_tab;
758 }
759}
760
761
762ctype_byname<wchar_t>::
763~ctype_byname ()
764{
765 // Release the codecvt database at this level
766 if (_C_cvtimpl != 0 && _C_cvtsize != 0)
767 _RW::__rw_release_facet_data (_C_cvtimpl, _C_cvtsize);
768}
769
770
771bool
772ctype_byname<wchar_t>::
773do_is (mask m, wchar_t c) const
774{
775 _RW::__rw_ctype_t* impl =
776 _RWSTD_CONST_CAST (_RW::__rw_ctype_t*,
777 _RWSTD_STATIC_CAST (const _RW::__rw_ctype_t*,
778 _C_data ()));
779
780 const bool libstd = 0 != (this->_C_opts & this->_C_use_libstd);
781
782 mask res = mask ();
783
784 _RW::__rw_get_mask (impl, &c, &c + 1, m, &res, false, libstd, _C_name);
785
786 return res != 0;
787}
788
789
790const ctype_byname<wchar_t>::char_type*
791ctype_byname<wchar_t>::
792do_is (const char_type *lo, const char_type *hi, mask *mvec) const
793{
794 _RWSTD_ASSERT (lo <= hi);
795 _RW::__rw_ctype_t* impl =
796 _RWSTD_CONST_CAST (_RW::__rw_ctype_t*,
797 _RWSTD_STATIC_CAST (const _RW::__rw_ctype_t*,
798 _C_data ()));
799
800 const bool libstd = 0 != (this->_C_opts & this->_C_use_libstd);
801
802 return _RW::__rw_get_mask (impl, lo, hi, _RW::__rw_all,
803 mvec, false, libstd, _C_name);
804}
805
806
807ctype_byname<wchar_t>::char_type
808ctype_byname<wchar_t>::
809do_toupper (char_type c) const
810{
811 _RW::__rw_ctype_t* impl =
812 _RWSTD_CONST_CAST (_RW::__rw_ctype_t*,
813 _RWSTD_STATIC_CAST (const _RW::__rw_ctype_t*,
814 _C_data ()));
815
816 const bool use_libstd = 0 != (this->_C_opts & this->_C_use_libstd);
817
818 return _RW::__rw_toupper (impl, c, use_libstd, _C_name);
819}
820
821
822ctype_byname<wchar_t>::char_type
823ctype_byname<wchar_t>::
824do_tolower (char_type c) const
825{
826 _RW::__rw_ctype_t* impl =
827 _RWSTD_CONST_CAST (_RW::__rw_ctype_t*,
828 _RWSTD_STATIC_CAST (const _RW::__rw_ctype_t*,
829 _C_data ()));
830
831 const bool use_libstd = 0 != (this->_C_opts & this->_C_use_libstd);
832
833 return _RW::__rw_tolower (impl, c, use_libstd, _C_name);
834}
835
836
837const ctype_byname<wchar_t>::char_type*
838ctype_byname<wchar_t>::
839do_toupper (char_type *lo, const char_type *hi) const
840{
841 _RWSTD_ASSERT (lo <= hi);
842 _RW::__rw_ctype_t* impl =
843 _RWSTD_CONST_CAST (_RW::__rw_ctype_t*,
844 _RWSTD_STATIC_CAST (const _RW::__rw_ctype_t*,
845 _C_data ()));
846
847 const bool use_libstd = 0 != (this->_C_opts & this->_C_use_libstd);
848
849 // FIXME: implement efficiently (__rw_toupper() may call setlocale())
850 for ( ; lo < hi; ++lo)
851 *lo = _RW::__rw_toupper (impl, *lo, use_libstd, _C_name);
852 return lo;
853}
854
855
856const ctype_byname<wchar_t>::char_type*
857ctype_byname<wchar_t>::
858do_tolower (char_type *lo, const char_type *hi) const
859{
860 _RWSTD_ASSERT (lo <= hi);
861 _RW::__rw_ctype_t* impl =
862 _RWSTD_CONST_CAST (_RW::__rw_ctype_t*,
863 _RWSTD_STATIC_CAST (const _RW::__rw_ctype_t*,
864 _C_data ()));
865
866 const bool use_libstd = 0 != (this->_C_opts & this->_C_use_libstd);
867
868 // FIXME: implement efficiently (__rw_tolower() may call setlocale())
869 for ( ; lo < hi; ++lo)
870 *lo = _RW::__rw_tolower (impl, *lo, use_libstd, _C_name);
871 return lo;
872}
873
874
875const ctype_byname<wchar_t>::char_type*
876ctype_byname<wchar_t>::
877do_scan_is (mask m, const char_type* lo, const char_type* hi) const
878{
879 _RWSTD_ASSERT (lo <= hi);
880
881 _RW::__rw_ctype_t* impl =
882 _RWSTD_CONST_CAST (_RW::__rw_ctype_t*,
883 _RWSTD_STATIC_CAST (const _RW::__rw_ctype_t*,
884 _C_data ()));
885 const bool libstd = 0 != (this->_C_opts & this->_C_use_libstd);
886
887 return _RW::__rw_get_mask (impl, lo, hi, m, 0, true, libstd, _C_name);
888}
889
890
891const ctype_byname<wchar_t>::char_type*
892ctype_byname<wchar_t>::
893do_scan_not (mask m, const char_type *lo, const char_type *hi) const
894{
895 _RWSTD_ASSERT (lo <= hi);
896
897 _RW::__rw_ctype_t* impl =
898 _RWSTD_CONST_CAST (_RW::__rw_ctype_t*,
899 _RWSTD_STATIC_CAST (const _RW::__rw_ctype_t*,
900 _C_data ()));
901 const bool libstd = 0 != (this->_C_opts & this->_C_use_libstd);
902
903 return _RW::__rw_get_mask (impl, lo, hi, m, 0, false, libstd, _C_name);
904}
905
906
907char
908ctype_byname<wchar_t>::
909do_narrow (char_type c, char dfault) const
910{
911#if _RWSTD_WCHAR_MIN < 0
912
913 // wchar_t is a signed type
914 if (c > L'\0' && c < SCHAR_MAX)
915 return char (c);
916
917#else // if _RWSTD_WCHAR_MIN >= 0
918
919 // wchar_t is an unsigned type
920 if (c < SCHAR_MAX)
921 return char (c);
922
923#endif // _RWSTD_WCHAR_MIN
924
925 const _RW::__rw_codecvt_t* cvt =
926 _RWSTD_STATIC_CAST(const _RW::__rw_codecvt_t*, _C_cvtimpl);
927
928 char ch = 0;
929 if (0 == cvt || (this->_C_opts & this->_C_use_libc)) {
930
931#ifndef _RWSTD_NO_WCTOB
932
933 const _RW::__rw_setlocale clocale (_C_name, LC_CTYPE);
934
935 const int tmp = wctob (c);
936
937 ch = tmp < 0 ? dfault : char (tmp);
938
939#elif !defined (_RWSTD_NO_WCTOMB)
940
941 char tmp [_RWSTD_MB_LEN_MAX];
942 ch = 1 == wctomb (tmp, c) ? *tmp : dfault;
943
944#else // if defined (_RWSTD_NO_WCTOMB)
945
946 ch = dfault;
947
948#endif // _RWSTD_NO_WCTOB, _RWSTD_NO_WCTOMB
949
950 }
951 else {
952
953#if _RWSTD_WCHAR_MIN < 0
954 // For a signed wchar_t test if the character has a negative value
955 if (c < 0)
956 return dfault;
957#endif // _RWSTD_WCHAR_MIN < 0
958
959 // Look up narrow character value in database; be aware that there
960 // is no way to know what the internal representation is for this
961 // wide character; we have to assume that the internal representation
962 // was native and use wide-to-narrow tables for conversion
963 char_type wc = 0;
964
965 unsigned int* tbl = _RWSTD_CONST_CAST(unsigned int*,
966 cvt->w_to_n_tab ());
967 unsigned int* ptbl = tbl;
968
969 char tmp [_UTF8_MB_CUR_MAX + 1];
970 char* ptmp = tmp;
971 _RWSTD_SIZE_T utf8_sz = _RW::__rw_itoutf8 (c, tmp);
972
973#if _RWSTD_WCHAR_MIN < 0
974 // compute the invalid bit mask (the MSB set)
975 const wchar_t imask = wchar_t (~(_RWSTD_WCHAR_MAX));
976#else
977 const wchar_t imask = wchar_t (~(_RWSTD_WCHAR_MAX >> 1));
978#endif // _RWSTD_WCHAR_MIN < 0
979
980 typedef unsigned char UChar;
981
982 _RWSTD_SIZE_T i = 0;
983 wc = ptbl [UChar (*ptmp)];
984 while (wc & imask) {
985 // check validity of the value
986 if (wc == (imask | _RWSTD_WCHAR_MAX))
987 return dfault;
988
989 ptbl = tbl + 256 * (wc & (~imask));
990 ptmp++;
991
992 // check for invalid sequences
993 if (++i >= utf8_sz)
994 return dfault;
995
996 // fetch next byte
997 wc = ptbl [UChar (*ptmp)];
998 }
999
1000 // the resulting ch value is an index to the storage space of
1001 // the narrow sequence; for our purposes here, that sequence has
1002 // to have length of one
1003 const char* impl_raw =
1004 _RWSTD_REINTERPRET_CAST(const char*, cvt);
1005 _RWSTD_SIZE_T offset = wc + sizeof (_RW::__rw_codecvt_t);
1006
1007 if (impl_raw [offset + 1])
1008 return dfault;
1009 else
1010 ch = impl_raw [offset];
1011 }
1012
1013 return ch;
1014}
1015
1016
1017const ctype_byname<wchar_t>::char_type*
1018ctype_byname<wchar_t>::
1019do_narrow (const char_type *lo, const char_type *hi,
1020 char dfault, char *dest) const
1021{
1022 _RWSTD_ASSERT (lo <= hi);
1023
1024 // FIXME: implement w/o relying on another virtual function
1025 while (lo != hi) {
1026 *dest++ = do_narrow (*lo, dfault);
1027 lo++;
1028 }
1029 return hi;
1030}
1031
1032
1033ctype_byname<wchar_t>::char_type
1034ctype_byname<wchar_t>::
1035do_widen (char c) const
1036{
1037 const unsigned char u_c = _UChar (c);
1038
1039 if (u_c <= SCHAR_MAX)
1040 return char_type (u_c);
1041
1042 // when using the C++ locale database files then we have to do
1043 // a table lookup to get the wide version of this character
1044 // otherwise we have to call setlocale() and btowc() to get the
1045 // corresponding wchar_t
1046 const _RW::__rw_codecvt_t* cvt =
1047 _RWSTD_STATIC_CAST (const _RW::__rw_codecvt_t*, _C_cvtimpl);
1048
1049 char_type ch;
1050
1051 if (0 == cvt || (this->_C_opts & this->_C_use_libc)) {
1052
1053#ifndef _RWSTD_NO_BTOWC
1054
1055 const _RW::__rw_setlocale clocale (_C_name, LC_CTYPE);
1056
1057 // prevent sign extension if `c' is negative
1058 ch = btowc (u_c);
1059
1060#else // if defined (_RWSTD_NO_BTOWC)
1061
1062 ch = char_type (u_c);
1063
1064#endif // _RWSTD_NO_BTOWC
1065
1066 }
1067 else {
1068
1069#if _RWSTD_WCHAR_MIN < 0
1070 // compute the invalid bit mask (the MSB set)
1071 const char_type imask = char_type (~(_RWSTD_WCHAR_MAX));
1072#else
1073 const char_type imask = char_type (~(_RWSTD_WCHAR_MAX >> 1));
1074#endif // _RWSTD_WCHAR_MIN < 0
1075
1076 // Lookup the narrow character in the table; be aware that
1077 // the result of the lookup might be the index for another
1078 // table (i.e., the narrow character may be the first byte
1079 // of a multibyte character) in which case return an error.
1080 ch = cvt->n_to_w_tab ()[u_c];
1081 if (ch & imask)
1082 return char_type (_RWSTD_WEOF);
1083
1084 ch = cvt->get_internal_at_offset (ch);
1085 }
1086
1087 return ch;
1088}
1089
1090
1091const char*
1092ctype_byname<wchar_t>::
1093do_widen (const char *lo, const char *hi, char_type *dest) const
1094{
1095 _RWSTD_ASSERT (lo <= hi);
1096
1097 // FIXME: implement w/o relying on another virtual function
1098 while (lo < hi) {
1099 *dest++ = widen (*lo++);
1100 }
1101
1102 return hi;
1103}
1104
1105
1106} // namespace std
1107
1108
1109_RWSTD_DEFINE_FACET_FACTORY (static, ctype, <wchar_t>, wctype);
1111
1112#endif // _RWSTD_NO_WCHAR_T
#define m
Definition 17.names.cpp:129
#define i
Definition 17.names.cpp:126
#define res
Definition 17.names.cpp:531
#define offset
Definition 17.names.cpp:508
#define c
Definition 17.names.cpp:111
#define tmp
Definition 17.names.cpp:553
const char * widen(char *dst, const char *src)
const int end
const int cur
#define LC_CTYPE
unsigned short wchar_t
#define _RETHROW
Definition _defs.h:853
#define _RWSTD_REINTERPRET_CAST(T, x)
Definition _defs.h:535
#define _RWSTD_UNUSED(arg)
Definition _defs.h:972
#define _RWSTD_STATIC_CAST(T, x)
Definition _defs.h:534
#define _TRY
Definition _defs.h:850
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
#define _RWSTD_ASSERT(ignore)
Definition _defs.h:1108
#define _CATCH(ex)
Definition _defs.h:851
#define _RWSTD_CONST_CAST(T, x)
Definition _defs.h:536
const char * name
Definition codecvt1.cpp:72
std::mbstate_t init
Definition codecvt1.cpp:80
#define SCHAR_MAX
Definition limits.h:52
Definition json.h:5363
#define _RWSTD_ONCE_INIT
Definition once.h:123
unsigned char UChar
Definition collate.cpp:122
#define _UTF8_MB_CUR_MAX
Definition wctype.cpp:60
#define _RWSTD_SPECIALIZE_USE_FACET(fid)
Definition use_facet.h:129
#define _RWSTD_DEFINE_FACET_FACTORY(Linkage, Facet, TArgs, fid)
Definition use_facet.h:52