210 lines
6.6 KiB
C++
210 lines
6.6 KiB
C++
/***************************************************************************
|
|
*
|
|
* _num_put.cc - definition of std::num_put members
|
|
*
|
|
* $Id: _num_put.cc 597438 2007-11-22 15:44:53Z faridz $
|
|
*
|
|
***************************************************************************
|
|
*
|
|
* 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
|