📄 locale_facets.tcc
字号:
// Locale support -*- C++ -*-// Copyright (C) 1997-1999 Cygnus Solutions//// 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#include <bits/std_cerrno.h>#include <bits/std_cstdlib.h> // For strof, strtold#include <bits/std_limits.h> // For numeric_limits#include <bits/std_vector.h>#include <bits/std_memory.h> // For auto_ptr#include <bits/sbuf_iter.h> // For streambuf_iteratorsnamespace std{ template<typename _Facet> locale locale::combine(const locale& __other) { locale __copy(*this); __copy._M_impl->_M_replace_facet(__other._M_impl, &_Facet::id); __copy._M_impl->_M_has_name = false; return __copy; } 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 { return use_facet< std::collate<_CharT> > (*this) ( __s1.data(), __s1.data() + __s1.length(), __s2.data(), __s2.data() + __s2.length()) < 0; } template<typename _Facet> const _Facet& use_facet(const locale& __loc) { const locale::facet* __fp = (const _Facet*)0; // check derivation locale::id& __id = _Facet::id; // check member id size_t __i = __id._M_index; const locale::_Impl* __tmp = __loc._M_impl; if (__id._M_index >= __loc._M_impl->_M_facets->size() || (__fp = (*(__tmp->_M_facets))[__i]) == 0) return _Use_facet_failure_handler<_Facet>(__loc); return static_cast<const _Facet&>(*__fp); } template<typename _Facet> inline bool has_facet(const locale& __loc) throw() { const locale::facet* __fp = (const _Facet*)0; // check derivation locale::id& __id = _Facet::id; // check member id size_t __i = __id._M_index; const locale::_Impl* __tmp = __loc._M_impl; return (__id._M_index < (*(__tmp->_M_facets))->size() && (*(__tmp->_M_facets))[__i] != 0); } // __match_parallel // matches input __s against a set of __ntargs strings in __targets, // placing in __matches a vector of indices into __targets which // match, and in __remain the number of such matches. If it hits // end of sequence before it minimizes the set, sets __eof. // Empty strings are never matched. template<typename _InIter, typename _CharT> _InIter __match_parallel(_InIter __s, _InIter __end, int __ntargs, const basic_string<_CharT>* __targets, int* __matches, int& __remain, bool& __eof) { typedef basic_string<_CharT> __string_type; __eof = false; for (int __ti = 0; __ti < __ntargs; ++__ti) __matches[__ti] = __ti; __remain = __ntargs; size_t __pos = 0; do { { int __ti = 0; for (;__ti < __remain && __pos == __targets[__matches[__ti]].size(); ++__ti) { } if (__ti == __remain) { if (__pos == 0) __remain = 0; return __s; } } if (__s == __end) __eof = true; bool __matched = false; for (int __ti = 0; __ti < __remain; ) { const __string_type& __target = __targets[__matches[__ti]]; if (__pos < __target.size()) { if (__eof || __target[__pos] != *__s) { __matches[__ti] = __matches[--__remain]; continue; } __matched = true; } ++__ti; } if (__matched) { ++__s; ++__pos; } for (int __ti = 0; __ti < __remain;) { if (__pos > __targets[__matches[__ti]].size()) { __matches[__ti] = __matches[--__remain]; continue; } ++__ti; } } while (__remain); return __s; } template<typename _CharT> locale::id ctype<_CharT>::id; template<typename _InternT, typename _ExternT, typename _StateT> locale::id codecvt<_InternT,_ExternT,_StateT>::id; template<typename _CharT> int _Format_cache<_CharT>::_S_pword_ix; template<typename _CharT> const char _Format_cache<_CharT>:: _S_literals[] = "-+xX0123456789abcdef0123456789ABCDEF"; template<typename _CharT> _Format_cache<_CharT>::_Format_cache() : _M_valid(true), _M_use_grouping(false) { } template<> _Format_cache<char>::_Format_cache() : _M_valid(true), _M_decimal_point('.'), _M_thousands_sep(','), _M_truename("true"), _M_falsename("false"), _M_use_grouping(false) { } #ifdef _GLIBCPP_USE_WCHAR_T template<> _Format_cache<wchar_t>::_Format_cache() : _M_valid(true), _M_decimal_point(L'.'), _M_thousands_sep(L','), _M_truename(L"true"), _M_falsename(L"false"), _M_use_grouping(false) { }#endif template<typename _CharT> void _Format_cache<_CharT>::_M_populate(ios_base& __io) { locale __loc = __io.getloc (); numpunct<_CharT> const& __np = use_facet<numpunct<_CharT> >(__loc); _M_truename = __np.truename(); _M_falsename = __np.falsename(); _M_thousands_sep = __np.thousands_sep(); _M_decimal_point = __np.decimal_point(); _M_grouping = __np.grouping(); _M_use_grouping = _M_grouping.size() != 0 && _M_grouping.data()[0] != 0; _M_valid = true; } // This function is always called via a pointer installed in // an ios_base by ios_base::register_callback. template<typename _CharT> void _Format_cache<_CharT>:: _S_callback(ios_base::event __ev, ios_base& __ios, int __ix) throw() { void*& __p = __ios.pword(__ix); switch (__ev) { case ios_base::erase_event: delete static_cast<_Format_cache<_CharT>*> (__p); __p = 0; break; case ios_base::copyfmt_event: // If just stored zero, the callback would get registered again. try { __p = new _Format_cache<_CharT>; } catch(...) { } break; case ios_base::imbue_event: static_cast<_Format_cache<_CharT>*>(__p)->_M_valid = false; break; } } template<typename _CharT> _Format_cache<_CharT>* _Format_cache<_CharT>::_S_get(ios_base& __ios) { if (!_S_pword_ix) _S_pword_ix = ios_base::xalloc(); // XXX MT void*& __p = __ios.pword(_S_pword_ix); // XXX What if pword fails? must check failbit, throw. if (__p == 0) // XXX MT? maybe sentry takes care of it { auto_ptr<_Format_cache<_CharT> > __ap(new _Format_cache<_CharT>); __ios.register_callback(&_Format_cache<_CharT>::_S_callback, _S_pword_ix); __p = __ap.release(); } _Format_cache<_CharT>* __ncp = static_cast<_Format_cache<_CharT>*>(__p); if (!__ncp->_M_valid) __ncp->_M_populate(__ios); return __ncp; } template<typename _CharT, typename _InIter> locale::id num_get<_CharT, _InIter>::id; // This member function takes an (w)istreambuf_iterator object and // parses it into a generic char array suitable for parsing with // strto[l,ll,f,d]. The thought was to encapsulate the conversion // into this one function, and thus the num_get::do_get member // functions can just adjust for the type of the overloaded // argument and process the char array returned from _M_extract. // Other things were also considered, including a fused // multiply-add loop that would obviate the need for any call to // strto... at all: however, it would b e a bit of a pain, because // you'd have to be able to return either floating or integral // types, etc etc. The current approach seems to be smack dab in // the middle between an unoptimized approach using sscanf, and // some kind of hyper-optimized approach alluded to above. // XXX // Need to do partial specialization to account for differences // between character sets. For char, this is pretty // straightforward, but for wchar_t, the conversion to a plain-jane // char type is a bit more involved. template<typename _CharT, typename _InIter> void num_get<_CharT, _InIter>:: _M_extract(iter_type /*__beg*/, iter_type /*__end*/, ios_base& /*__io*/, ios_base::iostate& /*__err*/, char* /*__xtrc*/, int& /*__base*/, bool /*__fp*/) const { // XXX Not currently done: need to expand upon char version below. } template<> void num_get<char, istreambuf_iterator<char> >:: _M_extract(istreambuf_iterator<char> __beg, istreambuf_iterator<char> __end, ios_base& __io, ios_base::iostate& __err, char* __xtrc, int& __base, bool __fp) const { typedef _Format_cache<char> __cache_type; // Stage 1: determine a conversion specifier. 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; // Stage 2: extract characters. __cache_type const* __fmt =__cache_type::_S_get(__io); bool __valid = __beg != __end; string __grp; int __i; int __pos = 0; // XXX Need to deal with discarding leading zeros for non-octal numbers! for (__i = 0; __valid && __beg != __end; ++__i, ++__beg) { __valid = false; char __c = *__beg; const char* __lits = __fmt->_S_literals; char* __p = strchr(__fmt->_S_literals, __c); if (__p) { if (!__c) break; // NB: strchr returns true for __c == 0x0 if ((__p >= &__lits[__cache_type::_S_digits + __base] && __p < &__lits[__cache_type::_S_digits_end]) || (__p >= &__lits[__cache_type::_S_udigits+__base] && __p < &__lits[__cache_type::_S_udigits_end])) { if (!(__fp && (__p == &__lits[__cache_type::_S_ee] || __p == &__lits[__cache_type::_S_Ee]))) break; } __xtrc[__pos] = __c; ++__pos; __valid = true; } else if (__c == __fmt->_M_thousands_sep) { if (__fmt->_M_use_grouping) __grp += static_cast<char>(__i); __valid = true; } else if (__c == __fmt->_M_decimal_point) { if (!__fp) break; __xtrc[__pos] = '.'; ++__pos; __valid = true; } if (!__valid) break; // NB: for otherwise we consume another character } __xtrc[__pos] = '\0'; if (__beg == __end) __err |= ios_base::eofbit; // Digit grouping is checked. If _M_groupings() doesn't // match, then get very very upset, and set failbit. if (__fmt->_M_use_grouping && __grp != __fmt->_M_grouping) __err |= ios_base::failbit; } 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 long if (!(__io.flags() & ios_base::boolalpha)) { unsigned long __l = 0; this->do_get(__beg, __end, __io, __err, __l); if ((__err & ios_base::failbit) == 0) { if (__l <= 1) __v = __l; else __err |= ios_base::failbit; } } // Parse bool values as alphanumeric else { typedef _Format_cache<char_type> __fcache_type; __fcache_type* __fmt = __fcache_type::_S_get(__io); const char_type* __true = __fmt->_M_truename.c_str(); const char_type* __false = __fmt->_M_falsename.c_str(); char_type __itrue[sizeof(__true)]; char_type __ifalse[sizeof(__false)]; bool __valid = __beg != __end; int __pos = 0; for (; __valid; ++__pos) { __valid = false; char_type __c = *__beg++; if (__c == __false[__pos]) { __ifalse[__pos] = __c; __valid = true; if (__pos == sizeof(__false) - sizeof(char_type)) { __err |= ios_base::goodbit; __v = 0; } } else if (__c == __true[__pos]) { __itrue[__pos] = __c; __valid = true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -