📄 locale_facets.tcc
字号:
__use_cache<__cache_type> __uc; const __cache_type* __lc = __uc(__loc); const char_type* __lit = __lc->_M_atoms; // Deduced sign. bool __negative = false; // Sign size. size_type __sign_size = 0; // True if sign is mandatory. const bool __mandatory_sign = (__lc->_M_positive_sign_size && __lc->_M_negative_sign_size); // String of grouping info from thousands_sep plucked from __units. string __grouping_tmp; if (__lc->_M_use_grouping) __grouping_tmp.reserve(32); // Last position before the decimal point. int __last_pos = 0; // Separator positions, then, possibly, fractional digits. int __n = 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 __res; __res.reserve(32); const char_type* __lit_zero = __lit + money_base::_S_zero; const char_type* __q; const money_base::pattern __p = __lc->_M_neg_format; for (int __i = 0; __i < 4 && __testvalid; ++__i) { const part __which = static_cast<part>(__p.field[__i]); switch (__which) { case money_base::symbol: // According to 22.2.6.1.2, p2, symbol is required // if (__io.flags() & ios_base::showbase), otherwise // is optional and consumed only if other characters // are needed to complete the format. if (__io.flags() & ios_base::showbase || __sign_size > 1 || __i == 0 || (__i == 1 && (__mandatory_sign || (static_cast<part>(__p.field[0]) == money_base::sign) || (static_cast<part>(__p.field[2]) == money_base::space))) || (__i == 2 && ((static_cast<part>(__p.field[3]) == money_base::value) || __mandatory_sign && (static_cast<part>(__p.field[3]) == money_base::sign)))) { const size_type __len = __lc->_M_curr_symbol_size; size_type __j = 0; for (; __beg != __end && __j < __len && *__beg == __lc->_M_curr_symbol[__j]; ++__beg, ++__j); if (__j != __len && (__j || __io.flags() & ios_base::showbase)) __testvalid = false; } break; case money_base::sign: // Sign might not exist, or be more than one character long. if (__lc->_M_positive_sign_size && __beg != __end && *__beg == __lc->_M_positive_sign[0]) { __sign_size = __lc->_M_positive_sign_size; ++__beg; } else if (__lc->_M_negative_sign_size && __beg != __end && *__beg == __lc->_M_negative_sign[0]) { __negative = true; __sign_size = __lc->_M_negative_sign_size; ++__beg; } else if (__lc->_M_positive_sign_size && !__lc->_M_negative_sign_size) // "... if no sign is detected, the result is given the sign // that corresponds to the source of the empty string" __negative = true; else if (__mandatory_sign) __testvalid = false; break; case money_base::value: // Extract digits, remove and stash away the // grouping of found thousands separators. for (; __beg != __end; ++__beg) if (__q = __traits_type::find(__lit_zero, 10, *__beg)) { __res += money_base::_S_atoms[__q - __lit]; ++__n; } else if (*__beg == __lc->_M_decimal_point && !__testdecfound) { __last_pos = __n; __n = 0; __testdecfound = true; } else if (__lc->_M_use_grouping && *__beg == __lc->_M_thousands_sep && !__testdecfound) { if (__n) { // Mark position for later analysis. __grouping_tmp += static_cast<char>(__n); __n = 0; } else { __testvalid = false; break; } } else break; if (__res.empty()) __testvalid = false; break; case money_base::space: // At least one space is required. if (__beg != __end && __ctype.is(ctype_base::space, *__beg)) ++__beg; else __testvalid = false; case money_base::none: // Only if not at the end of the pattern. if (__i != 3) for (; __beg != __end && __ctype.is(ctype_base::space, *__beg); ++__beg); break; } } // Need to get the rest of the sign characters, if they exist. if (__sign_size > 1 && __testvalid) { const char_type* __sign = __negative ? __lc->_M_negative_sign : __lc->_M_positive_sign; size_type __i = 1; for (; __beg != __end && __i < __sign_size && *__beg == __sign[__i]; ++__beg, ++__i); if (__i != __sign_size) __testvalid = false; } if (__testvalid) { // Strip leading zeros. if (__res.size() > 1) { const size_type __first = __res.find_first_not_of('0'); const bool __only_zeros = __first == string::npos; if (__first) __res.erase(0, __only_zeros ? __res.size() - 1 : __first); } // 22.2.6.1.2, p4 if (__negative && __res[0] != '0') __res.insert(__res.begin(), '-'); // Test for grouping fidelity. if (__grouping_tmp.size()) { // Add the ending grouping. __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos : __n); if (!std::__verify_grouping(__lc->_M_grouping, __lc->_M_grouping_size, __grouping_tmp)) __testvalid = false; } // Iff not enough digits were supplied after the decimal-point. if (__testdecfound && __lc->_M_frac_digits > 0 && __n != __lc->_M_frac_digits) __testvalid = false; } // Iff no more characters are available. if (__beg == __end) __err |= ios_base::eofbit; // Iff valid sequence is not recognized. if (!__testvalid) __err |= ios_base::failbit; else __units.swap(__res); 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, long double& __units) const { string __str; if (__intl) __beg = _M_extract<true>(__beg, __end, __io, __err, __str); else __beg = _M_extract<false>(__beg, __end, __io, __err, __str); std::__convert_to_v(__str.c_str(), __units, __err, _S_get_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 { typedef typename string::size_type size_type; const locale& __loc = __io._M_getloc(); const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); string __str; const iter_type __ret = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) : _M_extract<false>(__beg, __end, __io, __err, __str); const size_type __len = __str.size(); if (__len) { _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); __ctype.widen(__str.data(), __str.data() + __len, __ws); __units.assign(__ws, __len); } return __ret; } template<typename _CharT, typename _OutIter> template<bool _Intl> _OutIter money_put<_CharT, _OutIter>:: _M_insert(iter_type __s, ios_base& __io, char_type __fill, const string_type& __digits) const { typedef typename string_type::size_type size_type; typedef money_base::part part; typedef moneypunct<_CharT, _Intl> __moneypunct_type; typedef typename __moneypunct_type::__cache_type __cache_type; const locale& __loc = __io._M_getloc(); const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); __use_cache<__cache_type> __uc; const __cache_type* __lc = __uc(__loc); const char_type* __lit = __lc->_M_atoms; // Determine if negative or positive formats are to be used, and // discard leading negative_sign if it is present. const char_type* __beg = __digits.data(); money_base::pattern __p; const char_type* __sign; size_type __sign_size; if (*__beg != __lit[money_base::_S_minus]) { __p = __lc->_M_pos_format; __sign = __lc->_M_positive_sign; __sign_size = __lc->_M_positive_sign_size; } else { __p = __lc->_M_neg_format; __sign = __lc->_M_negative_sign; __sign_size = __lc->_M_negative_sign_size; if (__digits.size()) ++__beg; } // Look for valid numbers in the ctype facet within input digits. size_type __len = __ctype.scan_not(ctype_base::digit, __beg, __beg + __digits.size()) - __beg; if (__len) { // Assume valid input, and attempt to format. // Break down input numbers into base components, as follows: // final_value = grouped units + (decimal point) + (digits) string_type __value; __value.reserve(2 * __len); // Add thousands separators to non-decimal digits, per // grouping rules. int __paddec = __len - __lc->_M_frac_digits; if (__paddec > 0) { if (__lc->_M_frac_digits < 0) __paddec = __len; if (__lc->_M_grouping_size) { _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 2 * __len)); _CharT* __ws_end = std::__add_grouping(__ws, __lc->_M_thousands_sep, __lc->_M_grouping, __lc->_M_grouping_size, __beg, __beg + __paddec); __value.assign(__ws, __ws_end - __ws); } else __value.assign(__beg, __paddec); } // Deal with decimal point, decimal digits. if (__lc->_M_frac_digits > 0) { __value += __lc->_M_decimal_point; if (__paddec >= 0) __value.append(__beg + __paddec, __lc->_M_frac_digits); else { // Have to pad zeros in the decimal position. __value.append(-__paddec, __lit[money_base::_S_zero]); __value.append(__beg, __len); } } // Calculate length of resulting string. const ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield; __len = __value.size() + __sign_size; __len += ((__io.flags() & ios_base::showbase) ? __lc->_M_curr_symbol_size : 0); string_type __res; __res.reserve(2 * __len); const size_type __width = static_cast<size_type>(__io.width()); const bool __testipad = (__f == ios_base::internal && __len < __width); // Fit formatted digits into the required pattern. for (int __i = 0; __i < 4; ++__i) { const part __which = static_cast<part>(__p.field[__i]); switch (__which) { case money_base::symbol: if (__io.flags() & ios_base::showbase) __res.append(__lc->_M_curr_symbol, __lc->_M_curr_symbol_size); break; case money_base::sign: // Sign might not exist, or be more than one // charater long. In that case, add in the rest // below. if (__sign_size) __res += __sign[0]; break; case money_base::value: __res += __value; break; case money_base::space: // At least one space is required, but if internal // formatting is required, an arbitrary number of // fill spaces will be necessary. if (__testipad) __res.append(__width - __len, __fill); else __res += __fill; break; case money_base::none: if (__testipad) __res.append(__width - __len, __fill); break; } } // Special case of multi-part sign parts. if (__sign_size > 1) __res.append(__sign + 1, __sign_size - 1); // Pad, if still necessary. __len = __res.size(); if (__width > __len) { if (__f == ios_base::left) // After. __res.append(__width - __len, __fill); else // Before. __res.insert(0, __width - __len, __fill); __len = __width; } // Write resulting, fully-formatted string to output iterator. __s = std::__write(__s, __res.data(), __len); } __io.width(0); return __s; } template<typename _CharT, typename _OutIter> _OutIter money_put<_CharT, _OutIter>:: do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, long double __units) const { const locale __loc = __io.getloc(); const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);#ifdef _GLIBCXX_USE_C99 // First try a buffer perhaps big enough. int __cs_size = 64; char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); // _GLIBCXX_RESOLVE_LIB_DEFECTS // 328. Bad sprintf format modifier in money_put<>::do_put() int __len = std::__convert_from_v(__cs, __cs_size, "%.*Lf", __units,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -