Home | History | Annotate | Download | only in stl
      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 _STLP_STD::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 = _STLP_STD::copy(__first, __last, __oi);
     55       return _STLP_PRIV __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 = _STLP_PRIV __fill_n(__oi, __pad, __fill);
     61       return _STLP_STD::copy(__first, __last, __oi);
     62     }
     63     else {
     64       __oi = _STLP_PRIV __fill_n(__oi, __pad, __fill);
     65       return _STLP_STD::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 = use_facet<ctype<wchar_t> >(__f.getloc());
     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(__wbuf.data(), __wbuf.data() + __wbuf.size(), __oi,
     89                                __f.flags(), __f.width(0), __fill, __ct.widen('+'), __ct.widen('-'));
     90 }
     91 #endif /* WCHAR_T */
     92 
     93 // Helper routine for char
     94 template <class _OutputIter>
     95 _OutputIter  _STLP_CALL
     96 __put_float(__iostring &__str, _OutputIter __oi,
     97             ios_base& __f, char __fill,
     98             char __decimal_point, char __sep,
     99             size_t __group_pos, const string& __grouping) {
    100   if ((__group_pos < __str.size()) && (__str[__group_pos] == '.')) {
    101     __str[__group_pos] = __decimal_point;
    102   }
    103 
    104   if (!__grouping.empty()) {
    105     __insert_grouping(__str, __group_pos,
    106                       __grouping, __sep, '+', '-', 0);
    107   }
    108 
    109   return __copy_float_and_fill(__str.data(), __str.data() + __str.size(), __oi,
    110                                __f.flags(), __f.width(0), __fill, '+', '-');
    111 }
    112 
    113 template <class _CharT, class _OutputIter, class _Float>
    114 _OutputIter _STLP_CALL
    115 __do_put_float(_OutputIter __s, ios_base& __f,
    116                 _CharT __fill, _Float __x) {
    117   __iostring __buf;
    118 
    119   size_t __group_pos = __write_float(__buf, __f.flags(), (int)__f.precision(), __x);
    120 
    121   const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__f.getloc());
    122   return __put_float(__buf, __s, __f, __fill,
    123                      __np.decimal_point(), __np.thousands_sep(),
    124                      __group_pos, __np.grouping());
    125 }
    126 
    127 inline void __get_money_digits_aux (__iostring &__buf, ios_base &, _STLP_LONGEST_FLOAT_TYPE __x)
    128 { __get_floor_digits(__buf, __x); }
    129 
    130 #if !defined (_STLP_NO_WCHAR_T)
    131 inline void __get_money_digits_aux (__iowstring &__wbuf, ios_base &__f, _STLP_LONGEST_FLOAT_TYPE __x) {
    132   __iostring __buf;
    133   __get_floor_digits(__buf, __x);
    134 
    135   const ctype<wchar_t>& __ct = use_facet<ctype<wchar_t> >(__f.getloc());
    136   __convert_float_buffer(__buf, __wbuf, __ct, wchar_t(0), false);
    137 }
    138 #endif
    139 
    140 template <class _CharT>
    141 void _STLP_CALL __get_money_digits(_STLP_BASIC_IOSTRING(_CharT) &__buf, ios_base& __f, _STLP_LONGEST_FLOAT_TYPE __x)
    142 { __get_money_digits_aux(__buf, __f, __x); }
    143 
    144 // _M_do_put_integer and its helper functions.
    145 
    146 template <class _CharT, class _OutputIter>
    147 _OutputIter _STLP_CALL
    148 __copy_integer_and_fill(const _CharT* __buf, ptrdiff_t __len,
    149                         _OutputIter __oi,
    150                         ios_base::fmtflags __flg, streamsize __wid, _CharT __fill,
    151                         _CharT __xplus, _CharT __xminus) {
    152   if (__len >= __wid)
    153     return _STLP_STD::copy(__buf, __buf + __len, __oi);
    154   else {
    155     //casting numeric_limits<ptrdiff_t>::max to streamsize only works is ptrdiff_t is signed or streamsize representation
    156     //is larger than ptrdiff_t one.
    157     _STLP_STATIC_ASSERT((sizeof(streamsize) > sizeof(ptrdiff_t)) ||
    158                         ((sizeof(streamsize) == sizeof(ptrdiff_t)) && numeric_limits<ptrdiff_t>::is_signed))
    159     ptrdiff_t __pad = __STATIC_CAST(ptrdiff_t, (min) (__STATIC_CAST(streamsize, (numeric_limits<ptrdiff_t>::max)()),
    160                                                       __STATIC_CAST(streamsize, __wid - __len)));
    161     ios_base::fmtflags __dir = __flg & ios_base::adjustfield;
    162 
    163     if (__dir == ios_base::left) {
    164       __oi = _STLP_STD::copy(__buf, __buf + __len, __oi);
    165       return _STLP_PRIV __fill_n(__oi, __pad, __fill);
    166     }
    167     else if (__dir == ios_base::internal && __len != 0 &&
    168              (__buf[0] == __xplus || __buf[0] == __xminus)) {
    169       *__oi++ = __buf[0];
    170       __oi = __fill_n(__oi, __pad, __fill);
    171       return _STLP_STD::copy(__buf + 1, __buf + __len, __oi);
    172     }
    173     else if (__dir == ios_base::internal && __len >= 2 &&
    174              (__flg & ios_base::showbase) &&
    175              (__flg & ios_base::basefield) == ios_base::hex) {
    176       *__oi++ = __buf[0];
    177       *__oi++ = __buf[1];
    178       __oi = __fill_n(__oi, __pad, __fill);
    179       return _STLP_STD::copy(__buf + 2, __buf + __len, __oi);
    180     }
    181     else {
    182       __oi = __fill_n(__oi, __pad, __fill);
    183       return _STLP_STD::copy(__buf, __buf + __len, __oi);
    184     }
    185   }
    186 }
    187 
    188 #if !defined (_STLP_NO_WCHAR_T)
    189 // Helper function for wchar_t
    190 template <class _OutputIter>
    191 _OutputIter _STLP_CALL
    192 __put_integer(char* __buf, char* __iend, _OutputIter __s,
    193               ios_base& __f,
    194               ios_base::fmtflags __flags, wchar_t __fill) {
    195   locale __loc = __f.getloc();
    196   const ctype<wchar_t>& __ct = use_facet<ctype<wchar_t> >(__loc);
    197 
    198   wchar_t __xplus  = __ct.widen('+');
    199   wchar_t __xminus = __ct.widen('-');
    200 
    201   wchar_t __wbuf[64];
    202   __ct.widen(__buf, __iend, __wbuf);
    203   ptrdiff_t __len = __iend - __buf;
    204   wchar_t* __eend = __wbuf + __len;
    205 
    206   const numpunct<wchar_t>& __np = use_facet<numpunct<wchar_t> >(__loc);
    207   const string& __grouping = __np.grouping();
    208 
    209   if (!__grouping.empty()) {
    210     int __basechars;
    211     if (__flags & ios_base::showbase)
    212       switch (__flags & ios_base::basefield) {
    213         case ios_base::hex: __basechars = 2; break;
    214         case ios_base::oct: __basechars = 1; break;
    215         default: __basechars = 0;
    216       }
    217     else
    218       __basechars = 0;
    219 
    220     __len = __insert_grouping(__wbuf, __eend, __grouping, __np.thousands_sep(),
    221                               __xplus, __xminus, __basechars);
    222   }
    223 
    224   return __copy_integer_and_fill((wchar_t*)__wbuf, __len, __s,
    225                                  __flags, __f.width(0), __fill, __xplus, __xminus);
    226 }
    227 #endif
    228 
    229 // Helper function for char
    230 template <class _OutputIter>
    231 _OutputIter _STLP_CALL
    232 __put_integer(char* __buf, char* __iend, _OutputIter __s,
    233               ios_base& __f, ios_base::fmtflags __flags, char __fill) {
    234   char __grpbuf[64];
    235   ptrdiff_t __len = __iend - __buf;
    236 
    237   const numpunct<char>& __np = use_facet<numpunct<char> >(__f.getloc());
    238   const string& __grouping = __np.grouping();
    239 
    240   if (!__grouping.empty()) {
    241     int __basechars;
    242     if (__flags & ios_base::showbase)
    243       switch (__flags & ios_base::basefield) {
    244         case ios_base::hex: __basechars = 2; break;
    245         case ios_base::oct: __basechars = 1; break;
    246         default: __basechars = 0;
    247       }
    248     else
    249       __basechars = 0;
    250 
    251      // make sure there is room at the end of the buffer
    252      // we pass to __insert_grouping
    253     _STLP_STD::copy(__buf, __iend, (char *) __grpbuf);
    254     __buf = __grpbuf;
    255     __iend = __grpbuf + __len;
    256     __len = __insert_grouping(__buf, __iend, __grouping, __np.thousands_sep(),
    257                               '+', '-', __basechars);
    258   }
    259 
    260   return __copy_integer_and_fill(__buf, __len, __s, __flags, __f.width(0), __fill, '+', '-');
    261 }
    262 
    263 #if defined (_STLP_LONG_LONG)
    264 typedef _STLP_LONG_LONG __max_int_t;
    265 typedef unsigned _STLP_LONG_LONG __umax_int_t;
    266 #else
    267 typedef long __max_int_t;
    268 typedef unsigned long __umax_int_t;
    269 #endif
    270 
    271 _STLP_DECLSPEC const char* _STLP_CALL __hex_char_table_lo();
    272 _STLP_DECLSPEC const char* _STLP_CALL __hex_char_table_hi();
    273 
    274 template <class _Integer>
    275 inline char* _STLP_CALL
    276 __write_decimal_backward(char* __ptr, _Integer __x, ios_base::fmtflags __flags, const __true_type& /* is_signed */) {
    277   const bool __negative = __x < 0 ;
    278   __max_int_t __temp = __x;
    279   __umax_int_t __utemp = __negative?-__temp:__temp;
    280 
    281   for (; __utemp != 0; __utemp /= 10)
    282     *--__ptr = (char)((int)(__utemp % 10) + '0');
    283   // put sign if needed or requested
    284   if (__negative)
    285     *--__ptr = '-';
    286   else if (__flags & ios_base::showpos)
    287     *--__ptr = '+';
    288   return __ptr;
    289 }
    290 
    291 template <class _Integer>
    292 inline char* _STLP_CALL
    293 __write_decimal_backward(char* __ptr, _Integer __x, ios_base::fmtflags __flags, const __false_type& /* is_signed */) {
    294   for (; __x != 0; __x /= 10)
    295     *--__ptr = (char)((int)(__x % 10) + '0');
    296   // put sign if requested
    297   if (__flags & ios_base::showpos)
    298     *--__ptr = '+';
    299   return __ptr;
    300 }
    301 
    302 template <class _Integer>
    303 char* _STLP_CALL
    304 __write_integer_backward(char* __buf, ios_base::fmtflags __flags, _Integer __x) {
    305   char* __ptr = __buf;
    306 
    307   if (__x == 0) {
    308     *--__ptr = '0';
    309     if ((__flags & ios_base::showpos) && ((__flags & (ios_base::oct | ios_base::hex)) == 0))
    310       *--__ptr = '+';
    311     // oct or hex base shall not be added to the 0 value (see '#' flag in C formating strings)
    312   }
    313   else {
    314     switch (__flags & ios_base::basefield) {
    315       case ios_base::oct:
    316         {
    317           __umax_int_t __temp = __x;
    318           // if the size of integer is less than 8, clear upper part
    319           if ( sizeof(__x) < 8  && sizeof(__umax_int_t) >= 8 )
    320             __temp &= 0xFFFFFFFF;
    321 
    322           for (; __temp != 0; __temp >>=3)
    323             *--__ptr = (char)((((unsigned)__temp)& 0x7) + '0');
    324 
    325           // put leading '0' if showbase is set
    326           if (__flags & ios_base::showbase)
    327             *--__ptr = '0';
    328         }
    329         break;
    330       case ios_base::hex:
    331         {
    332           const char* __table_ptr = (__flags & ios_base::uppercase) ?
    333             __hex_char_table_hi() : __hex_char_table_lo();
    334           __umax_int_t __temp = __x;
    335           // if the size of integer is less than 8, clear upper part
    336           if ( sizeof(__x) < 8  && sizeof(__umax_int_t) >= 8 )
    337             __temp &= 0xFFFFFFFF;
    338 
    339           for (; __temp != 0; __temp >>=4)
    340             *--__ptr = __table_ptr[((unsigned)__temp & 0xF)];
    341 
    342           if (__flags & ios_base::showbase) {
    343             *--__ptr = __table_ptr[16];
    344             *--__ptr = '0';
    345           }
    346         }
    347         break;
    348       //case ios_base::dec:
    349       default:
    350         {
    351 #if defined(__HP_aCC) && (__HP_aCC == 1)
    352           bool _IsSigned = !((_Integer)-1 > 0);
    353           if (_IsSigned)
    354             __ptr = __write_decimal_backward(__ptr, __x, __flags, __true_type() );
    355           else
    356             __ptr = __write_decimal_backward(__ptr, __x, __flags, __false_type() );
    357 #else
    358           typedef typename __bool2type<numeric_limits<_Integer>::is_signed>::_Ret _IsSigned;
    359           __ptr = __write_decimal_backward(__ptr, __x, __flags, _IsSigned());
    360 #endif
    361         }
    362         break;
    363     }
    364   }
    365 
    366   // return pointer to beginning of the string
    367   return __ptr;
    368 }
    369 
    370 template <class _CharT, class _OutputIter, class _Integer>
    371 _OutputIter _STLP_CALL
    372 __do_put_integer(_OutputIter __s, ios_base& __f, _CharT __fill, _Integer __x) {
    373   // buffer size = number of bytes * number of digit necessary in the smallest Standard base (base 8, 3 digits/byte)
    374   //               plus the longest base representation '0x'
    375   // Do not use __buf_size to define __buf static buffer, some compilers (HP aCC) do not accept const variable as
    376   // the specification of a static buffer size.
    377   char __buf[sizeof(_Integer) * 3 + 2];
    378   const ptrdiff_t __buf_size = sizeof(__buf) / sizeof(char);
    379   ios_base::fmtflags __flags = __f.flags();
    380   char* __ibeg = __write_integer_backward((char*)__buf + __buf_size, __flags, __x);
    381   return __put_integer(__ibeg, (char*)__buf + __buf_size, __s, __f, __flags, __fill);
    382 }
    383 
    384 template <class _CharT, class _OutputIter>
    385 _OutputIter _STLP_CALL
    386 __do_put_bool(_OutputIter __s, ios_base& __f, _CharT __fill, bool __x) {
    387   const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__f.getloc());
    388 
    389   basic_string<_CharT, char_traits<_CharT>, allocator<_CharT> > __str = __x ? __np.truename() : __np.falsename();
    390 
    391   streamsize __wid = __f.width(0);
    392   if (__str.size() >= __STATIC_CAST(size_t, __wid))
    393     return _STLP_STD::copy(__str.begin(), __str.end(), __s);
    394   else {
    395     streamsize __pad = __wid - __str.size();
    396     ios_base::fmtflags __dir = __f.flags() & ios_base::adjustfield;
    397 
    398     if (__dir == ios_base::left) {
    399       __s = _STLP_STD::copy(__str.begin(), __str.end(), __s);
    400       return __fill_n(__s, __pad, __fill);
    401     }
    402     else /* covers right and internal padding */ {
    403       __s = __fill_n(__s, __pad, __fill);
    404       return _STLP_STD::copy(__str.begin(), __str.end(), __s);
    405     }
    406   }
    407 }
    408 _STLP_MOVE_TO_STD_NAMESPACE
    409 
    410 //
    411 // num_put<>
    412 //
    413 
    414 template <class _CharT, class _OutputIterator>
    415 locale::id num_put<_CharT, _OutputIterator>::id;
    416 
    417 #if !defined (_STLP_NO_BOOL)
    418 template <class _CharT, class _OutputIter>
    419 _OutputIter
    420 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
    421                                      bool __val) const {
    422   if (!(__f.flags() & ios_base::boolalpha))
    423     // 22.2.2.2.2.23: shall return do_put for int and not directly __do_put_integer.
    424     return do_put(__s, __f, __fill, __STATIC_CAST(long, __val));
    425 
    426   return _STLP_PRIV __do_put_bool(__s, __f, __fill, __val);
    427 }
    428 #endif
    429 
    430 template <class _CharT, class _OutputIter>
    431 _OutputIter
    432 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
    433                                      long __val) const
    434 { return _STLP_PRIV __do_put_integer(__s, __f, __fill, __val); }
    435 
    436 template <class _CharT, class _OutputIter>
    437 _OutputIter
    438 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
    439                                      unsigned long __val) const
    440 { return _STLP_PRIV __do_put_integer(__s, __f, __fill, __val); }
    441 
    442 template <class _CharT, class _OutputIter>
    443 _OutputIter
    444 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
    445                                      double __val) const
    446 { return _STLP_PRIV __do_put_float(__s, __f, __fill, __val); }
    447 
    448 #if !defined (_STLP_NO_LONG_DOUBLE)
    449 template <class _CharT, class _OutputIter>
    450 _OutputIter
    451 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
    452                                      long double __val) const
    453 { return _STLP_PRIV __do_put_float(__s, __f, __fill, __val); }
    454 #endif
    455 
    456 #if defined (_STLP_LONG_LONG)
    457 template <class _CharT, class _OutputIter>
    458 _OutputIter
    459 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
    460                                      _STLP_LONG_LONG __val) const
    461 { return _STLP_PRIV __do_put_integer(__s, __f, __fill, __val); }
    462 
    463 template <class _CharT, class _OutputIter>
    464 _OutputIter
    465 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill,
    466                                      unsigned _STLP_LONG_LONG __val) const
    467 { return _STLP_PRIV __do_put_integer(__s, __f, __fill, __val); }
    468 #endif /* _STLP_LONG_LONG */
    469 
    470 
    471 // 22.2.2.2.2 Stage 1: "For conversion from void* the specifier is %p."
    472 // This is not clear and I'm really don't follow this (below).
    473 template <class _CharT, class _OutputIter>
    474 _OutputIter
    475 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT /*__fill*/,
    476                                      const void* __val) const {
    477   const ctype<_CharT>& __c_type = use_facet<ctype<_CharT> >(__f.getloc());
    478   ios_base::fmtflags __save_flags = __f.flags();
    479 
    480   __f.setf(ios_base::hex, ios_base::basefield);
    481   __f.setf(ios_base::showbase);
    482   __f.setf(ios_base::internal, ios_base::adjustfield);
    483   __f.width((sizeof(void*) * 2) + 2); // digits in pointer type plus '0x' prefix
    484   if ( __val == 0 ) {
    485     // base ('0x') not shown for null, but I really want to type it
    486     // for pointer. Print it first in this case.
    487     const char* __table_ptr = (__save_flags & ios_base::uppercase) ?
    488             _STLP_PRIV __hex_char_table_hi() : _STLP_PRIV __hex_char_table_lo();
    489     __s++ = __c_type.widen( '0' );
    490     __s++ = __c_type.widen( __table_ptr[16] );
    491     __f.width((sizeof(void*) * 2)); // digits in pointer type
    492   } else {
    493     __f.width((sizeof(void*) * 2) + 2); // digits in pointer type plus '0x' prefix
    494   }
    495 #if defined (_STLP_MSVC)
    496 #  pragma warning (push)
    497 #  pragma warning (disable : 4311) //pointer truncation from 'const void*' to 'unsigned long'
    498 #endif
    499   _OutputIter result =
    500 #ifdef _STLP_LONG_LONG
    501     ( sizeof(void*) == sizeof(unsigned long) ) ?
    502 #endif
    503     _STLP_PRIV __do_put_integer(__s, __f, __c_type.widen('0'), __REINTERPRET_CAST(unsigned long,__val))
    504 #ifdef _STLP_LONG_LONG
    505       : /* ( sizeof(void*) == sizeof(unsigned _STLP_LONG_LONG) ) ? */
    506     _STLP_PRIV __do_put_integer(__s, __f, __c_type.widen('0'), __REINTERPRET_CAST(unsigned _STLP_LONG_LONG,__val))
    507 #endif
    508         ;
    509 #if defined (_STLP_MSVC)
    510 #  pragma warning (pop)
    511 #endif
    512   __f.flags(__save_flags);
    513   return result;
    514 }
    515 
    516 _STLP_END_NAMESPACE
    517 
    518 #endif /* _STLP_NUM_PUT_C */
    519 
    520 // Local Variables:
    521 // mode:C++
    522 // End:
    523