📄 locale_facets.tcc
字号:
_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 __write(__s, __cs, __len); } template<typename _CharT, typename _OutIter> void num_put<_CharT, _OutIter>:: _M_group_float(const string& __grouping, _CharT __sep, const _CharT* __p, _CharT* __new, _CharT* __cs, int& __len) const {#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS //282. What types does numpunct grouping refer to? // Add grouping, if necessary. _CharT* __p2; int __declen = __p ? __p - __cs : __len; __p2 = __add_grouping(__new, __sep, __grouping.c_str(), __grouping.c_str() + __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;#endif } // The following code uses snprintf (or sprintf(), when // _GLIBCPP_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_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, _ValueT __v) const { // Note: digits10 is rounded down: add 1 to ensure the maximum // available precision. Then, in general, one more 1 needs to // be added since, when the %{g,G} conversion specifiers are // chosen inside _S_format_float, the precision field is "the // maximum number of significant digits", *not* the "number of // digits to appear after the decimal point", as happens for // %{e,E,f,F} (C99, 7.19.6.1,4). const int __max_digits = numeric_limits<_ValueT>::digits10 + 2; // Use default precision if out of range. streamsize __prec = __io.precision(); if (__prec > static_cast<streamsize>(__max_digits)) __prec = static_cast<streamsize>(__max_digits); else if (__prec < static_cast<streamsize>(0)) __prec = static_cast<streamsize>(6); typedef numpunct<_CharT> __facet_type; typedef __locale_cache<numpunct<_CharT> > __cache_type; const locale __loc = __io._M_getloc(); const __cache_type& __lc = __use_cache<__facet_type>(__loc); // [22.2.2.2.2] Stage 1, numeric conversion to character. int __len; // Long enough for the max format spec. char __fbuf[16];#ifdef _GLIBCPP_USE_C99 // First try a buffer perhaps big enough (for sure sufficient // for non-ios_base::fixed outputs) int __cs_size = __max_digits * 3; char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); _S_format_float(__io, __fbuf, __mod, __prec); __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_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 = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_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; // ios_base::fixed outputs may need up to __max_exp+1 chars // for the integer part + up to __max_digits chars for the // fractional part + 3 chars for sign, decimal point, '\0'. On // the other hand, for non-fixed outputs __max_digits*3 chars // are largely sufficient. const int __cs_size = __fixed ? __max_exp + __max_digits + 4 : __max_digits * 3; char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); _S_format_float(__io, __fbuf, __mod, __prec); __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_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; if (__p = char_traits<_CharT>::find(__ws, __len, __cdec)) __ws[__p - __ws] = __dec; // Add grouping, if necessary. _CharT* __ws2; if (__lc._M_use_grouping) { // Grouping can add (almost) as many separators as the // number of digits, but no more. __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len * 2)); _M_group_float(__lc._M_grouping, __lc._M_thousands_sep, __p, __ws2, __ws, __len); __ws = __ws2; } // Pad. _CharT* __ws3; streamsize __w = __io.width(); if (__w > static_cast<streamsize>(__len)) { __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 __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 { ios_base::fmtflags __flags = __io.flags(); if ((__flags & ios_base::boolalpha) == 0) { unsigned long __uv = __v; __s = _M_convert_int(__s, __io, __fill, __uv); } else { typedef numpunct<_CharT> __facet_type; typedef __locale_cache<numpunct<_CharT> > __cache_type; const locale __loc = __io._M_getloc(); const __cache_type& __lc = __use_cache<__facet_type>(__loc); typedef basic_string<_CharT> __string_type; __string_type __name; if (__v) __name = __lc._M_truename; else __name = __lc._M_falsename; const _CharT* __cs = __name.c_str(); int __len = __name.size(); _CharT* __cs3; streamsize __w = __io.width(); if (__w > static_cast<streamsize>(__len)) { __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w)); _M_pad(__fill, __w, __io, __cs3, __cs, __len); __cs = __cs3; } __io.width(0); __s = __write(__s, __cs, __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_convert_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_convert_int(__s, __io, __fill, __v); }#ifdef _GLIBCPP_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_convert_int(__s, __b, __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 long __v) const { return _M_convert_int(__s, __io, __fill, __v); }#endif template<typename _CharT, typename _OutIter> _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const { return _M_convert_float(__s, __io, __fill, char(), __v); } template<typename _CharT, typename _OutIter> _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, long double __v) const { return _M_convert_float(__s, __io, __fill, 'L', __v); } template<typename _CharT, typename _OutIter> _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, const void* __v) const { ios_base::fmtflags __flags = __io.flags(); ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield | ios_base::uppercase | ios_base::internal); __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase)); try { __s = _M_convert_int(__s, __io, __fill, reinterpret_cast<unsigned long>(__v)); __io.flags(__flags); } catch (...) { __io.flags(__flags); __throw_exception_again; } return __s; } template<typename _CharT, typename _InIter> _InIter money_get<_CharT, _InIter>:: do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, ios_base::iostate& __err, long double& __units) const { string_type __str; __beg = this->do_get(__beg, __end, __intl, __io, __err, __str); const int __cs_size = __str.size() + 1; char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); const locale __loc = __io.getloc(); const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); const _CharT* __wcs = __str.c_str(); __ctype.narrow(__wcs, __wcs + __cs_size, char(), __cs); __convert_to_v(__cs, __units, __err, _S_c_locale); return __beg; } template<typename _CharT, typename _InIter> _InIter money_get<_CharT, _InIter>:: do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, ios_base::iostate& __err, string_type& __units) const { // These contortions are quite unfortunate. typedef moneypunct<_CharT, true> __money_true; typedef moneypunct<_CharT, false> __money_false; typedef money_base::part part; typedef typename string_type::size_type size_type; const locale __loc = __io.getloc(); const __money_true& __mpt = use_facet<__money_true>(__loc); const __money_false& __mpf = use_facet<__money_false>(__loc); const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); const money_base::pattern __p = __intl ? __mpt.neg_format() : __mpf.neg_format(); const string_type __pos_sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign(); const string_type __neg_sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign(); const char_type __d = __intl ? __mpt.decimal_point() : __mpf.decimal_point(); const char_type __sep = __intl ? __mpt.thousands_sep() : __mpf.thousands_sep(); const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping(); // Set to deduced positive or negative sign, depending. string_type __sign; // String of grouping info from thousands_sep plucked from __units. string __grouping_tmp; // Marker for thousands_sep position. int __sep_pos = 0; // If input iterator is in a valid state. bool __testvalid = true; // Flag marking when a decimal point is found. bool __testdecfound = false; // The tentative returned string is stored here. string_type __temp_units; char_type __c = *__beg; char_type __eof = static_cast<char_type>(char_traits<char_type>::eof()); for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i) { part __which = static_cast<part>(__p.field[__i]); switch (__which) { case money_base::symbol: if (__io.flags() & ios_base::showbase || __i < 2 || __sign.size() > 1 || ((static_cast<part>(__p.field[3]) != money_base::none) && __i == 2)) { // According to 22.2.6.1.2.2, symbol is required // if (__io.flags() & ios_base::showbase), // otherwise is optional and consumed only if // other characters are needed to complete the // format. const string_type __symbol = __intl ? __mpt.curr_symbol() : __mpf.curr_symbol(); size_type __len = __symbol.size(); size_type __j = 0; while (__beg != __end && __j < __len && __symbol[__j] == __c) { __c = *(++__beg); ++__j; } // When (__io.flags() & ios_base::showbase) // symbol is required. if (__j != __len && (__io.flags() & ios_base::showbase)) __testvalid = false; } break; case money_base::sign: // Sign might not exist, or be more than one character long. if (__pos_sign.size() && __neg_sign.size()) { // Sign is mandatory. if (__c == __pos_sign[0]) { __sign = __pos_sign; __c = *(++__beg); } else if (__c == __neg_sign[0]) { __sign = __neg_sign; __c = *(++__beg); } else __testvalid = false; } else if (__pos_sign.size() && __c == __pos_sign[0]) { __sign = __pos_sign; __c = *(++__beg); } else if (__neg_sign.size() && __c == __neg_sign[0]) { __sign = __neg_sign; __c = *(++__beg); } break; case money_base::value: // Extract digits, remove and stash away the // grouping of found thousands separators. while (__beg != __end && (__ctype.is(ctype_base::digit, __c) || (__c == __d && !__testdecfound) || __c == __sep)) { if (__c == __d) { __grouping_tmp += static_cast<char>(__sep_pos); __sep_pos = 0; __testdecfound = true; } else if (__c == __sep) { if (__grouping.size()) { // Mark position for later analysis. __grouping_tmp += static_cast<char>(__sep_pos); __sep_pos = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -