Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4680 right-hear 1
// Locale support -*- C++ -*-
2
 
3
// Copyright (C) 1997, 1998, 1999, 2000, 2001 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 2, 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
// You should have received a copy of the GNU General Public License along
17
// with this library; see the file COPYING.  If not, write to the Free
18
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19
// USA.
20
 
21
// As a special exception, you may use this file as part of a free software
22
// library without restriction.  Specifically, if other files instantiate
23
// templates or use macros or inline functions from this file, or you compile
24
// this file and link it with other files to produce an executable, this
25
// file does not by itself cause the resulting executable to be covered by
26
// the GNU General Public License.  This exception does not however
27
// invalidate any other reasons why the executable file might be covered by
28
// the GNU General Public License.
29
 
30
// Warning: this file is not meant for user inclusion.  Use .
31
 
32
#ifndef _CPP_BITS_LOCFACETS_TCC
33
#define _CPP_BITS_LOCFACETS_TCC 1
34
 
35
#include 
36
#include    // For localeconv
37
#include    // For strof, strtold
38
#include     // For numeric_limits
39
#include     // For auto_ptr
40
#include      // For streambuf_iterators
41
#include     // For isspace
42
#include  		// For bad_cast
43
#include 
44
 
45
 
46
namespace std
47
{
48
  template
49
    locale
50
    locale::combine(const locale& __other)
51
    {
52
      locale __copy(*this);
53
      __copy._M_impl->_M_replace_facet(__other._M_impl, &_Facet::id);
54
      return __copy;
55
    }
56
 
57
  template
58
    bool
59
    locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
60
                       const basic_string<_CharT, _Traits, _Alloc>& __s2) const
61
    {
62
      typedef std::collate<_CharT> __collate_type;
63
      const __collate_type* __fcoll = &use_facet<__collate_type>(*this);
64
      return (__fcoll->compare(__s1.data(), __s1.data() + __s1.length(),
65
                               __s2.data(), __s2.data() + __s2.length()) < 0);
66
    }
67
 
68
  template
69
    const _Facet&
70
    use_facet(const locale& __loc)
71
    {
72
      typedef locale::_Impl::__vec_facet        __vec_facet;
73
      size_t __i = _Facet::id._M_index;
74
      __vec_facet* __facet = __loc._M_impl->_M_facets;
75
      const locale::facet* __fp = (*__facet)[__i];
76
      if (__fp == 0 || __i >= __facet->size())
77
        __throw_bad_cast();
78
      return static_cast(*__fp);
79
    }
80
 
81
  template
82
    bool
83
    has_facet(const locale& __loc) throw()
84
    {
85
      typedef locale::_Impl::__vec_facet        __vec_facet;
86
      size_t __i = _Facet::id._M_index;
87
      __vec_facet* __facet = __loc._M_impl->_M_facets;
88
      return (__i < __facet->size() && (*__facet)[__i] != 0);
89
    }
90
 
91
  // __match_parallel
92
  // matches input __s against a set of __ntargs strings in __targets,
93
  // placing in __matches a vector of indices into __targets which
94
  // match, and in __remain the number of such matches. If it hits
95
  // end of sequence before it minimizes the set, sets __eof.
96
  // Empty strings are never matched.
97
  template
98
    _InIter
99
    __match_parallel(_InIter __s, _InIter __end, int __ntargs,
100
                     const basic_string<_CharT>* __targets,
101
                     int* __matches, int& __remain, bool& __eof)
102
    {
103
      typedef basic_string<_CharT> __string_type;
104
      __eof = false;
105
      for (int __ti = 0; __ti < __ntargs; ++__ti)
106
        __matches[__ti] = __ti;
107
      __remain = __ntargs;
108
      size_t __pos = 0;
109
      do
110
        {
111
	  int __ti = 0;
112
	  while (__ti < __remain && __pos == __targets[__matches[__ti]].size())
113
	    ++__ti;
114
	  if (__ti == __remain)
115
	    {
116
	      if (__pos == 0) __remain = 0;
117
	      return __s;
118
	    }
119
          if (__s == __end)
120
            __eof = true;
121
          bool __matched = false;
122
          for (int __ti2 = 0; __ti2 < __remain; )
123
            {
124
              const __string_type& __target = __targets[__matches[__ti2]];
125
              if (__pos < __target.size())
126
                {
127
                  if (__eof || __target[__pos] != *__s)
128
                    {
129
                      __matches[__ti2] = __matches[--__remain];
130
                      continue;
131
                    }
132
                  __matched = true;
133
                }
134
              ++__ti2;
135
            }
136
          if (__matched)
137
            {
138
              ++__s;
139
              ++__pos;
140
            }
141
          for (int __ti3 = 0; __ti3 < __remain;)
142
            {
143
              if (__pos > __targets[__matches[__ti3]].size())
144
                {
145
                  __matches[__ti3] = __matches[--__remain];
146
                  continue;
147
                }
148
              ++__ti3;
149
            }
150
        }
151
      while (__remain);
152
      return __s;
153
    }
154
 
155
  template
156
    _Format_cache<_CharT>::_Format_cache()
157
    : _M_valid(true), _M_use_grouping(false)
158
    { }
159
 
160
  template<>
161
    _Format_cache::_Format_cache();
162
 
163
  template<>
164
    _Format_cache::_Format_cache();
165
 
166
  template
167
    void
168
    _Format_cache<_CharT>::_M_populate(ios_base& __io)
169
    {
170
      locale __loc = __io.getloc ();
171
      numpunct<_CharT> const& __np = use_facet >(__loc);
172
      _M_truename = __np.truename();
173
      _M_falsename = __np.falsename();
174
      _M_thousands_sep = __np.thousands_sep();
175
      _M_decimal_point = __np.decimal_point();
176
      _M_grouping = __np.grouping();
177
      _M_use_grouping = _M_grouping.size() != 0 && _M_grouping.data()[0] != 0;
178
      _M_valid = true;
179
    }
180
 
181
  // This function is always called via a pointer installed in
182
  // an ios_base by ios_base::register_callback.
183
  template
184
    void
185
    _Format_cache<_CharT>::
186
    _S_callback(ios_base::event __ev, ios_base& __ios, int __ix) throw()
187
    {
188
      void*& __p = __ios.pword(__ix);
189
      switch (__ev)
190
        {
191
        case ios_base::erase_event:
192
          delete static_cast<_Format_cache<_CharT>*>(__p);
193
	  __p = 0;
194
          break;
195
        case ios_base::copyfmt_event:
196
          // If just stored zero, the callback would get registered again.
197
          try
198
	    { __p = new _Format_cache<_CharT>; }
199
          catch(...)
200
	    { }
201
          break;
202
        case ios_base::imbue_event:
203
          static_cast<_Format_cache<_CharT>*>(__p)->_M_valid = false;
204
          break;
205
        }
206
    }
207
 
208
  template
209
    _Format_cache<_CharT>*
210
    _Format_cache<_CharT>::_S_get(ios_base& __ios)
211
    {
212
      if (!_S_pword_ix)
213
        _S_pword_ix = ios_base::xalloc();  // XXX MT
214
      void*& __p = __ios.pword(_S_pword_ix);
215
 
216
      // XXX What if pword fails? must check failbit, throw.
217
      if (__p == 0)  // XXX MT?  maybe sentry takes care of it
218
        {
219
          auto_ptr<_Format_cache<_CharT> > __ap(new _Format_cache<_CharT>);
220
          __ios.register_callback(&_Format_cache<_CharT>::_S_callback,
221
                                  _S_pword_ix);
222
          __p = __ap.release();
223
        }
224
      _Format_cache<_CharT>* __ncp = static_cast<_Format_cache<_CharT>*>(__p);
225
      if (!__ncp->_M_valid)
226
        __ncp->_M_populate(__ios);
227
 
228
      return __ncp;
229
    }
230
 
231
  // This member function takes an (w)istreambuf_iterator object and
232
  // parses it into a generic char array suitable for parsing with
233
  // strto[l,ll,f,d]. The thought was to encapsulate the conversion
234
  // into this one function, and thus the num_get::do_get member
235
  // functions can just adjust for the type of the overloaded
236
  // argument and process the char array returned from _M_extract.
237
  // Other things were also considered, including a fused
238
  // multiply-add loop that would obviate the need for any call to
239
  // strto... at all: however, it would b e a bit of a pain, because
240
  // you'd have to be able to return either floating or integral
241
  // types, etc etc. The current approach seems to be smack dab in
242
  // the middle between an unoptimized approach using sscanf, and
243
  // some kind of hyper-optimized approach alluded to above.
244
 
245
  // XXX
246
  // Need to do partial specialization to account for differences
247
  // between character sets. For char, this is pretty
248
  // straightforward, but for wchar_t, the conversion to a plain-jane
249
  // char type is a bit more involved.
250
  template
251
    void
252
    num_get<_CharT, _InIter>::
253
    _M_extract(_InIter /*__beg*/, _InIter /*__end*/, ios_base& /*__io*/,
254
               ios_base::iostate& /*__err*/, char* /*__xtrc*/,
255
               int& /*__base*/, bool /*__fp*/) const
256
    {
257
      // XXX Not currently done: need to expand upon char version below.
258
    }
259
 
260
  template<>
261
    void
262
    num_get >::
263
    _M_extract(istreambuf_iterator __beg,
264
	       istreambuf_iterator __end, ios_base& __io,
265
	       ios_base::iostate& __err, char* __xtrc, int& __base,
266
	       bool __fp) const;
267
 
268
#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
269
  // NB: This is an unresolved library defect #17
270
  template
271
    _InIter
272
    num_get<_CharT, _InIter>::
273
    do_get(iter_type __beg, iter_type __end, ios_base& __io,
274
           ios_base::iostate& __err, bool& __v) const
275
    {
276
      // Parse bool values as long
277
      if (!(__io.flags() & ios_base::boolalpha))
278
        {
279
          // NB: We can't just call do_get(long) here, as it might
280
          // refer to a derived class.
281
 
282
          // Stage 1: extract and determine the conversion specifier.
283
          // Assuming leading zeros eliminated, thus the size of 32 for
284
          // integral types.
285
          char __xtrc[32] = {'\0'};
286
          int __base;
287
          _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
288
 
289
          // Stage 2: convert and store results.
290
          char* __sanity;
291
          errno = 0;
292
          long __l = strtol(__xtrc, &__sanity, __base);
293
          if (!(__err & ios_base::failbit)
294
              && __l <= 1
295
              && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
296
            __v = __l;
297
          else
298
            __err |= ios_base::failbit;
299
        }
300
 
301
      // Parse bool values as alphanumeric
302
      else
303
        {
304
          typedef _Format_cache __fcache_type;
305
          __fcache_type* __fmt = __fcache_type::_S_get(__io);
306
          const char_type* __true = __fmt->_M_truename.c_str();
307
          const char_type* __false = __fmt->_M_falsename.c_str();
308
          const size_t __truelen =  __traits_type::length(__true) - 1;
309
          const size_t __falselen =  __traits_type::length(__false) - 1;
310
 
311
          for (size_t __pos = 0; __beg != __end; ++__pos)
312
            {
313
              char_type __c = *__beg++;
314
              bool __testf = __c == __false[__pos];
315
              bool __testt = __c == __true[__pos];
316
              if (!(__testf || __testt))
317
                {
318
                  __err |= ios_base::failbit;
319
                  break;
320
                }
321
              else if (__testf && __pos == __falselen)
322
                {
323
                  __v = 0;
324
                  break;
325
                }
326
              else if (__testt && __pos == __truelen)
327
                {
328
                  __v = 1;
329
                  break;
330
                }
331
            }
332
          if (__beg == __end)
333
            __err |= ios_base::eofbit;
334
        }
335
 
336
      return __beg;
337
    }
338
#endif
339
 
340
#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
341
  template
342
    _InIter
343
    num_get<_CharT, _InIter>::
344
    do_get(iter_type __beg, iter_type __end, ios_base& __io,
345
           ios_base::iostate& __err, short& __v) const
346
    {
347
      // Stage 1: extract and determine the conversion specifier.
348
      // Assuming leading zeros eliminated, thus the size of 32 for
349
      // integral types.
350
      char __xtrc[32]= {'\0'};
351
      int __base;
352
      _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
353
 
354
      // Stage 2: convert and store results.
355
      char* __sanity;
356
      errno = 0;
357
      long __l = strtol(__xtrc, &__sanity, __base);
358
      if (!(__err & ios_base::failbit)
359
          && __sanity != __xtrc && *__sanity == '\0' && errno == 0
360
          && __l >= SHRT_MIN && __l <= SHRT_MAX)
361
        __v = static_cast(__l);
362
      else
363
        __err |= ios_base::failbit;
364
 
365
      return __beg;
366
    }
367
 
368
  template
369
    _InIter
370
    num_get<_CharT, _InIter>::
371
    do_get(iter_type __beg, iter_type __end, ios_base& __io,
372
           ios_base::iostate& __err, int& __v) const
373
    {
374
      // Stage 1: extract and determine the conversion specifier.
375
      // Assuming leading zeros eliminated, thus the size of 32 for
376
      // integral types.
377
      char __xtrc[32] = {'\0'};
378
      int __base;
379
      _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
380
 
381
      // Stage 2: convert and store results.
382
      char* __sanity;
383
      errno = 0;
384
      long __l = strtol(__xtrc, &__sanity, __base);
385
      if (!(__err & ios_base::failbit)
386
          && __sanity != __xtrc && *__sanity == '\0' && errno == 0
387
          && __l >= INT_MIN && __l <= INT_MAX)
388
        __v = static_cast(__l);
389
      else
390
        __err |= ios_base::failbit;
391
 
392
      return __beg;
393
    }
394
#endif
395
 
396
  template
397
    _InIter
398
    num_get<_CharT, _InIter>::
399
    do_get(iter_type __beg, iter_type __end, ios_base& __io,
400
           ios_base::iostate& __err, long& __v) const
401
    {
402
      // Stage 1: extract and determine the conversion specifier.
403
      // Assuming leading zeros eliminated, thus the size of 32 for
404
      // integral types.
405
      char __xtrc[32]= {'\0'};
406
      int __base;
407
      _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
408
 
409
      // Stage 2: convert and store results.
410
      char* __sanity;
411
      errno = 0;
412
      long __l = strtol(__xtrc, &__sanity, __base);
413
      if (!(__err & ios_base::failbit)
414
          && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
415
        __v = __l;
416
      else
417
        __err |= ios_base::failbit;
418
 
419
      return __beg;
420
    }
421
 
422
#ifdef _GLIBCPP_USE_LONG_LONG
423
  template
424
    _InIter
425
    num_get<_CharT, _InIter>::
426
    do_get(iter_type __beg, iter_type __end, ios_base& __io,
427
           ios_base::iostate& __err, long long& __v) const
428
    {
429
      // Stage 1: extract and determine the conversion specifier.
430
      // Assuming leading zeros eliminated, thus the size of 32 for
431
      // integral types.
432
      char __xtrc[32]= {'\0'};
433
      int __base;
434
      _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
435
 
436
      // Stage 2: convert and store results.
437
      char* __sanity;
438
      errno = 0;
439
      long long __ll = strtoll(__xtrc, &__sanity, __base);
440
      if (!(__err & ios_base::failbit)
441
          && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
442
        __v = __ll;
443
      else
444
        __err |= ios_base::failbit;
445
 
446
      return __beg;
447
    }
448
#endif
449
 
450
  template
451
    _InIter
452
    num_get<_CharT, _InIter>::
453
    do_get(iter_type __beg, iter_type __end, ios_base& __io,
454
           ios_base::iostate& __err, unsigned short& __v) const
455
    {
456
      // Stage 1: extract and determine the conversion specifier.
457
      // Assuming leading zeros eliminated, thus the size of 32 for
458
      // integral types.
459
      char __xtrc[32]= {'\0'};
460
      int __base;
461
      _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
462
 
463
      // Stage 2: convert and store results.
464
      char* __sanity;
465
      errno = 0;
466
      unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
467
      if (!(__err & ios_base::failbit)
468
          && __sanity != __xtrc && *__sanity == '\0' && errno == 0
469
          && __ul <= USHRT_MAX)
470
        __v = static_cast(__ul);
471
      else
472
        __err |= ios_base::failbit;
473
 
474
      return __beg;
475
    }
476
 
477
  template
478
    _InIter
479
    num_get<_CharT, _InIter>::
480
    do_get(iter_type __beg, iter_type __end, ios_base& __io,
481
           ios_base::iostate& __err, unsigned int& __v) const
482
    {
483
      // Stage 1: extract and determine the conversion specifier.
484
      // Assuming leading zeros eliminated, thus the size of 32 for
485
      // integral types.
486
      char __xtrc[32]= {'\0'};
487
      int __base;
488
      _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
489
 
490
      // Stage 2: convert and store results.
491
      char* __sanity;
492
      errno = 0;
493
      unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
494
      if (!(__err & ios_base::failbit)
495
          && __sanity != __xtrc && *__sanity == '\0' && errno == 0
496
          && __ul <= UINT_MAX)
497
        __v = static_cast(__ul);
498
      else
499
        __err |= ios_base::failbit;
500
 
501
      return __beg;
502
    }
503
 
504
  template
505
    _InIter
506
    num_get<_CharT, _InIter>::
507
    do_get(iter_type __beg, iter_type __end, ios_base& __io,
508
           ios_base::iostate& __err, unsigned long& __v) const
509
    {
510
      // Stage 1: extract and determine the conversion specifier.
511
      // Assuming leading zeros eliminated, thus the size of 32 for
512
      // integral types.
513
      char __xtrc[32] = {'\0'};
514
      int __base;
515
      _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
516
 
517
      // Stage 2: convert and store results.
518
      char* __sanity;
519
      errno = 0;
520
      unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
521
      if (!(__err & ios_base::failbit)
522
          && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
523
        __v = __ul;
524
      else
525
        __err |= ios_base::failbit;
526
 
527
      return __beg;
528
    }
529
 
530
#ifdef _GLIBCPP_USE_LONG_LONG
531
  template
532
    _InIter
533
    num_get<_CharT, _InIter>::
534
    do_get(iter_type __beg, iter_type __end, ios_base& __io,
535
           ios_base::iostate& __err, unsigned long long& __v) const
536
    {
537
      // Stage 1: extract and determine the conversion specifier.
538
      // Assuming leading zeros eliminated, thus the size of 32 for
539
      // integral types.
540
      char __xtrc[32]= {'\0'};
541
      int __base;
542
      _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
543
 
544
      // Stage 2: convert and store results.
545
      char* __sanity;
546
      errno = 0;
547
      unsigned long long __ull = strtoull(__xtrc, &__sanity, __base);
548
      if (!(__err & ios_base::failbit)
549
          && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
550
        __v = __ull;
551
      else
552
        __err |= ios_base::failbit;
553
 
554
      return __beg;
555
    }
556
#endif
557
 
558
  template
559
    _InIter
560
    num_get<_CharT, _InIter>::
561
    do_get(iter_type __beg, iter_type __end, ios_base& __io,
562
           ios_base::iostate& __err, float& __v) const
563
    {
564
      // Stage 1: extract and determine the conversion specifier.
565
      // Assuming leading zeros eliminated, thus the size of 256 for
566
      // floating-point types.
567
      char __xtrc[32]= {'\0'};
568
      int __base;
569
      _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
570
 
571
      // Stage 2: convert and store results.
572
      char* __sanity;
573
      errno = 0;
574
#ifdef _GLIBCPP_USE_C99
575
      float __f = strtof(__xtrc, &__sanity);
576
#else
577
      float __f = static_cast(strtod(__xtrc, &__sanity));
578
#endif
579
      if (!(__err & ios_base::failbit)
580
          && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
581
        __v = __f;
582
      else
583
        __err |= ios_base::failbit;
584
 
585
      return __beg;
586
    }
587
 
588
  template
589
    _InIter
590
    num_get<_CharT, _InIter>::
591
    do_get(iter_type __beg, iter_type __end, ios_base& __io,
592
           ios_base::iostate& __err, double& __v) const
593
    {
594
      // Stage 1: extract and determine the conversion specifier.
595
      // Assuming leading zeros eliminated, thus the size of 256 for
596
      // floating-point types.
597
      char __xtrc[32]= {'\0'};
598
      int __base;
599
      _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
600
 
601
      // Stage 2: convert and store results.
602
      char* __sanity;
603
      errno = 0;
604
      double __d = strtod(__xtrc, &__sanity);
605
      if (!(__err & ios_base::failbit)
606
          && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
607
        __v = __d;
608
      else
609
        __err |= ios_base::failbit;
610
 
611
      return __beg;
612
    }
613
 
614
#if defined(_GLIBCPP_USE_C99) && !defined(__hpux)
615
  template
616
    _InIter
617
    num_get<_CharT, _InIter>::
618
    do_get(iter_type __beg, iter_type __end, ios_base& __io,
619
           ios_base::iostate& __err, long double& __v) const
620
    {
621
      // Stage 1: extract and determine the conversion specifier.
622
      // Assuming leading zeros eliminated, thus the size of 256 for
623
      // floating-point types.
624
      char __xtrc[32]= {'\0'};
625
      int __base;
626
      _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
627
 
628
      // Stage 2: convert and store results.
629
      char* __sanity;
630
      errno = 0;
631
      long double __ld = strtold(__xtrc, &__sanity);
632
      if (!(__err & ios_base::failbit)
633
          && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
634
        __v = __ld;
635
      else
636
        __err |= ios_base::failbit;
637
 
638
      return __beg;
639
    }
640
#else
641
  template
642
    _InIter
643
    num_get<_CharT, _InIter>::
644
    do_get(iter_type __beg, iter_type __end, ios_base& __io,
645
           ios_base::iostate& __err, long double& __v) const
646
    {
647
      // Stage 1: extract
648
      char __xtrc[32]= {'\0'};
649
      int __base;
650
      _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
651
 
652
      // Stage 2: determine a conversion specifier.
653
      ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
654
      const char* __conv;
655
      if (__basefield == ios_base::oct)
656
        __conv = "%Lo";
657
      else if (__basefield == ios_base::hex)
658
        __conv = "%LX";
659
      else if (__basefield == 0)
660
        __conv = "%Li";
661
      else
662
        __conv = "%Lg";
663
 
664
      // Stage 3: store results.
665
      long double __ld;
666
      int __p = sscanf(__xtrc, __conv, &__ld);
667
      if (__p
668
          && static_cast(__p)
669
        != __traits_type::eof())
670
        __v = __ld;
671
      else
672
        __err |= ios_base::failbit;
673
 
674
      return __beg;
675
    }
676
#endif
677
 
678
  template
679
    _InIter
680
    num_get<_CharT, _InIter>::
681
    do_get(iter_type __beg, iter_type __end, ios_base& __io,
682
           ios_base::iostate& __err, void*& __v) const
683
    {
684
      // Prepare for hex formatted input
685
      typedef ios_base::fmtflags        fmtflags;
686
      fmtflags __fmt = __io.flags();
687
      fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield
688
                             | ios_base::uppercase | ios_base::internal);
689
      __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
690
 
691
      // Stage 1: extract and determine the conversion specifier.
692
      // Assuming leading zeros eliminated, thus the size of 32 for
693
      // integral types.
694
      char __xtrc[32]= {'\0'};
695
      int __base;
696
      _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
697
 
698
      // Stage 2: convert and store results.
699
      char* __sanity;
700
      errno = 0;
701
      void* __vp = reinterpret_cast(strtoul(__xtrc, &__sanity, __base));
702
      if (!(__err & ios_base::failbit)
703
          && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
704
        __v = __vp;
705
      else
706
        __err |= ios_base::failbit;
707
 
708
      // Reset from hex formatted input
709
      __io.flags(__fmt);
710
      return __beg;
711
    }
712
 
713
  // __pad is specialized for ostreambuf_iterator, random access iterator.
714
  template 
715
    inline _OutIter
716
    __pad(_OutIter __s, _CharT __fill, int __padding);
717
 
718
  template 
719
    _RaIter
720
    __pad(_RaIter __s, _CharT __fill, int __padding,
721
	  random_access_iterator_tag)
722
    {
723
      fill_n(__s, __fill);
724
      return __s + __padding;
725
    }
726
 
727
  template 
728
    _OutIter
729
    __pad(_OutIter __s, _CharT __fill, int __padding, _Tag)
730
    {
731
      while (--__padding >= 0) { *__s = __fill; ++__s; }
732
      return __s;
733
    }
734
 
735
  template 
736
    inline _OutIter
737
    __pad(_OutIter __s, _CharT __fill, int __padding)
738
    {
739
      return __pad(__s, __fill, __padding,
740
		   typename iterator_traits<_OutIter>::iterator_category());
741
    }
742
 
743
  template 
744
    _OutIter
745
    __pad_numeric(_OutIter __s, ios_base::fmtflags /*__flags*/,
746
		  _CharT /*__fill*/, int /*__width*/,
747
		  _CharT const* /*__first*/, _CharT const* /*__middle*/,
748
		  _CharT const* /*__last*/)
749
  {
750
      // XXX Not currently done: non streambuf_iterator
751
      return __s;
752
    }
753
 
754
  // Partial specialization for ostreambuf_iterator.
755
  template 
756
    ostreambuf_iterator<_CharT>
757
    __pad_numeric(ostreambuf_iterator<_CharT> __s, ios_base::fmtflags __flags,
758
		  _CharT __fill, int __width, _CharT const* __first,
759
		  _CharT const* __middle, _CharT const* __last)
760
    {
761
      typedef ostreambuf_iterator<_CharT> 	__out_iter;
762
      int __padding = __width - (__last - __first);
763
      if (__padding < 0)
764
        __padding = 0;
765
      ios_base::fmtflags __aflags = __flags & ios_base::adjustfield;
766
      bool __testfield = __padding == 0 || __aflags == ios_base::left
767
                         || __aflags == ios_base::internal;
768
 
769
      // This was needlessly complicated.
770
      if (__first != __middle)
771
        {
772
          if (!__testfield)
773
            {
774
              __pad(__s, __fill, __padding);
775
              __padding = 0;
776
            }
777
          copy(__first, __middle, __s);
778
        }
779
      __out_iter __s2 = __s;
780
 
781
      if (__padding && __aflags != ios_base::left)
782
        {
783
          __pad(__s2, __fill, __padding);
784
          __padding = 0;
785
        }
786
      __out_iter __s3 = copy(__middle, __last, __s2);
787
      if (__padding)
788
        __pad(__s3, __fill, __padding);
789
      return __s3;
790
    }
791
 
792
  template 
793
    _OutIter
794
    num_put<_CharT, _OutIter>::
795
    do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
796
    {
797
      const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
798
      ios_base::fmtflags __flags = __io.flags();
799
 
800
      if ((__flags & ios_base::boolalpha) == 0)
801
        {
802
          unsigned long __uv = __v;
803
          return __output_integer(__s, __io, __fill, false, __uv);
804
        }
805
      else
806
        {
807
          const char_type* __first;
808
          const char_type* __last;
809
          if (__v)
810
            {
811
              __first = __fmt->_M_truename.data();
812
              __last = __first + __fmt->_M_truename.size();
813
            }
814
          else
815
            {
816
              __first = __fmt->_M_falsename.data();
817
              __last = __first + __fmt->_M_falsename.size();
818
            }
819
          copy(__first, __last, __s);
820
        }
821
      return __s;
822
    }
823
 
824
  // __group_digits inserts "group separator" characters into an array
825
  // of characters.  It's recursive, one iteration per group.  It moves
826
  // the characters in the buffer this way: "xxxx12345" -> "12,345xxx".
827
  // Call this only with __grouping != __grend.
828
  template 
829
    _CharT*
830
    __group_digits(_CharT* __s, _CharT __grsep,  char const* __grouping,
831
                    char const* __grend, _CharT const* __first,
832
                    _CharT const* __last)
833
    {
834
      if (__last - __first > *__grouping)
835
        {
836
          __s = __group_digits(__s,  __grsep,
837
              (__grouping + 1 == __grend ? __grouping : __grouping + 1),
838
              __grend, __first, __last - *__grouping);
839
          __first = __last - *__grouping;
840
          *__s++ = __grsep;
841
        }
842
      do
843
        {
844
          *__s++ = *__first++;
845
        }
846
      while (__first != __last);
847
      return __s;
848
    }
849
 
850
  template 
851
    _OutIter
852
    __output_integer(_OutIter __s, ios_base& __io, _CharT __fill, bool __neg,
853
              _ValueT __v)
854
    {
855
      // Leave room for "+/-," "0x," and commas.
856
      const long _M_room = numeric_limits<_ValueT>::digits10 * 2 + 4;
857
      _CharT __digits[_M_room];
858
      _CharT* __front = __digits + _M_room;
859
      ios_base::fmtflags __flags = __io.flags();
860
      const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
861
      char const* __table = __fmt->_S_literals + __fmt->_S_digits;
862
 
863
      ios_base::fmtflags __basefield = (__flags & __io.basefield);
864
      _CharT* __sign_end = __front;
865
      if (__basefield == ios_base::hex)
866
        {
867
          if (__flags & ios_base::uppercase)
868
            __table += 16;  // use ABCDEF
869
          do
870
            *--__front = __table[__v & 15];
871
          while ((__v >>= 4) != 0);
872
          __sign_end = __front;
873
          if (__flags & ios_base::showbase)
874
            {
875
              *--__front = __fmt->_S_literals[__fmt->_S_x +
876
                       ((__flags & ios_base::uppercase) ? 1 : 0)];
877
              *--__front = __table[0];
878
            }
879
        }
880
      else if (__basefield == ios_base::oct)
881
        {
882
          do
883
            *--__front = __table[__v & 7];
884
          while ((__v >>= 3) != 0);
885
          if (__flags & ios_base::showbase
886
              && static_cast(*__front) != __table[0])
887
            *--__front = __table[0];
888
          __sign_end = __front;
889
        }
890
      else
891
        {
892
          // NB: This is _lots_ faster than using ldiv.
893
          do
894
            *--__front = __table[__v % 10];
895
          while ((__v /= 10) != 0);
896
          __sign_end = __front;
897
          // NB: ios_base:hex || ios_base::oct assumed to be unsigned.
898
          if (__neg || (__flags & ios_base::showpos))
899
            *--__front = __fmt->_S_literals[__fmt->_S_plus - __neg];
900
        }
901
 
902
      // XXX should specialize!
903
      if (!__fmt->_M_use_grouping && !__io.width())
904
        return copy(__front, __digits + _M_room, __s);
905
 
906
      if (!__fmt->_M_use_grouping)
907
        return __pad_numeric(__s, __flags, __fill, __io.width(0),
908
			     __front, __sign_end, __digits + _M_room);
909
 
910
      _CharT* __p = __digits;
911
      while (__front < __sign_end)
912
        *__p++ = *__front++;
913
      const char* __gr = __fmt->_M_grouping.data();
914
      __front = __group_digits(__p, __fmt->_M_thousands_sep, __gr,
915
        __gr + __fmt->_M_grouping.size(), __sign_end, __digits + _M_room);
916
      return __pad_numeric(__s, __flags, __fill, __io.width(0),
917
			   __digits, __p, __front);
918
    }
919
 
920
  template 
921
    _OutIter
922
    num_put<_CharT, _OutIter>::
923
    do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
924
    {
925
      unsigned long __uv = __v;
926
      bool __neg = false;
927
      if (__v < 0)
928
        {
929
          __neg = true;
930
          __uv = -__uv;
931
        }
932
      return __output_integer(__s, __io, __fill, __neg, __uv);
933
    }
934
 
935
  template 
936
    _OutIter
937
    num_put<_CharT, _OutIter>::
938
    do_put(iter_type __s, ios_base& __io, char_type __fill,
939
           unsigned long __v) const
940
    { return __output_integer(__s, __io, __fill, false, __v); }
941
 
942
#ifdef _GLIBCPP_USE_LONG_LONG
943
  template 
944
    _OutIter
945
    num_put<_CharT, _OutIter>::
946
    do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
947
    {
948
      unsigned long long __uv = __v;
949
      bool __neg = false;
950
      if (__v < 0)
951
        {
952
          __neg = true;
953
          __uv = -__uv;
954
        }
955
      return __output_integer(__s, __b, __fill, __neg, __uv);
956
    }
957
 
958
  template 
959
    _OutIter
960
    num_put<_CharT, _OutIter>::
961
    do_put(iter_type __s, ios_base& __io, char_type __fill,
962
           unsigned long long __v) const
963
    { return __output_integer(__s, __io, __fill, false, __v); }
964
#endif
965
 
966
  // Generic helper function
967
  template
968
    _OutIter
969
    __output_float(_OutIter __s, ios_base& __io, _CharT __fill,
970
                    const char* __sptr, size_t __slen)
971
    {
972
      // XXX Not currently done: non streambuf_iterator
973
      return __s;
974
    }
975
 
976
  // Partial specialization for ostreambuf_iterator.
977
  template
978
    ostreambuf_iterator<_CharT, _Traits>
979
    __output_float(ostreambuf_iterator<_CharT, _Traits> __s, ios_base& __io,
980
		   _CharT __fill, const char* __sptr, size_t __slen)
981
    {
982
      size_t __padding = __io.width() > streamsize(__slen) ?
983
                         __io.width() -__slen : 0;
984
      locale __loc = __io.getloc();
985
      ctype<_CharT> const& __ct = use_facet >(__loc);
986
      ios_base::fmtflags __adjfield = __io.flags() & ios_base::adjustfield;
987
      const char* const __eptr = __sptr + __slen;
988
      // [22.2.2.2.2.19] Table 61
989
      if (__adjfield == ios_base::internal)
990
       {
991
         // [22.2.2.2.2.14]; widen()
992
         if (__sptr < __eptr && (*__sptr == '+' || *__sptr == '-'))
993
           {
994
             __s = __ct.widen(*__sptr);
995
             ++__s;
996
             ++__sptr;
997
           }
998
         __s = __pad(__s, __fill, __padding);
999
         __padding = 0;
1000
       }
1001
      else if (__adjfield != ios_base::left)
1002
        {
1003
          __s = __pad(__s, __fill, __padding);
1004
          __padding = 0;
1005
        }
1006
      // the "C" locale decimal character
1007
      char __decimal_point = *(localeconv()->decimal_point);
1008
      const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
1009
      for (; __sptr != __eptr; ++__s, ++__sptr)
1010
       {
1011
         // [22.2.2.2.2.17]; decimal point conversion
1012
         if (*__sptr == __decimal_point)
1013
           __s = __fmt->_M_decimal_point;
1014
         // [22.2.2.2.2.14]; widen()
1015
         else
1016
           __s = __ct.widen(*__sptr);
1017
       }
1018
      // [22.2.2.2.2.19] Table 61
1019
      if (__padding)
1020
        __pad(__s, __fill, __padding);
1021
      __io.width(0);
1022
      return __s;
1023
    }
1024
 
1025
  bool
1026
  __build_float_format(ios_base& __io, char* __fptr, char __modifier,
1027
		       streamsize __prec);
1028
 
1029
  template 
1030
    _OutIter
1031
    num_put<_CharT, _OutIter>::
1032
    do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
1033
    {
1034
      const streamsize __max_prec = numeric_limits::digits10 + 3;
1035
      streamsize __prec = __io.precision();
1036
      // Protect against sprintf() buffer overflows.
1037
      if (__prec > __max_prec)
1038
        __prec = __max_prec;
1039
      // The *2 provides for signs, exp, 'E', and pad.
1040
      char __sbuf[__max_prec * 2];
1041
      size_t __slen;
1042
      // Long enough for the max format spec.
1043
      char __fbuf[16];
1044
      if (__build_float_format(__io, __fbuf, 0, __prec))
1045
        __slen = sprintf(__sbuf, __fbuf, __prec, __v);
1046
      else
1047
        __slen = sprintf(__sbuf, __fbuf, __v);
1048
      // [22.2.2.2.2] Stages 2-4.
1049
      return __output_float(__s, __io, __fill, __sbuf, __slen);
1050
    }
1051
 
1052
  template 
1053
    _OutIter
1054
    num_put<_CharT, _OutIter>::
1055
    do_put(iter_type __s, ios_base& __io, char_type __fill,
1056
           long double __v) const
1057
    {
1058
      const streamsize __max_prec = numeric_limits::digits10 + 3;
1059
      streamsize __prec = __io.precision();
1060
      // Protect against sprintf() buffer overflows.
1061
      if (__prec > __max_prec)
1062
        __prec = __max_prec;
1063
      // The *2 provides for signs, exp, 'E', and pad.
1064
      char __sbuf[__max_prec * 2];
1065
      size_t __slen;
1066
      // Long enough for the max format spec.
1067
      char __fbuf[16];
1068
      // 'L' as per [22.2.2.2.2] Table 59
1069
      if (__build_float_format(__io, __fbuf, 'L', __prec))
1070
        __slen = sprintf(__sbuf, __fbuf, __prec, __v);
1071
      else
1072
        __slen = sprintf(__sbuf, __fbuf, __v);
1073
      // [22.2.2.2.2] Stages 2-4
1074
      return __output_float(__s, __io, __fill, __sbuf, __slen);
1075
    }
1076
 
1077
  template 
1078
    _OutIter
1079
    num_put<_CharT, _OutIter>::
1080
    do_put(iter_type __s, ios_base& __io, char_type __fill,
1081
           const void* __v) const
1082
    {
1083
      typedef ios_base::fmtflags        fmtflags;
1084
      fmtflags __fmt = __io.flags();
1085
      fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield
1086
                             | ios_base::uppercase | ios_base::internal);
1087
      __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
1088
      try {
1089
        _OutIter __s2 = __output_integer(__s, __io, __fill, false,
1090
                                  reinterpret_cast(__v));
1091
        __io.flags(__fmt);
1092
        return __s2;
1093
      }
1094
      catch (...) {
1095
        __io.flags(__fmt);
1096
        __throw_exception_again;
1097
      }
1098
    }
1099
 
1100
  // Support for time_get:
1101
  // Note that these partial specializations could, and maybe should,
1102
  // be changed to full specializations (by eliminating the _Dummy
1103
  // argument) and moved to a .cc file.
1104
  template
1105
    struct _Weekdaynames;
1106
 
1107
  template
1108
    struct _Weekdaynames
1109
    { static const char* const _S_names[14]; };
1110
 
1111
  template
1112
    const char* const
1113
    _Weekdaynames::_S_names[14] =
1114
    {
1115
      "Sun", "Sunday",
1116
      "Mon", "Monday",   "Tue", "Tuesday", "Wed", "Wednesday",
1117
      "Thu", "Thursday", "Fri", "Friday",  "Sat", "Saturday"
1118
    };
1119
 
1120
#ifdef _GLIBCPP_USE_WCHAR_T
1121
  template
1122
    struct _Weekdaynames
1123
    { static const wchar_t* const _S_names[14]; };
1124
 
1125
  template
1126
    const wchar_t* const
1127
    _Weekdaynames::_S_names[14] =
1128
    {
1129
      L"Sun", L"Sunday",
1130
      L"Mon", L"Monday",   L"Tue", L"Tuesday", L"Wed", L"Wednesday",
1131
      L"Thu", L"Thursday", L"Fri", L"Friday",  L"Sat", L"Saturday"
1132
    };
1133
#endif
1134
 
1135
  template
1136
    struct _Monthnames;
1137
 
1138
  template
1139
    struct _Monthnames
1140
    { static const char* const _S_names[24]; };
1141
 
1142
  template
1143
    const char* const
1144
    _Monthnames::_S_names[24] =
1145
    {
1146
      "Jan", "January", "Feb", "February", "Mar", "March",
1147
      "Apr", "April",   "May", "May",      "Jun", "June",
1148
      "Jul", "July",    "Aug", "August",   "Sep", "September",
1149
      "Oct", "October", "Nov", "November", "Dec", "December"
1150
    };
1151
 
1152
#ifdef _GLIBCPP_USE_WCHAR_T
1153
  template
1154
    struct _Monthnames
1155
    { static const wchar_t* const _S_names[24]; };
1156
 
1157
  template
1158
    const wchar_t* const
1159
    _Monthnames::_S_names[24] =
1160
    {
1161
      L"Jan", L"January", L"Feb", L"February", L"Mar", L"March",
1162
      L"Apr", L"April",   L"May", L"May",      L"Jun", L"June",
1163
      L"Jul", L"July",    L"Aug", L"August",   L"Sep", L"September",
1164
      L"Oct", L"October", L"Nov", L"November", L"Dec", L"December"
1165
    };
1166
#endif
1167
 
1168
  template
1169
    _InIter
1170
    time_get<_CharT, _InIter>::
1171
    do_get_weekday(iter_type __s, iter_type __end,
1172
                   ios_base& __io, ios_base::iostate& __err, tm* __t) const
1173
    {
1174
      if (!_M_daynames)
1175
        {
1176
          _M_daynames = new basic_string<_CharT>[14];
1177
          for (int __i = 0; __i < 14; ++__i)
1178
            _M_daynames[__i] = _Weekdaynames<_CharT>::_S_names[__i];
1179
        }
1180
      bool __at_eof = false;
1181
      int __remain = 0;
1182
      int __matches[14];
1183
      iter_type __out = __match_parallel(__s, __end, 14, _M_daynames,
1184
                                         __matches, __remain, __at_eof);
1185
      __err = ios_base::iostate(0);
1186
      if (__at_eof) __err |= __io.eofbit;
1187
      if (__remain == 1 ||
1188
          __remain == 2 && (__matches[0]>>1) == (__matches[1]>>1))
1189
        __t->tm_wday = (__matches[0]>>1);
1190
      else
1191
        __err |= __io.failbit;
1192
      return __out;
1193
    }
1194
 
1195
  template
1196
    _InIter
1197
    time_get<_CharT, _InIter>::
1198
    do_get_monthname(iter_type __s, iter_type __end,
1199
                     ios_base& __io, ios_base::iostate& __err, tm* __t) const
1200
    {
1201
      if (!_M_monthnames)
1202
        {
1203
          _M_monthnames = new basic_string<_CharT>[24];
1204
          for (int __i = 0; __i < 24; ++__i)
1205
            _M_monthnames[__i] = _Monthnames<_CharT>::_S_names[__i];
1206
        }
1207
      bool __at_eof = false;
1208
      int __remain = 0;
1209
      int __matches[24];
1210
      iter_type __out = __match_parallel( __s, __end, 24, _M_monthnames,
1211
                                          __matches, __remain, __at_eof);
1212
      __err = ios_base::iostate(0);
1213
      if (__at_eof) __err |= __io.eofbit;
1214
      if (__remain == 1 ||
1215
          __remain == 2 && (__matches[0]>>1) == (__matches[1]>>1))
1216
        __t->tm_mon = (__matches[0]>>1);
1217
      else
1218
        __err |= __io.failbit;
1219
      return __out;
1220
    }
1221
} // std::
1222
 
1223
#endif /* _CPP_BITS_LOCFACETS_TCC */
1224
 
1225
// Local Variables:
1226
// mode:c++
1227
// End: