📄 locale_facets.tcc
字号:
_CharT* __new, const _CharT* __cs, int& __len) const
{
// [22.2.2.2.2] Stage 3.
// If necessary, pad.
__pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs,
__w, __len, true);
__len = static_cast<int>(__w);
}
// Forwarding functions to peel signed from unsigned integer types.
template<typename _CharT>
inline int
__int_to_char(_CharT* __bufend, long __v, const _CharT* __lit,
ios_base::fmtflags __flags)
{
unsigned long __ul = static_cast<unsigned long>(__v);
bool __neg = false;
if (__v < 0)
{
__ul = -__ul;
__neg = true;
}
return __int_to_char(__bufend, __ul, __lit, __flags, __neg);
}
template<typename _CharT>
inline int
__int_to_char(_CharT* __bufend, unsigned long __v, const _CharT* __lit,
ios_base::fmtflags __flags)
{
// About showpos, see Table 60 and C99 7.19.6.1, p6 (+).
return __int_to_char(__bufend, __v, __lit,
__flags & ~ios_base::showpos, false);
}
#ifdef _GLIBCXX_USE_LONG_LONG
template<typename _CharT>
inline int
__int_to_char(_CharT* __bufend, long long __v, const _CharT* __lit,
ios_base::fmtflags __flags)
{
unsigned long long __ull = static_cast<unsigned long long>(__v);
bool __neg = false;
if (__v < 0)
{
__ull = -__ull;
__neg = true;
}
return __int_to_char(__bufend, __ull, __lit, __flags, __neg);
}
template<typename _CharT>
inline int
__int_to_char(_CharT* __bufend, unsigned long long __v,
const _CharT* __lit, ios_base::fmtflags __flags)
{ return __int_to_char(__bufend, __v, __lit,
__flags & ~ios_base::showpos, false); }
#endif
template<typename _CharT, typename _ValueT>
int
__int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
ios_base::fmtflags __flags, bool __neg)
{
// Don't write base if already 0.
const bool __showbase = (__flags & ios_base::showbase) && __v;
const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
_CharT* __buf = __bufend - 1;
if (__builtin_expect(__basefield != ios_base::oct &&
__basefield != ios_base::hex, true))
{
// Decimal.
do
{
*__buf-- = __lit[(__v % 10) + __num_base::_S_odigits];
__v /= 10;
}
while (__v != 0);
if (__neg)
*__buf-- = __lit[__num_base::_S_ominus];
else if (__flags & ios_base::showpos)
*__buf-- = __lit[__num_base::_S_oplus];
}
else if (__basefield == ios_base::oct)
{
// Octal.
do
{
*__buf-- = __lit[(__v & 0x7) + __num_base::_S_odigits];
__v >>= 3;
}
while (__v != 0);
if (__showbase)
*__buf-- = __lit[__num_base::_S_odigits];
}
else
{
// Hex.
const bool __uppercase = __flags & ios_base::uppercase;
const int __case_offset = __uppercase ? __num_base::_S_oudigits
: __num_base::_S_odigits;
do
{
*__buf-- = __lit[(__v & 0xf) + __case_offset];
__v >>= 4;
}
while (__v != 0);
if (__showbase)
{
// 'x' or 'X'
*__buf-- = __lit[__num_base::_S_ox + __uppercase];
// '0'
*__buf-- = __lit[__num_base::_S_odigits];
}
}
return __bufend - __buf - 1;
}
template<typename _CharT, typename _OutIter>
void
num_put<_CharT, _OutIter>::
_M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep,
ios_base& __io, _CharT* __new, _CharT* __cs, int& __len) const
{
// By itself __add_grouping cannot deal correctly with __cs when
// ios::showbase is set and ios_base::oct || ios_base::hex.
// Therefore we take care "by hand" of the initial 0, 0x or 0X.
// However, remember that the latter do not occur if the number
// printed is '0' (__len == 1).
streamsize __off = 0;
const ios_base::fmtflags __basefield = __io.flags()
& ios_base::basefield;
if ((__io.flags() & ios_base::showbase) && __len > 1)
if (__basefield == ios_base::oct)
{
__off = 1;
__new[0] = __cs[0];
}
else if (__basefield == ios_base::hex)
{
__off = 2;
__new[0] = __cs[0];
__new[1] = __cs[1];
}
_CharT* __p;
__p = std::__add_grouping(__new + __off, __sep, __grouping,
__grouping_size, __cs + __off,
__cs + __len);
__len = __p - __new;
}
template<typename _CharT, typename _OutIter>
template<typename _ValueT>
_OutIter
num_put<_CharT, _OutIter>::
_M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill,
_ValueT __v) const
{
typedef typename numpunct<_CharT>::__cache_type __cache_type;
__use_cache<__cache_type> __uc;
const locale& __loc = __io._M_getloc();
const __cache_type* __lc = __uc(__loc);
const _CharT* __lit = __lc->_M_atoms_out;
// Long enough to hold hex, dec, and octal representations.
const int __ilen = 4 * sizeof(_ValueT);
_CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
* __ilen));
// [22.2.2.2.2] Stage 1, numeric conversion to character.
// Result is returned right-justified in the buffer.
int __len;
__len = __int_to_char(__cs + __ilen, __v, __lit, __io.flags());
__cs += __ilen - __len;
// Add grouping, if necessary.
if (__lc->_M_use_grouping)
{
// Grouping can add (almost) as many separators as the
// number of digits, but no more.
_CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
* __len * 2));
_M_group_int(__lc->_M_grouping, __lc->_M_grouping_size,
__lc->_M_thousands_sep, __io, __cs2, __cs, __len);
__cs = __cs2;
}
// Pad.
const streamsize __w = __io.width();
if (__w > static_cast<streamsize>(__len))
{
_CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
* __w));
_M_pad(__fill, __w, __io, __cs3, __cs, __len);
__cs = __cs3;
}
__io.width(0);
// [22.2.2.2.2] Stage 4.
// Write resulting, fully-formatted string to output iterator.
return std::__write(__s, __cs, __len);
}
template<typename _CharT, typename _OutIter>
void
num_put<_CharT, _OutIter>::
_M_group_float(const char* __grouping, size_t __grouping_size,
_CharT __sep, const _CharT* __p, _CharT* __new,
_CharT* __cs, int& __len) const
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 282. What types does numpunct grouping refer to?
// Add grouping, if necessary.
_CharT* __p2;
const int __declen = __p ? __p - __cs : __len;
__p2 = std::__add_grouping(__new, __sep, __grouping, __grouping_size,
__cs, __cs + __declen);
// Tack on decimal part.
int __newlen = __p2 - __new;
if (__p)
{
char_traits<_CharT>::copy(__p2, __p, __len - __declen);
__newlen += __len - __declen;
}
__len = __newlen;
}
// The following code uses snprintf (or sprintf(), when
// _GLIBCXX_USE_C99 is not defined) to convert floating point values
// for insertion into a stream. An optimization would be to replace
// them with code that works directly on a wide buffer and then use
// __pad to do the padding. It would be good to replace them anyway
// to gain back the efficiency that C++ provides by knowing up front
// the type of the values to insert. Also, sprintf is dangerous
// since may lead to accidental buffer overruns. This
// implementation follows the C++ standard fairly directly as
// outlined in 22.2.2.2 [lib.locale.num.put]
template<typename _CharT, typename _OutIter>
template<typename _ValueT>
_OutIter
num_put<_CharT, _OutIter>::
_M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
_ValueT __v) const
{
typedef typename numpunct<_CharT>::__cache_type __cache_type;
__use_cache<__cache_type> __uc;
const locale& __loc = __io._M_getloc();
const __cache_type* __lc = __uc(__loc);
// Use default precision if out of range.
streamsize __prec = __io.precision();
if (__prec < static_cast<streamsize>(0))
__prec = static_cast<streamsize>(6);
const int __max_digits = numeric_limits<_ValueT>::digits10;
// [22.2.2.2.2] Stage 1, numeric conversion to character.
int __len;
// Long enough for the max format spec.
char __fbuf[16];
#ifdef _GLIBCXX_USE_C99
// First try a buffer perhaps big enough (most probably sufficient
// for non-ios_base::fixed outputs)
int __cs_size = __max_digits * 3;
char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
__num_base::_S_format_float(__io, __fbuf, __mod);
__len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
_S_get_c_locale(), __prec);
// If the buffer was not large enough, try again with the correct size.
if (__len >= __cs_size)
{
__cs_size = __len + 1;
__cs = static_cast<char*>(__builtin_alloca(__cs_size));
__len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
_S_get_c_locale(), __prec);
}
#else
// Consider the possibility of long ios_base::fixed outputs
const bool __fixed = __io.flags() & ios_base::fixed;
const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
// The size of the output string is computed as follows.
// ios_base::fixed outputs may need up to __max_exp + 1 chars
// for the integer part + __prec chars for the fractional part
// + 3 chars for sign, decimal point, '\0'. On the other hand,
// for non-fixed outputs __max_digits * 2 + __prec chars are
// largely sufficient.
const int __cs_size = __fixed ? __max_exp + __prec + 4
: __max_digits * 2 + __prec;
char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
__num_base::_S_format_float(__io, __fbuf, __mod);
__len = std::__convert_from_v(__cs, 0, __fbuf, __v,
_S_get_c_locale(), __prec);
#endif
// [22.2.2.2.2] Stage 2, convert to char_type, using correct
// numpunct.decimal_point() values for '.' and adding grouping.
const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
_CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
* __len));
__ctype.widen(__cs, __cs + __len, __ws);
// Replace decimal point.
const _CharT __cdec = __ctype.widen('.');
const _CharT __dec = __lc->_M_decimal_point;
const _CharT* __p = char_traits<_CharT>::find(__ws, __len, __cdec);
if (__p)
__ws[__p - __ws] = __dec;
// Add grouping, if necessary.
if (__lc->_M_use_grouping)
{
// Grouping can add (almost) as many separators as the
// number of digits, but no more.
_CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
* __len * 2));
_M_group_float(__lc->_M_grouping, __lc->_M_grouping_size,
__lc->_M_thousands_sep, __p, __ws2, __ws, __len);
__ws = __ws2;
}
// Pad.
const streamsize __w = __io.width();
if (__w > static_cast<streamsize>(__len))
{
_CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
* __w));
_M_pad(__fill, __w, __io, __ws3, __ws, __len);
__ws = __ws3;
}
__io.width(0);
// [22.2.2.2.2] Stage 4.
// Write resulting, fully-formatted string to output iterator.
return std::__write(__s, __ws, __len);
}
template<typename _CharT, typename _OutIter>
_OutIter
num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
{
const ios_base::fmtflags __flags = __io.flags();
if ((__flags & ios_base::boolalpha) == 0)
{
const long __l = __v;
__s = _M_insert_int(__s, __io, __fill, __l);
}
else
{
typedef typename numpunct<_CharT>::__cache_type __cache_type;
__use_cache<__cache_type> __uc;
const locale& __loc = __io._M_getloc();
const __cache_type* __lc = __uc(__loc);
const _CharT* __name = __v ? __lc->_M_truename
: __lc->_M_falsename;
int __len = __v ? __lc->_M_truename_size
: __lc->_M_falsename_size;
const streamsize __w = __io.width();
if (__w > static_cast<streamsize>(__len))
{
_CharT* __cs
= static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
* __w));
_M_pad(__fill, __w, __io, __cs, __name, __len);
__name = __cs;
}
__io.width(0);
__s = std::__write(__s, __name, __len);
}
return __s;
}
template<typename _CharT, typename _OutIter>
_OutIter
num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
{ return _M_insert_int(__s, __io, __fill, __v); }
template<typename _CharT, typename _OutIter>
_OutIter
num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __io, char_type __fill,
unsigned long __v) const
{ return _M_insert_int(__s, __io, __fill, __v); }
#ifdef _GLIBCXX_USE_LONG_LONG
template<typename _CharT, typename _OutIter>
_OutIter
num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
{ return _M_insert_int(__s, __b, __fill, __v); }
template<typename _CharT, typename _OutIter>
_OutIter
num_put<_CharT, _OutIter>::
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -