2 * Portions Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
5 * Silicon Graphics Computer Systems, Inc.
10 * This material is provided "as is", with absolutely no warranty expressed
11 * or implied. Any use is at your own risk.
13 * Permission to use or copy this software for any purpose is hereby granted
14 * without fee, provided the above notices are retained on all copies.
15 * Permission to modify the code and to distribute modified code is granted,
16 * provided the above notices are retained, and a notice that the code was
17 * modified is included with the above copyright notice.
20 #ifndef _STLP_NUM_PUT_C
21 #define _STLP_NUM_PUT_C
23 #ifndef _STLP_INTERNAL_NUM_PUT_H
24 # include <stl/_num_put.h>
27 #ifndef _STLP_INTERNAL_LIMITS
28 # include <stl/_limits.h>
33 _STLP_MOVE_TO_PRIV_NAMESPACE
35 // __do_put_float and its helper functions. Strategy: write the output
36 // to a buffer of char, transform the buffer to _CharT, and then copy
39 //----------------------------------------------------------------------
42 template <class _CharT, class _OutputIter>
43 _OutputIter _STLP_CALL
44 __copy_float_and_fill(const _CharT* __first, const _CharT* __last,
46 ios_base::fmtflags __flags,
47 streamsize __width, _CharT __fill,
48 _CharT __xplus, _CharT __xminus) {
49 if (__width <= __last - __first)
50 return copy(__first, __last, __oi);
52 streamsize __pad = __width - (__last - __first);
53 ios_base::fmtflags __dir = __flags & ios_base::adjustfield;
55 if (__dir == ios_base::left) {
56 __oi = copy(__first, __last, __oi);
57 return __fill_n(__oi, __pad, __fill);
59 else if (__dir == ios_base::internal && __first != __last &&
60 (*__first == __xplus || *__first == __xminus)) {
62 __oi = __fill_n(__oi, __pad, __fill);
63 return copy(__first, __last, __oi);
66 __oi = __fill_n(__oi, __pad, __fill);
67 return copy(__first, __last, __oi);
72 #if !defined (_STLP_NO_WCHAR_T)
73 // Helper routine for wchar_t
74 template <class _OutputIter>
75 _OutputIter _STLP_CALL
76 __put_float(__iostring &__str, _OutputIter __oi,
77 ios_base& __f, wchar_t __fill,
78 wchar_t __decimal_point, wchar_t __sep,
79 size_t __group_pos, const string& __grouping) {
80 const ctype<wchar_t>& __ct = *__STATIC_CAST(const ctype<wchar_t>*, __f._M_ctype_facet());
83 __convert_float_buffer(__str, __wbuf, __ct, __decimal_point);
85 if (!__grouping.empty()) {
86 __insert_grouping(__wbuf, __group_pos, __grouping,
87 __sep, __ct.widen('+'), __ct.widen('-'), 0);
90 return __copy_float_and_fill(__CONST_CAST(wchar_t*, __wbuf.data()),
91 __CONST_CAST(wchar_t*, __wbuf.data()) + __wbuf.size(), __oi,
92 __f.flags(), __f.width(0), __fill, __ct.widen('+'), __ct.widen('-'));
96 // Helper routine for char
97 template <class _OutputIter>
98 _OutputIter _STLP_CALL
99 __put_float(__iostring &__str, _OutputIter __oi,
100 ios_base& __f, char __fill,
101 char __decimal_point, char __sep,
102 size_t __group_pos, const string& __grouping) {
103 if ((__group_pos < __str.size()) && (__str[__group_pos] == '.')) {
104 __str[__group_pos] = __decimal_point;
107 if (!__grouping.empty()) {
108 __insert_grouping(__str, __group_pos,
109 __grouping, __sep, '+', '-', 0);
112 return __copy_float_and_fill(__CONST_CAST(char*, __str.data()),
113 __CONST_CAST(char*, __str.data()) + __str.size(), __oi,
114 __f.flags(), __f.width(0), __fill, '+', '-');
117 template <class _CharT, class _OutputIter, class _Float>
118 _OutputIter _STLP_CALL
119 __do_put_float(_OutputIter __s, ios_base& __f,
120 _CharT __fill, _Float __x) {
123 size_t __group_pos = __write_float(__buf, __f.flags(), (int)__f.precision(), __x);
125 const numpunct<_CharT>& __np = *__STATIC_CAST(const numpunct<_CharT>*, __f._M_numpunct_facet());
127 return __put_float(__buf, __s, __f, __fill,
128 __np.decimal_point(), __np.thousands_sep(),
129 __group_pos, __f._M_grouping());
132 inline void __get_money_digits_aux (__iostring &__buf, ios_base &, _STLP_LONGEST_FLOAT_TYPE __x)
133 { __get_floor_digits(__buf, __x); }
135 #if !defined (_STLP_NO_WCHAR_T)
136 inline void __get_money_digits_aux (__iowstring &__wbuf, ios_base &__f, _STLP_LONGEST_FLOAT_TYPE __x) {
138 __get_floor_digits(__buf, __x);
140 const ctype<wchar_t>& __ct = *__STATIC_CAST(const ctype<wchar_t>*, __f._M_ctype_facet());
141 __convert_float_buffer(__buf, __wbuf, __ct, wchar_t(0), false);
145 template <class _CharT>
146 void _STLP_CALL __get_money_digits(_STLP_BASIC_IOSTRING(_CharT) &__buf, ios_base& __f, _STLP_LONGEST_FLOAT_TYPE __x)
147 { __get_money_digits_aux(__buf, __f, __x); }
149 // _M_do_put_integer and its helper functions.
151 template <class _CharT, class _OutputIter>
152 _OutputIter _STLP_CALL
153 __copy_integer_and_fill(const _CharT* __buf, ptrdiff_t __len,
155 ios_base::fmtflags __flg, streamsize __wid, _CharT __fill,
156 _CharT __xplus, _CharT __xminus) {
158 return copy(__buf, __buf + __len, __oi);
160 //casting numeric_limits<ptrdiff_t>::max to streamsize only works is ptrdiff_t is signed or streamsize representation
161 //is larger than ptrdiff_t one.
162 _STLP_STATIC_ASSERT((sizeof(streamsize) > sizeof(ptrdiff_t)) ||
163 (sizeof(streamsize) == sizeof(ptrdiff_t)) && numeric_limits<ptrdiff_t>::is_signed)
164 ptrdiff_t __pad = __STATIC_CAST(ptrdiff_t, (min) (__STATIC_CAST(streamsize, (numeric_limits<ptrdiff_t>::max)()),
165 __STATIC_CAST(streamsize, __wid - __len)));
166 ios_base::fmtflags __dir = __flg & ios_base::adjustfield;
168 if (__dir == ios_base::left) {
169 __oi = copy(__buf, __buf + __len, __oi);
170 return __fill_n(__oi, __pad, __fill);
172 else if (__dir == ios_base::internal && __len != 0 &&
173 (__buf[0] == __xplus || __buf[0] == __xminus)) {
175 __oi = __fill_n(__oi, __pad, __fill);
176 return copy(__buf + 1, __buf + __len, __oi);
178 else if (__dir == ios_base::internal && __len >= 2 &&
179 (__flg & ios_base::showbase) &&
180 (__flg & ios_base::basefield) == ios_base::hex) {
183 __oi = __fill_n(__oi, __pad, __fill);
184 return copy(__buf + 2, __buf + __len, __oi);
187 __oi = __fill_n(__oi, __pad, __fill);
188 return copy(__buf, __buf + __len, __oi);
193 #if !defined (_STLP_NO_WCHAR_T)
194 // Helper function for wchar_t
195 template <class _OutputIter>
196 _OutputIter _STLP_CALL
197 __put_integer(char* __buf, char* __iend, _OutputIter __s,
199 ios_base::fmtflags __flags, wchar_t __fill) {
200 locale __loc = __f.getloc();
201 // const ctype<wchar_t>& __ct = use_facet<ctype<wchar_t> >(__loc);
202 const ctype<wchar_t>& __ct = *__STATIC_CAST(const ctype<wchar_t>*, __f._M_ctype_facet());
204 wchar_t __xplus = __ct.widen('+');
205 wchar_t __xminus = __ct.widen('-');
208 __ct.widen(__buf, __iend, __wbuf);
209 ptrdiff_t __len = __iend - __buf;
210 wchar_t* __eend = __wbuf + __len;
212 // const numpunct<wchar_t>& __np = use_facet<numpunct<wchar_t> >(__loc);
213 // const string& __grouping = __np.grouping();
215 const numpunct<wchar_t>& __np = *__STATIC_CAST(const numpunct<wchar_t>*, __f._M_numpunct_facet());
216 const string& __grouping = __f._M_grouping();
218 if (!__grouping.empty()) {
220 if (__flags & ios_base::showbase)
221 switch (__flags & ios_base::basefield) {
222 case ios_base::hex: __basechars = 2; break;
223 case ios_base::oct: __basechars = 1; break;
224 default: __basechars = 0;
229 __len = __insert_grouping(__wbuf, __eend, __grouping, __np.thousands_sep(),
230 __xplus, __xminus, __basechars);
233 return __copy_integer_and_fill((wchar_t*)__wbuf, __len, __s,
234 __flags, __f.width(0), __fill, __xplus, __xminus);
238 // Helper function for char
239 template <class _OutputIter>
240 _OutputIter _STLP_CALL
241 __put_integer(char* __buf, char* __iend, _OutputIter __s,
242 ios_base& __f, ios_base::fmtflags __flags, char __fill) {
244 ptrdiff_t __len = __iend - __buf;
246 // const numpunct<char>& __np = use_facet<numpunct<char> >(__f.getloc());
247 // const string& __grouping = __np.grouping();
249 const numpunct<char>& __np = *__STATIC_CAST(const numpunct<char>*, __f._M_numpunct_facet());
250 const string& __grouping = __f._M_grouping();
252 if (!__grouping.empty()) {
254 if (__flags & ios_base::showbase)
255 switch (__flags & ios_base::basefield) {
256 case ios_base::hex: __basechars = 2; break;
257 case ios_base::oct: __basechars = 1; break;
258 default: __basechars = 0;
263 // make sure there is room at the end of the buffer
264 // we pass to __insert_grouping
265 copy(__buf, __iend, (char *) __grpbuf);
267 __iend = __grpbuf + __len;
268 __len = __insert_grouping(__buf, __iend, __grouping, __np.thousands_sep(),
269 '+', '-', __basechars);
272 return __copy_integer_and_fill(__buf, __len, __s, __flags, __f.width(0), __fill, '+', '-');
275 #if defined (_STLP_LONG_LONG)
276 typedef _STLP_LONG_LONG __max_int_t;
277 typedef unsigned _STLP_LONG_LONG __umax_int_t;
279 typedef long __max_int_t;
280 typedef unsigned long __umax_int_t;
283 _STLP_DECLSPEC const char* _STLP_CALL __hex_char_table_lo();
284 _STLP_DECLSPEC const char* _STLP_CALL __hex_char_table_hi();
286 template <class _Integer>
287 inline char* _STLP_CALL
288 __write_decimal_backward(char* __ptr, _Integer __x, ios_base::fmtflags __flags, const __true_type& /* is_signed */) {
289 const bool __negative = __x < 0 ;
290 __max_int_t __temp = __x;
291 __umax_int_t __utemp = __negative?-__temp:__temp;
293 for (; __utemp != 0; __utemp /= 10)
294 *--__ptr = (char)((int)(__utemp % 10) + '0');
295 // put sign if needed or requested
298 else if (__flags & ios_base::showpos)
303 template <class _Integer>
304 inline char* _STLP_CALL
305 __write_decimal_backward(char* __ptr, _Integer __x, ios_base::fmtflags __flags, const __false_type& /* is_signed */) {
306 for (; __x != 0; __x /= 10)
307 *--__ptr = (char)((int)(__x % 10) + '0');
308 // put sign if requested
309 if (__flags & ios_base::showpos)
314 template <class _Integer>
316 __write_integer_backward(char* __buf, ios_base::fmtflags __flags, _Integer __x) {
321 if ((__flags & ios_base::showpos) && ((__flags & (ios_base::oct | ios_base::hex)) == 0))
323 // oct or hex base shall not be added to the 0 value (see '#' flag in C formating strings)
326 switch (__flags & ios_base::basefield) {
329 __umax_int_t __temp = __x;
330 // if the size of integer is less than 8, clear upper part
331 if ( sizeof(__x) < 8 && sizeof(__umax_int_t) >= 8 )
332 __temp &= 0xFFFFFFFF;
334 for (; __temp != 0; __temp >>=3)
335 *--__ptr = (char)((((unsigned)__temp)& 0x7) + '0');
337 // put leading '0' if showbase is set
338 if (__flags & ios_base::showbase)
344 const char* __table_ptr = (__flags & ios_base::uppercase) ?
345 __hex_char_table_hi() : __hex_char_table_lo();
346 __umax_int_t __temp = __x;
347 // if the size of integer is less than 8, clear upper part
348 if ( sizeof(__x) < 8 && sizeof(__umax_int_t) >= 8 )
349 __temp &= 0xFFFFFFFF;
351 for (; __temp != 0; __temp >>=4)
352 *--__ptr = __table_ptr[((unsigned)__temp & 0xF)];
354 if (__flags & ios_base::showbase) {
355 *--__ptr = __table_ptr[16];
360 //case ios_base::dec:
363 #if defined(__HP_aCC) && (__HP_aCC == 1)
364 bool _IsSigned = !((_Integer)-1 > 0);
366 __ptr = __write_decimal_backward(__ptr, __x, __flags, __true_type() );
368 __ptr = __write_decimal_backward(__ptr, __x, __flags, __false_type() );
370 typedef typename __bool2type<numeric_limits<_Integer>::is_signed>::_Ret _IsSigned;
371 __ptr = __write_decimal_backward(__ptr, __x, __flags, _IsSigned());
378 // return pointer to beginning of the string
382 template <class _CharT, class _OutputIter, class _Integer>
383 _OutputIter _STLP_CALL
384 __do_put_integer(_OutputIter __s, ios_base& __f, _CharT __fill, _Integer __x) {
385 // buffer size = number of bytes * number of digit necessary in the smallest Standard base (base 8, 3 digits/byte)
386 // plus the longest base representation '0x'
387 // Do not use __buf_size to define __buf static buffer, some compilers (HP aCC) do not accept const variable as
388 // the specification of a static buffer size.
389 char __buf[sizeof(_Integer) * 3 + 2];
390 const ptrdiff_t __buf_size = sizeof(__buf) / sizeof(char);
391 ios_base::fmtflags __flags = __f.flags();
392 char* __ibeg = __write_integer_backward((char*)__buf+__buf_size, __flags, __x);
393 return __put_integer(__ibeg, (char*)__buf+__buf_size, __s, __f, __flags, __fill);
396 _STLP_MOVE_TO_STD_NAMESPACE
402 #if (_STLP_STATIC_TEMPLATE_DATA > 0)
403 # if !defined(__SYMBIAN32__WSD__)
404 # if !defined (__BORLANDC__) && defined (__SYMBIAN32__) && defined(_STLP_DESIGNATED_DLL)
405 template <class _CharT, class _OutputIterator>
406 locale::id num_put<_CharT, _OutputIterator>::id;
409 # if ((defined (__CYGWIN__) || defined (__MINGW32__)) && \
410 defined (_STLP_USE_DYNAMIC_LIB) && !defined (__BUILDING_STLPORT)) || (defined (__SYMBIAN32__) && defined(_STLP_DESIGNATED_DLL))
412 * Under cygwin, when STLport is used as a shared library, the id needs
413 * to be specified as imported otherwise they will be duplicated in the
414 * calling executable.
416 # if defined(__SYMBIAN32__)
418 locale::id num_put<char, ostreambuf_iterator<char, char_traits<char> > >::id; //data should not be exported in symbian
421 _STLP_DECLSPEC locale::id num_put<char, char*>::id;
424 # if !defined (_STLP_NO_WCHAR_T)
426 locale::id num_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id;
429 _STLP_DECLSPEC locale::id num_put<wchar_t, wchar_t*>::id;
435 _STLP_DECLSPEC locale::id num_put<char, ostreambuf_iterator<char, char_traits<char> > >::id;
438 _STLP_DECLSPEC locale::id num_put<char, char*>::id;
441 # if !defined (_STLP_NO_WCHAR_T)
443 _STLP_DECLSPEC locale::id num_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id;
446 _STLP_DECLSPEC locale::id num_put<wchar_t, wchar_t*>::id;
450 # endif //__SYMBIAN32__
452 # endif /* __CYGWIN__ && _STLP_USE_DYNAMIC_LIB */
453 #endif /*__SYMBIAN32__WSD__ */
454 #else /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
456 //typedef num_put<char, char*> num_put_char;
457 typedef num_put<char, ostreambuf_iterator<char, char_traits<char> > > num_put_char_2;
459 //__DECLARE_INSTANCE(locale::id, num_put_char::id, );
460 __DECLARE_INSTANCE(locale::id, num_put_char_2::id, );
462 # if !defined (_STLP_NO_WCHAR_T)
464 //typedef num_put<wchar_t, wchar_t*> num_put_wchar_t;
465 typedef num_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > > num_put_wchar_t_2;
467 //__DECLARE_INSTANCE(locale::id, num_put_wchar_t::id, );
468 __DECLARE_INSTANCE(locale::id, num_put_wchar_t_2::id, );
472 #endif /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
476 #if !defined (_STLP_NO_BOOL)
477 template <class _CharT, class _OutputIter>
479 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f,
480 char_type __fill, bool __val) const {
481 if (!(__f.flags() & ios_base::boolalpha))
482 return this->do_put(__s, __f, __fill, __STATIC_CAST(long,__val));
484 locale __loc = __f.getloc();
485 // typedef numpunct<_CharT> _Punct;
486 // const _Punct& __np = use_facet<_Punct>(__loc);
488 const numpunct<_CharT>& __np = *__STATIC_CAST(const numpunct<_CharT>*, __f._M_numpunct_facet());
490 basic_string<_CharT> __str = __val ? __np.truename() : __np.falsename();
492 // Reuse __copy_integer_and_fill. Since internal padding makes no
493 // sense for bool, though, make sure we use something else instead.
494 // The last two argument to __copy_integer_and_fill are dummies.
495 ios_base::fmtflags __flags = __f.flags();
496 if ((__flags & ios_base::adjustfield) == ios_base::internal)
497 __flags = (__flags & ~ios_base::adjustfield) | ios_base::right;
499 return _STLP_PRIV __copy_integer_and_fill(__str.c_str(), __str.size(), __s,
500 __flags, __f.width(0), __fill,
501 (_CharT) 0, (_CharT) 0);
506 template <class _CharT, class _OutputIter>
508 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
510 { return _STLP_PRIV __do_put_integer(__s, __f, __fill, __val); }
512 template <class _CharT, class _OutputIter>
514 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
515 unsigned long __val) const
516 { return _STLP_PRIV __do_put_integer(__s, __f, __fill, __val); }
518 template <class _CharT, class _OutputIter>
520 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
522 { return _STLP_PRIV __do_put_float(__s, __f, __fill, __val); }
524 #if !defined (_STLP_NO_LONG_DOUBLE)
525 template <class _CharT, class _OutputIter>
527 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
528 long double __val) const
529 { return _STLP_PRIV __do_put_float(__s, __f, __fill, __val); }
532 #if defined (_STLP_LONG_LONG)
533 template <class _CharT, class _OutputIter>
535 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
536 _STLP_LONG_LONG __val) const
537 { return _STLP_PRIV __do_put_integer(__s, __f, __fill, __val); }
539 template <class _CharT, class _OutputIter>
541 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
542 unsigned _STLP_LONG_LONG __val) const
543 { return _STLP_PRIV __do_put_integer(__s, __f, __fill, __val); }
544 #endif /* _STLP_LONG_LONG */
547 // lib.facet.num.put.virtuals "12 For conversion from void* the specifier is %p."
548 template <class _CharT, class _OutputIter>
550 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT /*__fill*/,
551 const void* __val) const {
552 const ctype<_CharT>& __c_type = *__STATIC_CAST(const ctype<_CharT>*, __f._M_ctype_facet());
553 ios_base::fmtflags __save_flags = __f.flags();
555 __f.setf(ios_base::hex, ios_base::basefield);
556 __f.setf(ios_base::showbase);
557 __f.setf(ios_base::internal, ios_base::adjustfield);
558 __f.width((sizeof(void*) * 2) + 2); // digits in pointer type plus '0x' prefix
559 # if defined(_STLP_LONG_LONG) && !defined(__MRC__) //*ty 11/24/2001 - MrCpp can not cast from void* to long long
560 _OutputIter result = this->do_put(__s, __f, __c_type.widen('0'), __REINTERPRET_CAST(unsigned _STLP_LONG_LONG,__val));
562 _OutputIter result = this->do_put(__s, __f, __c_type.widen('0'), __REINTERPRET_CAST(unsigned long,__val));
564 __f.flags(__save_flags);
570 #endif /* _STLP_NUM_PUT_C */