📄 locale_facets.tcc
字号:
// Locale support -*- C++ -*-// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004// Free Software Foundation, Inc.//// This file is part of the GNU ISO C++ Library. This library is free// software; you can redistribute it and/or modify it under the// terms of the GNU General Public License as published by the// Free Software Foundation; either version 2, or (at your option)// any later version.// This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.// You should have received a copy of the GNU General Public License along// with this library; see the file COPYING. If not, write to the Free// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,// USA.// As a special exception, you may use this file as part of a free software// library without restriction. Specifically, if other files instantiate// templates or use macros or inline functions from this file, or you compile// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by// the GNU General Public License. This exception does not however// invalidate any other reasons why the executable file might be covered by// the GNU General Public License.// Warning: this file is not meant for user inclusion. Use <locale>.#ifndef _LOCALE_FACETS_TCC#define _LOCALE_FACETS_TCC 1#pragma GCC system_header#include <limits> // For numeric_limits#include <typeinfo> // For bad_cast.#include <bits/streambuf_iterator.h>namespace std{ template<typename _Facet> locale locale::combine(const locale& __other) const { _Impl* __tmp = new _Impl(*_M_impl, 1); try { __tmp->_M_replace_facet(__other._M_impl, &_Facet::id); } catch(...) { __tmp->_M_remove_reference(); __throw_exception_again; } return locale(__tmp); } template<typename _CharT, typename _Traits, typename _Alloc> bool locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1, const basic_string<_CharT, _Traits, _Alloc>& __s2) const { typedef std::collate<_CharT> __collate_type; const __collate_type& __collate = use_facet<__collate_type>(*this); return (__collate.compare(__s1.data(), __s1.data() + __s1.length(), __s2.data(), __s2.data() + __s2.length()) < 0); } /** * @brief Test for the presence of a facet. * * has_facet tests the locale argument for the presence of the facet type * provided as the template parameter. Facets derived from the facet * parameter will also return true. * * @param Facet The facet type to test the presence of. * @param locale The locale to test. * @return true if locale contains a facet of type Facet, else false. */ template<typename _Facet> inline bool has_facet(const locale& __loc) throw() { const size_t __i = _Facet::id._M_id(); const locale::facet** __facets = __loc._M_impl->_M_facets; return (__i < __loc._M_impl->_M_facets_size && __facets[__i]); } /** * @brief Return a facet. * * use_facet looks for and returns a reference to a facet of type Facet * where Facet is the template parameter. If has_facet(locale) is true, * there is a suitable facet to return. It throws std::bad_cast if the * locale doesn't contain a facet of type Facet. * * @param Facet The facet type to access. * @param locale The locale to use. * @return Reference to facet of type Facet. * @throw std::bad_cast if locale doesn't contain a facet of type Facet. */ template<typename _Facet> inline const _Facet& use_facet(const locale& __loc) { const size_t __i = _Facet::id._M_id(); const locale::facet** __facets = __loc._M_impl->_M_facets; if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i])) __throw_bad_cast(); return static_cast<const _Facet&>(*__facets[__i]); } // Routine to access a cache for the facet. If the cache didn't // exist before, it gets constructed on the fly. template<typename _Facet> struct __use_cache { const _Facet* operator() (const locale& __loc) const; }; // Specializations. template<typename _CharT> struct __use_cache<__numpunct_cache<_CharT> > { const __numpunct_cache<_CharT>* operator() (const locale& __loc) const { const size_t __i = numpunct<_CharT>::id._M_id(); const locale::facet** __caches = __loc._M_impl->_M_caches; if (!__caches[__i]) { __numpunct_cache<_CharT>* __tmp = NULL; try { __tmp = new __numpunct_cache<_CharT>; __tmp->_M_cache(__loc); } catch(...) { delete __tmp; __throw_exception_again; } __loc._M_impl->_M_install_cache(__tmp, __i); } return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]); } }; template<typename _CharT, bool _Intl> struct __use_cache<__moneypunct_cache<_CharT, _Intl> > { const __moneypunct_cache<_CharT, _Intl>* operator() (const locale& __loc) const { const size_t __i = moneypunct<_CharT, _Intl>::id._M_id(); const locale::facet** __caches = __loc._M_impl->_M_caches; if (!__caches[__i]) { __moneypunct_cache<_CharT, _Intl>* __tmp = NULL; try { __tmp = new __moneypunct_cache<_CharT, _Intl>; __tmp->_M_cache(__loc); } catch(...) { delete __tmp; __throw_exception_again; } __loc._M_impl->_M_install_cache(__tmp, __i); } return static_cast< const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]); } }; template<typename _CharT> void __numpunct_cache<_CharT>::_M_cache(const locale& __loc) { _M_allocated = true; const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); _M_grouping_size = __np.grouping().size(); char* __grouping = new char[_M_grouping_size]; __np.grouping().copy(__grouping, _M_grouping_size); _M_grouping = __grouping; _M_use_grouping = _M_grouping_size && __np.grouping()[0] != 0; _M_truename_size = __np.truename().size(); _CharT* __truename = new _CharT[_M_truename_size]; __np.truename().copy(__truename, _M_truename_size); _M_truename = __truename; _M_falsename_size = __np.falsename().size(); _CharT* __falsename = new _CharT[_M_falsename_size]; __np.falsename().copy(__falsename, _M_falsename_size); _M_falsename = __falsename; _M_decimal_point = __np.decimal_point(); _M_thousands_sep = __np.thousands_sep(); const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); __ct.widen(__num_base::_S_atoms_out, __num_base::_S_atoms_out + __num_base::_S_oend, _M_atoms_out); __ct.widen(__num_base::_S_atoms_in, __num_base::_S_atoms_in + __num_base::_S_iend, _M_atoms_in); } template<typename _CharT, bool _Intl> void __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc) { _M_allocated = true; const moneypunct<_CharT, _Intl>& __mp = use_facet<moneypunct<_CharT, _Intl> >(__loc); _M_grouping_size = __mp.grouping().size(); char* __grouping = new char[_M_grouping_size]; __mp.grouping().copy(__grouping, _M_grouping_size); _M_grouping = __grouping; _M_use_grouping = _M_grouping_size && __mp.grouping()[0] != 0; _M_decimal_point = __mp.decimal_point(); _M_thousands_sep = __mp.thousands_sep(); _M_frac_digits = __mp.frac_digits(); _M_curr_symbol_size = __mp.curr_symbol().size(); _CharT* __curr_symbol = new _CharT[_M_curr_symbol_size]; __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size); _M_curr_symbol = __curr_symbol; _M_positive_sign_size = __mp.positive_sign().size(); _CharT* __positive_sign = new _CharT[_M_positive_sign_size]; __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size); _M_positive_sign = __positive_sign; _M_negative_sign_size = __mp.negative_sign().size(); _CharT* __negative_sign = new _CharT[_M_negative_sign_size]; __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size); _M_negative_sign = __negative_sign; _M_pos_format = __mp.pos_format(); _M_neg_format = __mp.neg_format(); const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); __ct.widen(money_base::_S_atoms, money_base::_S_atoms + money_base::_S_end, _M_atoms); } // Used by both numeric and monetary facets. // Check to make sure that the __grouping_tmp string constructed in // money_get or num_get matches the canonical grouping for a given // locale. // __grouping_tmp is parsed L to R // 1,222,444 == __grouping_tmp of "\1\3\3" // __grouping is parsed R to L // 1,222,444 == __grouping of "\3" == "\3\3\3" static bool __verify_grouping(const char* __grouping, size_t __grouping_size, const string& __grouping_tmp); template<typename _CharT, typename _InIter> _InIter num_get<_CharT, _InIter>:: _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, ios_base::iostate& __err, string& __xtrc) const { typedef char_traits<_CharT> __traits_type; 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_in; // True if a mantissa is found. bool __found_mantissa = false; // First check for sign. if (__beg != __end) { const char_type __c = *__beg; const bool __plus = __c == __lit[__num_base::_S_iplus]; if ((__plus || __c == __lit[__num_base::_S_iminus]) && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) && !(__c == __lc->_M_decimal_point)) { __xtrc += __plus ? '+' : '-'; ++__beg; } } // Next, look for leading zeros. while (__beg != __end) { const char_type __c = *__beg; if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep || __c == __lc->_M_decimal_point) break; else if (__c == __lit[__num_base::_S_izero]) { if (!__found_mantissa) { __xtrc += '0'; __found_mantissa = true; } ++__beg; } else break; } // Only need acceptable digits for floating point numbers. bool __found_dec = false; bool __found_sci = false; string __found_grouping; if (__lc->_M_use_grouping) __found_grouping.reserve(32); int __sep_pos = 0; const char_type* __lit_zero = __lit + __num_base::_S_izero; const char_type* __q; while (__beg != __end) { // According to 22.2.2.1.2, p8-9, first look for thousands_sep // and decimal_point. const char_type __c = *__beg; if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) { if (!__found_dec && !__found_sci) { // NB: Thousands separator at the beginning of a string // is a no-no, as is two consecutive thousands separators. if (__sep_pos) { __found_grouping += static_cast<char>(__sep_pos); __sep_pos = 0; ++__beg; } else { __err |= ios_base::failbit; break; } } else break; } else if (__c == __lc->_M_decimal_point) { if (!__found_dec && !__found_sci) { // If no grouping chars are seen, no grouping check // is applied. Therefore __found_grouping is adjusted // only if decimal_point comes after some thousands_sep. if (__found_grouping.size()) __found_grouping += static_cast<char>(__sep_pos); __xtrc += '.'; __found_dec = true; ++__beg; } else break; } else if (__q = __traits_type::find(__lit_zero, 10, __c)) { __xtrc += __num_base::_S_atoms_in[__q - __lit]; __found_mantissa = true; ++__sep_pos; ++__beg; } else if ((__c == __lit[__num_base::_S_ie] || __c == __lit[__num_base::_S_iE]) && __found_mantissa && !__found_sci) { // Scientific notation. if (__found_grouping.size() && !__found_dec) __found_grouping += static_cast<char>(__sep_pos); __xtrc += 'e'; __found_sci = true; // Remove optional plus or minus sign, if they exist. if (++__beg != __end) { const bool __plus = *__beg == __lit[__num_base::_S_iplus]; if ((__plus || *__beg == __lit[__num_base::_S_iminus]) && !(__lc->_M_use_grouping && *__beg == __lc->_M_thousands_sep) && !(*__beg == __lc->_M_decimal_point)) { __xtrc += __plus ? '+' : '-'; ++__beg; } } } else // Not a valid input item. break; } // Digit grouping is checked. If grouping and found_grouping don't // match, then get very very upset, and set failbit. if (__lc->_M_use_grouping && __found_grouping.size()) { // Add the ending grouping if a decimal or 'e'/'E' wasn't found. if (!__found_dec && !__found_sci) __found_grouping += static_cast<char>(__sep_pos); if (!std::__verify_grouping(__lc->_M_grouping, __lc->_M_grouping_size, __found_grouping)) __err |= ios_base::failbit; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -