| /*************************************************************************** |
| * |
| * _num_put.cc - definition of std::num_put members |
| * |
| * $Id$ |
| * |
| *************************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed |
| * with this work for additional information regarding copyright |
| * ownership. The ASF licenses this file to you under the Apache |
| * License, Version 2.0 (the "License"); you may not use this file |
| * except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| * implied. See the License for the specific language governing |
| * permissions and limitations under the License. |
| * |
| * Copyright 2001-2006 Rogue Wave Software. |
| * |
| **************************************************************************/ |
| |
| #include <loc/_locale.h> // for use_facet |
| #include <loc/_ctype.h> // for ctype |
| |
| _RWSTD_NAMESPACE (__rw) { |
| |
| _RWSTD_EXPORT _RWSTD_SIZE_T |
| __rw_put_num (char**, _RWSTD_SIZE_T, unsigned, int, _RWSTD_STREAMSIZE, |
| const void*, const char*); |
| |
| _RWSTD_EXPORT extern const unsigned char |
| __rw_digit_map[]; |
| |
| |
| template <class _OutputIter> |
| inline bool |
| __rw_iter_failed (const _OutputIter&) { return false; } |
| |
| // const commented to resolve ambiguity on MSVC 7.0: |
| // error C2667: '__rw_iter_failed' : none of 2 overloads have a best conversion |
| template <class _CharT, class _Traits> |
| inline bool |
| __rw_iter_failed (/*const */_STD::ostreambuf_iterator<_CharT, _Traits> &__it) |
| { |
| return __it.failed (); |
| } |
| |
| } // namespace __rw |
| |
| |
| _RWSTD_NAMESPACE (std) { |
| |
| |
| template <class _CharT, class _OutputIter> |
| _RW::__rw_facet_id num_put<_CharT, _OutputIter>::id; |
| |
| |
| template <class _CharT, class _OutputIter /* = ostreambuf_iterator<_CharT> */> |
| /* virtual */ num_put<_CharT, _OutputIter>::~num_put () |
| { |
| // no-op |
| } |
| |
| |
| template <class _CharT, class _OutputIter /* = ostreambuf_iterator<_CharT> */> |
| typename num_put<_CharT, _OutputIter>::iter_type |
| num_put<_CharT, _OutputIter>:: |
| _C_put (iter_type __it, ios_base &__flags, char_type __fill, int __type, |
| const void *__pval) const |
| { |
| const numpunct<char_type> &__np = |
| _RWSTD_USE_FACET (numpunct<char_type>, __flags.getloc ()); |
| |
| char __buf [_RWSTD_DBL_MAX_10_EXP]; |
| |
| // will grow as necessary and may need to be deleted |
| char *__pbuf = __buf; |
| |
| const string __grouping = __np.grouping (); |
| const char* const __grp = __grouping.c_str (); |
| const _RWSTD_STREAMSIZE __prec = __flags.precision (); |
| |
| const int __f = __flags.flags (); |
| |
| // format value, ignore C++ decimal_point and thousands_sep |
| _RWSTD_SIZE_T __res = |
| _RW::__rw_put_num (&__pbuf, sizeof __buf, __f, __type, |
| __prec, __pval, __grp); |
| |
| // for bool values and boolalpha bit set, retrieve the "truth" string |
| basic_string<char_type, char_traits<char_type>, allocator<char_type> > |
| __boolstr; |
| |
| if (!__res) { |
| // avoid an IBM VAC++ 7.0 code generation bug that causes |
| // local string objects to get incorrectly destroyed (see |
| // bug #546) |
| // __boolstr = __pval ? __np.truename () : __np.falsename (); |
| |
| if (__pval) |
| __boolstr = __np.truename (); |
| else |
| __boolstr = __np.falsename (); |
| |
| __res = __boolstr.size (); |
| } |
| |
| // number of fill chars to pad with |
| streamsize __pad = __flags.width () - streamsize (__res); |
| |
| #ifdef _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE |
| |
| // unconditionally reset width before inserting anything |
| // in case the insertion causes an exception to be thrown |
| __flags.width (0); |
| |
| #endif // _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE |
| |
| // adjustfield bits (left, internal, or the default right) |
| const int __adj = __f & _RWSTD_IOS_ADJUSTFIELD; |
| |
| if (__pad > 0 && !(__adj & (_RWSTD_IOS_LEFT | _RWSTD_IOS_INTERNAL))) { |
| |
| // right justify if either no justification or |
| // right justification specified in adjustfield |
| |
| for (; __pad--; ++__it) |
| *__it = __fill; |
| } |
| |
| const ctype<char_type> &__ctp = |
| _RWSTD_USE_FACET (ctype<char_type>, __flags.getloc ()); |
| |
| const char *__p = __pbuf; |
| |
| if (__pad > 0 && _RWSTD_IOS_INTERNAL == __adj) { |
| |
| typedef unsigned char _UChar; |
| |
| // internal padding only between the leading "0x" |
| // prefix or the leading sign and the number |
| |
| if (43 /* '+' or '-' */ == _RW::__rw_digit_map [_UChar (*__p)]) |
| *__it++ = __ctp.widen (*__p++); |
| else if ( '0' == *__p && __res > 2 |
| && 33 == /* 'X' */ _RW::__rw_digit_map [_UChar (__p [1])]) { |
| *__it++ = __ctp.widen (*__p++); |
| *__it++ = __ctp.widen (*__p++); |
| } |
| |
| // right justify if not internally padded |
| for (; __pad--; ++__it) |
| *__it = __fill; |
| } |
| |
| if (__type & _RW::__rw_facet::_C_integral && !*__grp && __prec >= 0) { |
| // optimized for integer output, no grouping |
| for (const char *__end = __pbuf + __res; __p != __end; ++__p, ++__it) |
| *__it = __ctp.widen (*__p); |
| } |
| else if (_RW::__rw_facet::_C_bool == __type) { |
| // boolalpha output |
| for (_RWSTD_SIZE_T __i = 0; __i != __res; ++__i, ++__it) |
| *__it = __boolstr [__i]; |
| } |
| else { |
| // all other numeric output |
| for (const char *__end = __pbuf + __res; __p != __end; ++__p, ++__it) { |
| switch (*__p) { |
| // replace either the period or the comma with the |
| // decimal point in case a setlocale() call made by |
| // the program changed the default '.' to ',' |
| case '.': |
| case ',': *__it = __np.decimal_point (); break; |
| case ';': *__it = __np.thousands_sep (); break; |
| default: *__it = __ctp.widen (*__p); break; |
| } |
| } |
| } |
| |
| // delete if the buffer was dynamically allocated |
| if (__pbuf != __buf) |
| delete[] __pbuf; |
| |
| // left justify if necessary |
| for (; __pad > 0; ++__it, --__pad) |
| *__it = __fill; |
| |
| #ifndef _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE |
| |
| // reset width only if the insertion has been successful |
| // (i.e., no exception and the iterator has not failed) |
| if (!_RW::__rw_iter_failed (__it)) |
| __flags.width (0); |
| |
| #endif // _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE |
| |
| return __it; |
| } |
| |
| |
| } // namespace std |