📄 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 _CPP_BITS_LOCFACETS_TCC#define _CPP_BITS_LOCFACETS_TCC 1#pragma GCC system_header#include <cerrno>#include <clocale> // For localeconv#include <cstdlib> // For strof, strtold#include <cmath> // For ceil#include <cctype> // For isspace#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); } template<typename _Facet> const _Facet& use_facet(const locale& __loc) { size_t __i = _Facet::id._M_id(); 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]); } template<typename _Facet> bool has_facet(const locale& __loc) throw() { size_t __i = _Facet::id._M_id(); locale::facet** __facets = __loc._M_impl->_M_facets; return (__i < __loc._M_impl->_M_facets_size && __facets[__i]); } // Routine to access a cache for the locale. If the cache didn't // exist before, it gets constructed on the fly. template<typename _Facet> inline const __locale_cache<_Facet>& __use_cache(const locale& __loc) { size_t __i = _Facet::id._M_id(); if (__builtin_expect(__i >= __loc._M_impl->_M_facets_size,false)) __throw_bad_cast(); __locale_cache_base* __cache = __loc._M_impl->_M_get_cache(__i); if (__builtin_expect(!__cache, false)) { __cache = new __locale_cache<_Facet>(__loc); __loc._M_impl->_M_install_cache(__cache, __i); } return static_cast<const __locale_cache<_Facet>&>(*__cache); } // Stage 1: Determine a conversion specifier. 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; const locale __loc = __io.getloc(); const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); // First check for sign. const char_type __plus = __ctype.widen('+'); const char_type __minus = __ctype.widen('-'); int __pos = 0; char_type __c = *__beg; if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) && __beg != __end) { __xtrc += __ctype.narrow(__c, char()); ++__pos; __c = *(++__beg); } // Next, strip leading zeros. const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]); bool __found_zero = false; while (__traits_type::eq(__c, __zero) && __beg != __end) { __c = *(++__beg); __found_zero = true; } if (__found_zero) { __xtrc += _S_atoms_in[_M_zero]; ++__pos; } // Only need acceptable digits for floating point numbers. const size_t __len = _M_E - _M_zero + 1; char_type __watoms[__len]; __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms); bool __found_dec = false; bool __found_sci = false; const char_type __dec = __np.decimal_point(); string __found_grouping; const string __grouping = __np.grouping(); bool __check_grouping = __grouping.size(); int __sep_pos = 0; const char_type __sep = __np.thousands_sep(); while (__beg != __end) { // Only look in digits. const char_type* __p = __traits_type::find(__watoms, 10, __c); // NB: strchr returns true for __c == 0x0 if (__p && !__traits_type::eq(__c, char_type())) { // Try first for acceptable digit; record it if found. ++__pos; __xtrc += _S_atoms_in[__p - __watoms]; ++__sep_pos; __c = *(++__beg); } else if (__traits_type::eq(__c, __sep) && __check_grouping && !__found_dec) { // 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; __c = *(++__beg); } else { __err |= ios_base::failbit; break; } } else if (__traits_type::eq(__c, __dec) && !__found_dec) { // According to the standard, if no grouping chars are seen, // no grouping check is applied. Therefore __found_grouping // must be adjusted only if __dec comes after some __sep. if (__found_grouping.size()) __found_grouping += static_cast<char>(__sep_pos); ++__pos; __xtrc += '.'; __c = *(++__beg); __found_dec = true; } else if ((__traits_type::eq(__c, __watoms[_M_e]) || __traits_type::eq(__c, __watoms[_M_E])) && !__found_sci && __pos) { // Scientific notation. ++__pos; __xtrc += __ctype.narrow(__c, char()); __c = *(++__beg); // Remove optional plus or minus sign, if they exist. if (__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) { ++__pos; __xtrc += __ctype.narrow(__c, char()); __c = *(++__beg); } __found_sci = true; } 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 (__check_grouping && __found_grouping.size()) { // Add the ending grouping if a decimal wasn't found. if (!__found_dec) __found_grouping += static_cast<char>(__sep_pos); if (!__verify_grouping(__grouping, __found_grouping)) __err |= ios_base::failbit; } // Finish up __xtrc += char(); if (__beg == __end) __err |= ios_base::eofbit; return __beg; } // Stage 1: Determine a conversion specifier. template<typename _CharT, typename _InIter> _InIter num_get<_CharT, _InIter>:: _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, ios_base::iostate& __err, string& __xtrc, int& __base) const { typedef char_traits<_CharT> __traits_type; const locale __loc = __io.getloc(); const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); // NB: Iff __basefield == 0, this can change based on contents. ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; if (__basefield == ios_base::oct) __base = 8; else if (__basefield == ios_base::hex) __base = 16; else __base = 10; // First check for sign. int __pos = 0; char_type __c = *__beg; const char_type __plus = __ctype.widen('+'); const char_type __minus = __ctype.widen('-'); if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) && __beg != __end) { __xtrc += __ctype.narrow(__c, char()); ++__pos; __c = *(++__beg); } // Next, strip leading zeros and check required digits for base formats. const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]); const char_type __x = __ctype.widen('x'); const char_type __X = __ctype.widen('X'); if (__base == 10) { bool __found_zero = false; while (__traits_type::eq(__c, __zero) && __beg != __end) { __c = *(++__beg); __found_zero = true; } if (__found_zero) { __xtrc += _S_atoms_in[_M_zero]; ++__pos; if (__basefield == 0) { if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X)) && __beg != __end) { __xtrc += __ctype.narrow(__c, char()); ++__pos; __c = *(++__beg); __base = 16; } else __base = 8; } } } else if (__base == 16) { if (__traits_type::eq(__c, __zero) && __beg != __end) { __xtrc += _S_atoms_in[_M_zero]; ++__pos; __c = *(++__beg); if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X)) && __beg != __end) { __xtrc += __ctype.narrow(__c, char()); ++__pos; __c = *(++__beg); } } } // At this point, base is determined. If not hex, only allow // base digits as valid input. size_t __len; if (__base == 16) __len = _M_size; else __len = __base; // Extract. char_type __watoms[_M_size]; __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms); string __found_grouping; const string __grouping = __np.grouping(); bool __check_grouping = __grouping.size(); int __sep_pos = 0; const char_type __sep = __np.thousands_sep(); while (__beg != __end) { const char_type* __p = __traits_type::find(__watoms, __len, __c); // NB: strchr returns true for __c == 0x0 if (__p && !__traits_type::eq(__c, char_type())) { // Try first for acceptable digit; record it if found. __xtrc += _S_atoms_in[__p - __watoms]; ++__pos; ++__sep_pos; __c = *(++__beg); } else if (__traits_type::eq(__c, __sep) && __check_grouping) { // 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; __c = *(++__beg); } else { __err |= ios_base::failbit; break; } } 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 (__check_grouping && __found_grouping.size()) { // Add the ending grouping. __found_grouping += static_cast<char>(__sep_pos); if (!__verify_grouping(__grouping, __found_grouping)) __err |= ios_base::failbit; } // Finish up. __xtrc += char(); if (__beg == __end) __err |= ios_base::eofbit; return __beg; }#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS //17. Bad bool parsing template<typename _CharT, typename _InIter> _InIter num_get<_CharT, _InIter>:: do_get(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, bool& __v) const { // Parse bool values as unsigned long if (!(__io.flags() & ios_base::boolalpha)) { // NB: We can't just call do_get(long) here, as it might // refer to a derived class.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -