3 * Silicon Graphics Computer Systems, Inc.
8 * This material is provided "as is", with absolutely no warranty expressed
9 * or implied. Any use is at your own risk.
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.
18 #ifndef _STLP_NUM_PUT_C
19 #define _STLP_NUM_PUT_C
21 #ifndef _STLP_INTERNAL_NUM_PUT_H
22 # include <stl/_num_put.h>
25 #ifndef _STLP_INTERNAL_LIMITS
26 # include <stl/_limits.h>
31 _STLP_MOVE_TO_PRIV_NAMESPACE
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
37 //----------------------------------------------------------------------
40 template <class _CharT, class _OutputIter>
41 _OutputIter _STLP_CALL
42 __copy_float_and_fill(const _CharT* __first, const _CharT* __last,
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);
50 streamsize __pad = __width - (__last - __first);
51 ios_base::fmtflags __dir = __flags & ios_base::adjustfield;
53 if (__dir == ios_base::left) {
54 __oi = copy(__first, __last, __oi);
55 return __fill_n(__oi, __pad, __fill);
57 else if (__dir == ios_base::internal && __first != __last &&
58 (*__first == __xplus || *__first == __xminus)) {
60 __oi = __fill_n(__oi, __pad, __fill);
61 return copy(__first, __last, __oi);
64 __oi = __fill_n(__oi, __pad, __fill);
65 return copy(__first, __last, __oi);
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());
81 __convert_float_buffer(__str, __wbuf, __ct, __decimal_point);
83 if (!__grouping.empty()) {
84 __insert_grouping(__wbuf, __group_pos, __grouping,
85 __sep, __ct.widen('+'), __ct.widen('-'), 0);
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('-'));
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;
105 if (!__grouping.empty()) {
106 __insert_grouping(__str, __group_pos,
107 __grouping, __sep, '+', '-', 0);
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, '+', '-');
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) {
121 size_t __group_pos = __write_float(__buf, __f.flags(), (int)__f.precision(), __x);
123 const numpunct<_CharT>& __np = *__STATIC_CAST(const numpunct<_CharT>*, __f._M_numpunct_facet());
125 return __put_float(__buf, __s, __f, __fill,
126 __np.decimal_point(), __np.thousands_sep(),
127 __group_pos, __f._M_grouping());
130 inline void __get_money_digits_aux (__iostring &__buf, ios_base &, _STLP_LONGEST_FLOAT_TYPE __x)
131 { __get_floor_digits(__buf, __x); }
133 #if !defined (_STLP_NO_WCHAR_T)
134 inline void __get_money_digits_aux (__iowstring &__wbuf, ios_base &__f, _STLP_LONGEST_FLOAT_TYPE __x) {
136 __get_floor_digits(__buf, __x);
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);
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); }
147 // _M_do_put_integer and its helper functions.
149 template <class _CharT, class _OutputIter>
150 _OutputIter _STLP_CALL
151 __copy_integer_and_fill(const _CharT* __buf, ptrdiff_t __len,
153 ios_base::fmtflags __flg, streamsize __wid, _CharT __fill,
154 _CharT __xplus, _CharT __xminus) {
156 return copy(__buf, __buf + __len, __oi);
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;
166 if (__dir == ios_base::left) {
167 __oi = copy(__buf, __buf + __len, __oi);
168 return __fill_n(__oi, __pad, __fill);
170 else if (__dir == ios_base::internal && __len != 0 &&
171 (__buf[0] == __xplus || __buf[0] == __xminus)) {
173 __oi = __fill_n(__oi, __pad, __fill);
174 return copy(__buf + 1, __buf + __len, __oi);
176 else if (__dir == ios_base::internal && __len >= 2 &&
177 (__flg & ios_base::showbase) &&
178 (__flg & ios_base::basefield) == ios_base::hex) {
181 __oi = __fill_n(__oi, __pad, __fill);
182 return copy(__buf + 2, __buf + __len, __oi);
185 __oi = __fill_n(__oi, __pad, __fill);
186 return copy(__buf, __buf + __len, __oi);
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,
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());
202 wchar_t __xplus = __ct.widen('+');
203 wchar_t __xminus = __ct.widen('-');
206 __ct.widen(__buf, __iend, __wbuf);
207 ptrdiff_t __len = __iend - __buf;
208 wchar_t* __eend = __wbuf + __len;
210 // const numpunct<wchar_t>& __np = use_facet<numpunct<wchar_t> >(__loc);
211 // const string& __grouping = __np.grouping();
213 const numpunct<wchar_t>& __np = *__STATIC_CAST(const numpunct<wchar_t>*, __f._M_numpunct_facet());
214 const string& __grouping = __f._M_grouping();
216 if (!__grouping.empty()) {
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;
227 __len = __insert_grouping(__wbuf, __eend, __grouping, __np.thousands_sep(),
228 __xplus, __xminus, __basechars);
231 return __copy_integer_and_fill((wchar_t*)__wbuf, __len, __s,
232 __flags, __f.width(0), __fill, __xplus, __xminus);
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) {
242 ptrdiff_t __len = __iend - __buf;
244 // const numpunct<char>& __np = use_facet<numpunct<char> >(__f.getloc());
245 // const string& __grouping = __np.grouping();
247 const numpunct<char>& __np = *__STATIC_CAST(const numpunct<char>*, __f._M_numpunct_facet());
248 const string& __grouping = __f._M_grouping();
250 if (!__grouping.empty()) {
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;
261 // make sure there is room at the end of the buffer
262 // we pass to __insert_grouping
263 copy(__buf, __iend, (char *) __grpbuf);
265 __iend = __grpbuf + __len;
266 __len = __insert_grouping(__buf, __iend, __grouping, __np.thousands_sep(),
267 '+', '-', __basechars);
270 return __copy_integer_and_fill(__buf, __len, __s, __flags, __f.width(0), __fill, '+', '-');
273 #if defined (_STLP_LONG_LONG)
274 typedef _STLP_LONG_LONG __max_int_t;
275 typedef unsigned _STLP_LONG_LONG __umax_int_t;
277 typedef long __max_int_t;
278 typedef unsigned long __umax_int_t;
281 _STLP_DECLSPEC const char* _STLP_CALL __hex_char_table_lo();
282 _STLP_DECLSPEC const char* _STLP_CALL __hex_char_table_hi();
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;
291 for (; __utemp != 0; __utemp /= 10)
292 *--__ptr = (char)((int)(__utemp % 10) + '0');
293 // put sign if needed or requested
296 else if (__flags & ios_base::showpos)
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)
312 template <class _Integer>
314 __write_integer_backward(char* __buf, ios_base::fmtflags __flags, _Integer __x) {
319 if ((__flags & ios_base::showpos) && ((__flags & (ios_base::oct | ios_base::hex)) == 0))
321 // oct or hex base shall not be added to the 0 value (see '#' flag in C formating strings)
324 switch (__flags & ios_base::basefield) {
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;
332 for (; __temp != 0; __temp >>=3)
333 *--__ptr = (char)((((unsigned)__temp)& 0x7) + '0');
335 // put leading '0' if showbase is set
336 if (__flags & ios_base::showbase)
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;
349 for (; __temp != 0; __temp >>=4)
350 *--__ptr = __table_ptr[((unsigned)__temp & 0xF)];
352 if (__flags & ios_base::showbase) {
353 *--__ptr = __table_ptr[16];
358 //case ios_base::dec:
361 #if defined(__HP_aCC) && (__HP_aCC == 1)
362 bool _IsSigned = !((_Integer)-1 > 0);
364 __ptr = __write_decimal_backward(__ptr, __x, __flags, __true_type() );
366 __ptr = __write_decimal_backward(__ptr, __x, __flags, __false_type() );
368 typedef typename __bool2type<numeric_limits<_Integer>::is_signed>::_Ret _IsSigned;
369 __ptr = __write_decimal_backward(__ptr, __x, __flags, _IsSigned());
376 // return pointer to beginning of the string
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);
394 _STLP_MOVE_TO_STD_NAMESPACE
400 #if (_STLP_STATIC_TEMPLATE_DATA > 0)
402 # if !defined (__BORLANDC__)
403 template <class _CharT, class _OutputIterator>
404 locale::id num_put<_CharT, _OutputIterator>::id;
407 # if (defined (__CYGWIN__) || defined (__MINGW32__)) && \
408 defined (_STLP_USE_DYNAMIC_LIB) && !defined (__BUILDING_STLPORT)
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.
415 _STLP_DECLSPEC locale::id num_put<char, ostreambuf_iterator<char, char_traits<char> > >::id;
418 _STLP_DECLSPEC locale::id num_put<char, char*>::id;
421 # if !defined (_STLP_NO_WCHAR_T)
423 _STLP_DECLSPEC locale::id num_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id;
426 _STLP_DECLSPEC locale::id num_put<wchar_t, wchar_t*>::id;
430 # endif /* __CYGWIN__ && _STLP_USE_DYNAMIC_LIB */
432 #else /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
434 //typedef num_put<char, char*> num_put_char;
435 typedef num_put<char, ostreambuf_iterator<char, char_traits<char> > > num_put_char_2;
437 //__DECLARE_INSTANCE(locale::id, num_put_char::id, );
438 __DECLARE_INSTANCE(locale::id, num_put_char_2::id, );
440 # if !defined (_STLP_NO_WCHAR_T)
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;
445 //__DECLARE_INSTANCE(locale::id, num_put_wchar_t::id, );
446 __DECLARE_INSTANCE(locale::id, num_put_wchar_t_2::id, );
450 #endif /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
454 #if !defined (_STLP_NO_BOOL)
455 template <class _CharT, class _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));
462 locale __loc = __f.getloc();
463 // typedef numpunct<_CharT> _Punct;
464 // const _Punct& __np = use_facet<_Punct>(__loc);
466 const numpunct<_CharT>& __np = *__STATIC_CAST(const numpunct<_CharT>*, __f._M_numpunct_facet());
468 basic_string<_CharT> __str = __val ? __np.truename() : __np.falsename();
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;
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);
484 template <class _CharT, class _OutputIter>
486 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
488 { return _STLP_PRIV __do_put_integer(__s, __f, __fill, __val); }
490 template <class _CharT, class _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); }
496 template <class _CharT, class _OutputIter>
498 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
500 { return _STLP_PRIV __do_put_float(__s, __f, __fill, __val); }
502 #if !defined (_STLP_NO_LONG_DOUBLE)
503 template <class _CharT, class _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); }
510 #if defined (_STLP_LONG_LONG)
511 template <class _CharT, class _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); }
517 template <class _CharT, class _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 */
525 // lib.facet.num.put.virtuals "12 For conversion from void* the specifier is %p."
526 template <class _CharT, class _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();
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));
540 _OutputIter result = this->do_put(__s, __f, __c_type.widen('0'), __REINTERPRET_CAST(unsigned long,__val));
542 __f.flags(__save_flags);
548 #endif /* _STLP_NUM_PUT_C */