]> git.buserror.net Git - polintos/scott/priv.git/blob - include/c++/stl/stl/_num_put.c
minor doc updates
[polintos/scott/priv.git] / include / c++ / stl / stl / _num_put.c
1 /*
2  * Copyright (c) 1999
3  * Silicon Graphics Computer Systems, Inc.
4  *
5  * Copyright (c) 1999
6  * Boris Fomitchev
7  *
8  * This material is provided "as is", with absolutely no warranty expressed
9  * or implied. Any use is at your own risk.
10  *
11  * Permission to use or copy this software for any purpose is hereby granted
12  * without fee, provided the above notices are retained on all copies.
13  * Permission to modify the code and to distribute modified code is granted,
14  * provided the above notices are retained, and a notice that the code was
15  * modified is included with the above copyright notice.
16  *
17  */
18 #ifndef _STLP_NUM_PUT_C
19 #define _STLP_NUM_PUT_C
20
21 #ifndef _STLP_INTERNAL_NUM_PUT_H
22 #  include <stl/_num_put.h>
23 #endif
24
25 #ifndef _STLP_INTERNAL_LIMITS
26 #  include <stl/_limits.h>
27 #endif
28
29 _STLP_BEGIN_NAMESPACE
30
31 _STLP_MOVE_TO_PRIV_NAMESPACE
32
33 // __do_put_float and its helper functions.  Strategy: write the output
34 // to a buffer of char, transform the buffer to _CharT, and then copy
35 // it to the output.
36
37 //----------------------------------------------------------------------
38 // num_put facet
39
40 template <class _CharT, class _OutputIter>
41 _OutputIter  _STLP_CALL
42 __copy_float_and_fill(const _CharT* __first, const _CharT* __last,
43                       _OutputIter __oi,
44                       ios_base::fmtflags __flags,
45                       streamsize __width, _CharT __fill,
46                       _CharT __xplus, _CharT __xminus) {
47   if (__width <= __last - __first)
48     return copy(__first, __last, __oi);
49   else {
50     streamsize __pad = __width - (__last - __first);
51     ios_base::fmtflags __dir = __flags & ios_base::adjustfield;
52
53     if (__dir == ios_base::left) {
54       __oi = copy(__first, __last, __oi);
55       return __fill_n(__oi, __pad, __fill);
56     }
57     else if (__dir == ios_base::internal && __first != __last &&
58              (*__first == __xplus || *__first == __xminus)) {
59       *__oi++ = *__first++;
60       __oi = __fill_n(__oi, __pad, __fill);
61       return copy(__first, __last, __oi);
62     }
63     else {
64       __oi = __fill_n(__oi, __pad, __fill);
65       return copy(__first, __last, __oi);
66     }
67   }
68 }
69
70 #if !defined (_STLP_NO_WCHAR_T)
71 // Helper routine for wchar_t
72 template <class _OutputIter>
73 _OutputIter  _STLP_CALL
74 __put_float(__iostring &__str, _OutputIter __oi,
75             ios_base& __f, wchar_t __fill,
76             wchar_t __decimal_point, wchar_t __sep,
77             size_t __group_pos, const string& __grouping) {
78   const ctype<wchar_t>& __ct = *__STATIC_CAST(const ctype<wchar_t>*, __f._M_ctype_facet());
79
80   __iowstring __wbuf;
81   __convert_float_buffer(__str, __wbuf, __ct, __decimal_point);
82
83   if (!__grouping.empty()) {
84     __insert_grouping(__wbuf, __group_pos, __grouping,
85                       __sep, __ct.widen('+'), __ct.widen('-'), 0);
86   }
87
88   return __copy_float_and_fill(__CONST_CAST(wchar_t*, __wbuf.data()),
89                                __CONST_CAST(wchar_t*, __wbuf.data()) + __wbuf.size(), __oi,
90                                __f.flags(), __f.width(0), __fill, __ct.widen('+'), __ct.widen('-'));
91 }
92 #endif /* WCHAR_T */
93
94 // Helper routine for char
95 template <class _OutputIter>
96 _OutputIter  _STLP_CALL
97 __put_float(__iostring &__str, _OutputIter __oi,
98             ios_base& __f, char __fill,
99             char __decimal_point, char __sep,
100             size_t __group_pos, const string& __grouping) {
101   if ((__group_pos < __str.size()) && (__str[__group_pos] == '.')) {
102     __str[__group_pos] = __decimal_point;
103   }
104
105   if (!__grouping.empty()) {
106     __insert_grouping(__str, __group_pos,
107                       __grouping, __sep, '+', '-', 0);
108   }
109
110   return __copy_float_and_fill(__CONST_CAST(char*, __str.data()),
111                                __CONST_CAST(char*, __str.data()) + __str.size(), __oi,
112                                __f.flags(), __f.width(0), __fill, '+', '-');
113 }
114
115 template <class _CharT, class _OutputIter, class _Float>
116 _OutputIter _STLP_CALL
117 __do_put_float(_OutputIter __s, ios_base& __f,
118                 _CharT __fill, _Float __x) {
119   __iostring __buf;
120
121   size_t __group_pos = __write_float(__buf, __f.flags(), (int)__f.precision(), __x);
122
123   const numpunct<_CharT>& __np = *__STATIC_CAST(const numpunct<_CharT>*, __f._M_numpunct_facet());
124
125   return __put_float(__buf, __s, __f, __fill,
126                      __np.decimal_point(), __np.thousands_sep(),
127                      __group_pos, __f._M_grouping());
128 }
129
130 inline void __get_money_digits_aux (__iostring &__buf, ios_base &, _STLP_LONGEST_FLOAT_TYPE __x)
131 { __get_floor_digits(__buf, __x); }
132
133 #if !defined (_STLP_NO_WCHAR_T)
134 inline void __get_money_digits_aux (__iowstring &__wbuf, ios_base &__f, _STLP_LONGEST_FLOAT_TYPE __x) {
135   __iostring __buf;
136   __get_floor_digits(__buf, __x);
137
138   const ctype<wchar_t>& __ct = *__STATIC_CAST(const ctype<wchar_t>*, __f._M_ctype_facet());
139   __convert_float_buffer(__buf, __wbuf, __ct, wchar_t(0), false);
140 }
141 #endif
142
143 template <class _CharT>
144 void _STLP_CALL __get_money_digits(_STLP_BASIC_IOSTRING(_CharT) &__buf, ios_base& __f, _STLP_LONGEST_FLOAT_TYPE __x)
145 { __get_money_digits_aux(__buf, __f, __x); }
146
147 // _M_do_put_integer and its helper functions.
148
149 template <class _CharT, class _OutputIter>
150 _OutputIter _STLP_CALL
151 __copy_integer_and_fill(const _CharT* __buf, ptrdiff_t __len,
152                         _OutputIter __oi,
153                         ios_base::fmtflags __flg, streamsize __wid, _CharT __fill,
154                         _CharT __xplus, _CharT __xminus) {
155   if (__len >= __wid)
156     return copy(__buf, __buf + __len, __oi);
157   else {
158     //casting numeric_limits<ptrdiff_t>::max to streamsize only works is ptrdiff_t is signed or streamsize representation
159     //is larger than ptrdiff_t one.
160     _STLP_STATIC_ASSERT((sizeof(streamsize) > sizeof(ptrdiff_t)) ||
161                         (sizeof(streamsize) == sizeof(ptrdiff_t)) && numeric_limits<ptrdiff_t>::is_signed)
162     ptrdiff_t __pad = __STATIC_CAST(ptrdiff_t, (min) (__STATIC_CAST(streamsize, (numeric_limits<ptrdiff_t>::max)()),
163                                                       __STATIC_CAST(streamsize, __wid - __len)));
164     ios_base::fmtflags __dir = __flg & ios_base::adjustfield;
165
166     if (__dir == ios_base::left) {
167       __oi = copy(__buf, __buf + __len, __oi);
168       return __fill_n(__oi, __pad, __fill);
169     }
170     else if (__dir == ios_base::internal && __len != 0 &&
171              (__buf[0] == __xplus || __buf[0] == __xminus)) {
172       *__oi++ = __buf[0];
173       __oi = __fill_n(__oi, __pad, __fill);
174       return copy(__buf + 1, __buf + __len, __oi);
175     }
176     else if (__dir == ios_base::internal && __len >= 2  &&
177              (__flg & ios_base::showbase) &&
178              (__flg & ios_base::basefield) == ios_base::hex) {
179       *__oi++ = __buf[0];
180       *__oi++ = __buf[1];
181       __oi = __fill_n(__oi, __pad, __fill);
182       return copy(__buf + 2, __buf + __len, __oi);
183     }
184     else {
185       __oi = __fill_n(__oi, __pad, __fill);
186       return copy(__buf, __buf + __len, __oi);
187     }
188   }
189 }
190
191 #if !defined (_STLP_NO_WCHAR_T)
192 // Helper function for wchar_t
193 template <class _OutputIter>
194 _OutputIter _STLP_CALL
195 __put_integer(char* __buf, char* __iend, _OutputIter __s,
196               ios_base& __f,
197               ios_base::fmtflags __flags, wchar_t __fill) {
198   locale __loc = __f.getloc();
199   //  const ctype<wchar_t>& __ct = use_facet<ctype<wchar_t> >(__loc);
200   const ctype<wchar_t>& __ct = *__STATIC_CAST(const ctype<wchar_t>*, __f._M_ctype_facet());
201
202   wchar_t __xplus  = __ct.widen('+');
203   wchar_t __xminus = __ct.widen('-');
204
205   wchar_t __wbuf[64];
206   __ct.widen(__buf, __iend, __wbuf);
207   ptrdiff_t __len = __iend - __buf;
208   wchar_t* __eend = __wbuf + __len;
209
210   //  const numpunct<wchar_t>& __np = use_facet<numpunct<wchar_t> >(__loc);
211   //  const string& __grouping = __np.grouping();
212
213   const numpunct<wchar_t>& __np = *__STATIC_CAST(const numpunct<wchar_t>*, __f._M_numpunct_facet());
214   const string& __grouping = __f._M_grouping();
215
216   if (!__grouping.empty()) {
217     int __basechars;
218     if (__flags & ios_base::showbase)
219       switch (__flags & ios_base::basefield) {
220         case ios_base::hex: __basechars = 2; break;
221         case ios_base::oct: __basechars = 1; break;
222         default: __basechars = 0;
223       }
224     else
225       __basechars = 0;
226
227     __len = __insert_grouping(__wbuf, __eend, __grouping, __np.thousands_sep(),
228                               __xplus, __xminus, __basechars);
229   }
230
231   return __copy_integer_and_fill((wchar_t*)__wbuf, __len, __s,
232                                  __flags, __f.width(0), __fill, __xplus, __xminus);
233 }
234 #endif
235
236 // Helper function for char
237 template <class _OutputIter>
238 _OutputIter _STLP_CALL
239 __put_integer(char* __buf, char* __iend, _OutputIter __s,
240               ios_base& __f, ios_base::fmtflags __flags, char __fill) {
241   char __grpbuf[64];
242   ptrdiff_t __len = __iend - __buf;
243
244   //  const numpunct<char>& __np = use_facet<numpunct<char> >(__f.getloc());
245   //  const string& __grouping = __np.grouping();
246
247   const numpunct<char>& __np = *__STATIC_CAST(const numpunct<char>*, __f._M_numpunct_facet());
248   const string& __grouping = __f._M_grouping();
249
250   if (!__grouping.empty()) {
251     int __basechars;
252     if (__flags & ios_base::showbase)
253       switch (__flags & ios_base::basefield) {
254         case ios_base::hex: __basechars = 2; break;
255         case ios_base::oct: __basechars = 1; break;
256         default: __basechars = 0;
257       }
258     else
259       __basechars = 0;
260
261      // make sure there is room at the end of the buffer
262      // we pass to __insert_grouping
263     copy(__buf, __iend, (char *) __grpbuf);
264     __buf = __grpbuf;
265     __iend = __grpbuf + __len;
266     __len = __insert_grouping(__buf, __iend, __grouping, __np.thousands_sep(),
267                               '+', '-', __basechars);
268   }
269
270   return __copy_integer_and_fill(__buf, __len, __s, __flags, __f.width(0), __fill, '+', '-');
271 }
272
273 #if defined (_STLP_LONG_LONG)
274 typedef _STLP_LONG_LONG __max_int_t;
275 typedef unsigned _STLP_LONG_LONG __umax_int_t;
276 #else
277 typedef long __max_int_t;
278 typedef unsigned long __umax_int_t;
279 #endif
280
281 _STLP_DECLSPEC const char* _STLP_CALL __hex_char_table_lo();
282 _STLP_DECLSPEC const char* _STLP_CALL __hex_char_table_hi();
283
284 template <class _Integer>
285 inline char* _STLP_CALL
286 __write_decimal_backward(char* __ptr, _Integer __x, ios_base::fmtflags __flags, const __true_type& /* is_signed */) {
287   const bool __negative = __x < 0 ;
288   __max_int_t __temp = __x;
289   __umax_int_t __utemp = __negative?-__temp:__temp;
290
291   for (; __utemp != 0; __utemp /= 10)
292     *--__ptr = (char)((int)(__utemp % 10) + '0');
293   // put sign if needed or requested
294   if (__negative)
295     *--__ptr = '-';
296   else if (__flags & ios_base::showpos)
297     *--__ptr = '+';
298   return __ptr;
299 }
300
301 template <class _Integer>
302 inline char* _STLP_CALL
303 __write_decimal_backward(char* __ptr, _Integer __x, ios_base::fmtflags __flags, const __false_type& /* is_signed */) {
304   for (; __x != 0; __x /= 10)
305     *--__ptr = (char)((int)(__x % 10) + '0');
306   // put sign if requested
307   if (__flags & ios_base::showpos)
308     *--__ptr = '+';
309   return __ptr;
310 }
311
312 template <class _Integer>
313 char* _STLP_CALL
314 __write_integer_backward(char* __buf, ios_base::fmtflags __flags, _Integer __x) {
315   char* __ptr = __buf;
316
317   if (__x == 0) {
318     *--__ptr = '0';
319     if ((__flags & ios_base::showpos) && ((__flags & (ios_base::oct | ios_base::hex)) == 0))
320       *--__ptr = '+';
321     // oct or hex base shall not be added to the 0 value (see '#' flag in C formating strings)
322   }
323   else {
324     switch (__flags & ios_base::basefield) {
325       case ios_base::oct:
326         {
327           __umax_int_t __temp = __x;
328           // if the size of integer is less than 8, clear upper part
329           if ( sizeof(__x) < 8  && sizeof(__umax_int_t) >= 8 )
330             __temp &= 0xFFFFFFFF;
331
332           for (; __temp != 0; __temp >>=3)
333             *--__ptr = (char)((((unsigned)__temp)& 0x7) + '0');
334
335           // put leading '0' if showbase is set
336           if (__flags & ios_base::showbase)
337             *--__ptr = '0';
338         }
339         break;
340       case ios_base::hex:
341         {
342           const char* __table_ptr = (__flags & ios_base::uppercase) ?
343             __hex_char_table_hi() : __hex_char_table_lo();
344           __umax_int_t __temp = __x;
345           // if the size of integer is less than 8, clear upper part
346           if ( sizeof(__x) < 8  && sizeof(__umax_int_t) >= 8 )
347             __temp &= 0xFFFFFFFF;
348
349           for (; __temp != 0; __temp >>=4)
350             *--__ptr = __table_ptr[((unsigned)__temp & 0xF)];
351
352           if (__flags & ios_base::showbase) {
353             *--__ptr = __table_ptr[16];
354             *--__ptr = '0';
355           }
356         }
357         break;
358       //case ios_base::dec:
359       default:
360         {
361 #if defined(__HP_aCC) && (__HP_aCC == 1)
362           bool _IsSigned = !((_Integer)-1 > 0);
363           if (_IsSigned)
364             __ptr = __write_decimal_backward(__ptr, __x, __flags, __true_type() );
365           else
366             __ptr = __write_decimal_backward(__ptr, __x, __flags, __false_type() );
367 #else
368           typedef typename __bool2type<numeric_limits<_Integer>::is_signed>::_Ret _IsSigned;
369           __ptr = __write_decimal_backward(__ptr, __x, __flags, _IsSigned());
370 #endif
371         }
372         break;
373     }
374   }
375
376   // return pointer to beginning of the string
377   return __ptr;
378 }
379
380 template <class _CharT, class _OutputIter, class _Integer>
381 _OutputIter _STLP_CALL
382 __do_put_integer(_OutputIter __s, ios_base& __f, _CharT __fill, _Integer __x) {
383   // buffer size = number of bytes * number of digit necessary in the smallest Standard base (base 8, 3 digits/byte)
384   //               plus the longest base representation '0x'
385   // Do not use __buf_size to define __buf static buffer, some compilers (HP aCC) do not accept const variable as
386   // the specification of a static buffer size.
387   char __buf[sizeof(_Integer) * 3 + 2];
388   const ptrdiff_t __buf_size = sizeof(__buf) / sizeof(char);
389   ios_base::fmtflags __flags = __f.flags();
390   char* __ibeg = __write_integer_backward((char*)__buf+__buf_size, __flags, __x);
391   return __put_integer(__ibeg, (char*)__buf+__buf_size, __s, __f, __flags, __fill);
392 }
393
394 _STLP_MOVE_TO_STD_NAMESPACE
395
396 //
397 // num_put<>
398 //
399
400 #if (_STLP_STATIC_TEMPLATE_DATA > 0)
401
402 #  if !defined (__BORLANDC__)
403 template <class _CharT, class _OutputIterator>
404 locale::id num_put<_CharT, _OutputIterator>::id;
405 #  endif
406
407 #  if (defined (__CYGWIN__) || defined (__MINGW32__)) && \
408        defined (_STLP_USE_DYNAMIC_LIB) && !defined (__BUILDING_STLPORT)
409 /*
410  * Under cygwin, when STLport is used as a shared library, the id needs
411  * to be specified as imported otherwise they will be duplicated in the
412  * calling executable.
413  */
414 template <>
415 _STLP_DECLSPEC locale::id num_put<char, ostreambuf_iterator<char, char_traits<char> > >::id;
416 /*
417 template <>
418 _STLP_DECLSPEC locale::id num_put<char, char*>::id;
419 */
420
421 #    if !defined (_STLP_NO_WCHAR_T)
422 template <>
423 _STLP_DECLSPEC locale::id num_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id;
424 /*
425 template <>
426 _STLP_DECLSPEC locale::id num_put<wchar_t, wchar_t*>::id;
427 */
428 #    endif
429
430 #  endif /* __CYGWIN__ && _STLP_USE_DYNAMIC_LIB */
431
432 #else /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
433
434 //typedef num_put<char, char*> num_put_char;
435 typedef num_put<char, ostreambuf_iterator<char, char_traits<char> > > num_put_char_2;
436
437 //__DECLARE_INSTANCE(locale::id, num_put_char::id, );
438 __DECLARE_INSTANCE(locale::id, num_put_char_2::id, );
439
440 #  if !defined (_STLP_NO_WCHAR_T)
441
442 //typedef num_put<wchar_t, wchar_t*> num_put_wchar_t;
443 typedef num_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > > num_put_wchar_t_2;
444
445 //__DECLARE_INSTANCE(locale::id, num_put_wchar_t::id, );
446 __DECLARE_INSTANCE(locale::id, num_put_wchar_t_2::id, );
447
448 #  endif
449
450 #endif /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
451
452 // issue 118
453
454 #if !defined (_STLP_NO_BOOL)
455 template <class _CharT, class _OutputIter>
456 _OutputIter
457 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f,
458                                      char_type __fill,  bool __val) const {
459   if (!(__f.flags() & ios_base::boolalpha))
460     return this->do_put(__s, __f, __fill, __STATIC_CAST(long,__val));
461
462   locale __loc = __f.getloc();
463   //  typedef numpunct<_CharT> _Punct;
464   //  const _Punct& __np = use_facet<_Punct>(__loc);
465
466   const numpunct<_CharT>& __np = *__STATIC_CAST(const numpunct<_CharT>*, __f._M_numpunct_facet());
467
468   basic_string<_CharT> __str = __val ? __np.truename() : __np.falsename();
469
470   // Reuse __copy_integer_and_fill.  Since internal padding makes no
471   // sense for bool, though, make sure we use something else instead.
472   // The last two argument to __copy_integer_and_fill are dummies.
473   ios_base::fmtflags __flags = __f.flags();
474   if ((__flags & ios_base::adjustfield) == ios_base::internal)
475     __flags = (__flags & ~ios_base::adjustfield) | ios_base::right;
476
477   return _STLP_PRIV __copy_integer_and_fill(__str.c_str(), __str.size(), __s,
478                                             __flags, __f.width(0), __fill,
479                                             (_CharT) 0, (_CharT) 0);
480 }
481
482 #endif
483
484 template <class _CharT, class _OutputIter>
485 _OutputIter
486 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
487                                      long __val) const
488 { return _STLP_PRIV __do_put_integer(__s, __f, __fill, __val); }
489
490 template <class _CharT, class _OutputIter>
491 _OutputIter
492 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
493                                      unsigned long __val) const
494 { return _STLP_PRIV __do_put_integer(__s, __f, __fill, __val); }
495
496 template <class _CharT, class _OutputIter>
497 _OutputIter
498 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
499                                      double __val) const
500 { return _STLP_PRIV __do_put_float(__s, __f, __fill, __val); }
501
502 #if !defined (_STLP_NO_LONG_DOUBLE)
503 template <class _CharT, class _OutputIter>
504 _OutputIter
505 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
506                                      long double __val) const
507 { return _STLP_PRIV __do_put_float(__s, __f, __fill, __val); }
508 #endif
509
510 #if defined (_STLP_LONG_LONG)
511 template <class _CharT, class _OutputIter>
512 _OutputIter
513 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
514                                      _STLP_LONG_LONG __val) const
515 { return _STLP_PRIV __do_put_integer(__s, __f, __fill, __val); }
516
517 template <class _CharT, class _OutputIter>
518 _OutputIter
519 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
520                                      unsigned _STLP_LONG_LONG __val) const
521 { return _STLP_PRIV __do_put_integer(__s, __f, __fill, __val); }
522 #endif /* _STLP_LONG_LONG */
523
524
525 // lib.facet.num.put.virtuals "12 For conversion from void* the specifier is %p."
526 template <class _CharT, class _OutputIter>
527 _OutputIter
528 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT /*__fill*/,
529                                      const void* __val) const {
530   const ctype<_CharT>& __c_type = *__STATIC_CAST(const ctype<_CharT>*, __f._M_ctype_facet());
531   ios_base::fmtflags __save_flags = __f.flags();
532
533   __f.setf(ios_base::hex, ios_base::basefield);
534   __f.setf(ios_base::showbase);
535   __f.setf(ios_base::internal, ios_base::adjustfield);
536   __f.width((sizeof(void*) * 2) + 2); // digits in pointer type plus '0x' prefix
537 # if defined(_STLP_LONG_LONG) && !defined(__MRC__) //*ty 11/24/2001 - MrCpp can not cast from void* to long long
538   _OutputIter result = this->do_put(__s, __f, __c_type.widen('0'), __REINTERPRET_CAST(unsigned _STLP_LONG_LONG,__val));
539 # else
540   _OutputIter result = this->do_put(__s, __f, __c_type.widen('0'), __REINTERPRET_CAST(unsigned long,__val));
541 # endif
542   __f.flags(__save_flags);
543   return result;
544 }
545
546 _STLP_END_NAMESPACE
547
548 #endif /* _STLP_NUM_PUT_C */
549
550 // Local Variables:
551 // mode:C++
552 // End: