// Locale support -*- C++ -*-
-// Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2007-2015 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)
+// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-// 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.
-
-/** @file locale_facets_nonio.tcc
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/locale_facets_nonio.tcc
* This is an internal header file, included by other library headers.
- * You should not attempt to use it directly.
+ * Do not attempt to use it directly. @headername{locale}
*/
#ifndef _LOCALE_FACETS_NONIO_TCC
#pragma GCC system_header
-_GLIBCXX_BEGIN_NAMESPACE(std)
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _CharT, bool _Intl>
struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
const locale::facet** __caches = __loc._M_impl->_M_caches;
if (!__caches[__i])
{
- __moneypunct_cache<_CharT, _Intl>* __tmp = NULL;
+ __moneypunct_cache<_CharT, _Intl>* __tmp = 0;
__try
{
__tmp = new __moneypunct_cache<_CharT, _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
- && static_cast<signed char>(__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);
+ char* __grouping = 0;
+ _CharT* __curr_symbol = 0;
+ _CharT* __positive_sign = 0;
+ _CharT* __negative_sign = 0;
+ __try
+ {
+ const string& __g = __mp.grouping();
+ _M_grouping_size = __g.size();
+ __grouping = new char[_M_grouping_size];
+ __g.copy(__grouping, _M_grouping_size);
+ _M_use_grouping = (_M_grouping_size
+ && static_cast<signed char>(__grouping[0]) > 0
+ && (__grouping[0]
+ != __gnu_cxx::__numeric_traits<char>::__max));
+
+ const basic_string<_CharT>& __cs = __mp.curr_symbol();
+ _M_curr_symbol_size = __cs.size();
+ __curr_symbol = new _CharT[_M_curr_symbol_size];
+ __cs.copy(__curr_symbol, _M_curr_symbol_size);
+
+ const basic_string<_CharT>& __ps = __mp.positive_sign();
+ _M_positive_sign_size = __ps.size();
+ __positive_sign = new _CharT[_M_positive_sign_size];
+ __ps.copy(__positive_sign, _M_positive_sign_size);
+
+ const basic_string<_CharT>& __ns = __mp.negative_sign();
+ _M_negative_sign_size = __ns.size();
+ __negative_sign = new _CharT[_M_negative_sign_size];
+ __ns.copy(__negative_sign, _M_negative_sign_size);
+
+ _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);
+
+ _M_grouping = __grouping;
+ _M_curr_symbol = __curr_symbol;
+ _M_positive_sign = __positive_sign;
+ _M_negative_sign = __negative_sign;
+ _M_allocated = true;
+ }
+ __catch(...)
+ {
+ delete [] __grouping;
+ delete [] __curr_symbol;
+ delete [] __positive_sign;
+ delete [] __negative_sign;
+ __throw_exception_again;
+ }
}
-_GLIBCXX_BEGIN_LDBL_NAMESPACE
+_GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
template<typename _CharT, typename _InIter>
template<bool _Intl>
return __beg;
}
-#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
+ && _GLIBCXX_USE_CXX11_ABI == 0
template<typename _CharT, typename _InIter>
_InIter
money_get<_CharT, _InIter>::
return __s;
}
-#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
+ && _GLIBCXX_USE_CXX11_ABI == 0
template<typename _CharT, typename _OutIter>
_OutIter
money_put<_CharT, _OutIter>::
{ return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
: _M_insert<false>(__s, __io, __fill, __digits); }
-_GLIBCXX_END_LDBL_NAMESPACE
+_GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
// NB: Not especially useful. Without an ios_base object or some
// kind of locale reference, we are left clawing at the air where
const size_t __len = char_traits<_CharT>::length(__format);
ios_base::iostate __tmperr = ios_base::goodbit;
- for (size_t __i = 0; __beg != __end && __i < __len && !__tmperr; ++__i)
+ size_t __i = 0;
+ for (; __beg != __end && __i < __len && !__tmperr; ++__i)
{
if (__ctype.narrow(__format[__i], 0) == '%')
{
break;
case 'y':
case 'C': // C99
- // Two digit year. [tm_year]
- __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
- __io, __tmperr);
- break;
+ // Two digit year.
case 'Y':
- // Year [1900). [tm_year]
+ // Year [1900).
+ // NB: We parse either two digits, implicitly years since
+ // 1900, or 4 digits, full year. In both cases we can
+ // reconstruct [tm_year]. See also libstdc++/26701.
__beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
__io, __tmperr);
if (!__tmperr)
- __tm->tm_year = __mem - 1900;
+ __tm->tm_year = __mem < 0 ? __mem + 100 : __mem - 1900;
break;
case 'Z':
// Timezone info.
}
}
- if (__tmperr)
+ if (__tmperr || __i != __len)
__err |= ios_base::failbit;
return __beg;
}
if (__i == __len)
__member = __value;
+ // Special encoding for do_get_year, 'y', and 'Y' above.
+ else if (__len == 4 && __i == 2)
+ __member = __value - 100;
else
__err |= ios_base::failbit;
return __beg;
}
+ template<typename _CharT, typename _InIter>
+ _InIter
+ time_get<_CharT, _InIter>::
+ _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
+ const _CharT** __names, size_t __indexlen,
+ ios_base& __io, ios_base::iostate& __err) const
+ {
+ typedef char_traits<_CharT> __traits_type;
+ const locale& __loc = __io._M_getloc();
+ const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+
+ int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
+ * __indexlen));
+ size_t __nmatches = 0;
+ size_t* __matches_lengths = 0;
+ size_t __pos = 0;
+
+ if (__beg != __end)
+ {
+ const char_type __c = *__beg;
+ for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
+ if (__c == __names[__i][0]
+ || __c == __ctype.toupper(__names[__i][0]))
+ __matches[__nmatches++] = __i;
+ }
+
+ if (__nmatches)
+ {
+ ++__beg, ++__pos;
+
+ __matches_lengths
+ = static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
+ * __nmatches));
+ for (size_t __i = 0; __i < __nmatches; ++__i)
+ __matches_lengths[__i]
+ = __traits_type::length(__names[__matches[__i]]);
+ }
+
+ for (; __beg != __end; ++__beg, ++__pos)
+ {
+ size_t __nskipped = 0;
+ const char_type __c = *__beg;
+ for (size_t __i = 0; __i < __nmatches;)
+ {
+ const char_type* __name = __names[__matches[__i]];
+ if (__pos >= __matches_lengths[__i])
+ ++__nskipped, ++__i;
+ else if (!(__name[__pos] == __c))
+ {
+ --__nmatches;
+ __matches[__i] = __matches[__nmatches];
+ __matches_lengths[__i] = __matches_lengths[__nmatches];
+ }
+ else
+ ++__i;
+ }
+ if (__nskipped == __nmatches)
+ break;
+ }
+
+ if ((__nmatches == 1 && __matches_lengths[0] == __pos)
+ || (__nmatches == 2 && (__matches_lengths[0] == __pos
+ || __matches_lengths[1] == __pos)))
+ __member = (__matches[0] >= __indexlen
+ ? __matches[0] - __indexlen : __matches[0]);
+ else
+ __err |= ios_base::failbit;
+
+ return __beg;
+ }
+
template<typename _CharT, typename _InIter>
_InIter
time_get<_CharT, _InIter>::
do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
ios_base::iostate& __err, tm* __tm) const
{
- typedef char_traits<_CharT> __traits_type;
const locale& __loc = __io._M_getloc();
const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
- const char_type* __days[7];
+ const char_type* __days[14];
__tp._M_days_abbreviated(__days);
+ __tp._M_days(__days + 7);
int __tmpwday;
ios_base::iostate __tmperr = ios_base::goodbit;
- __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7,
- __io, __tmperr);
-
- // Check to see if non-abbreviated name exists, and extract.
- // NB: Assumes both _M_days and _M_days_abbreviated organized in
- // exact same order, first to last, such that the resulting
- // __days array with the same index points to a day, and that
- // day's abbreviated form.
- // NB: Also assumes that an abbreviated name is a subset of the name.
- if (!__tmperr && __beg != __end)
- {
- size_t __pos = __traits_type::length(__days[__tmpwday]);
- __tp._M_days(__days);
- const char_type* __name = __days[__tmpwday];
- if (__name[__pos] == *__beg)
- {
- // Extract the rest of it.
- const size_t __len = __traits_type::length(__name);
- while (__pos < __len && __beg != __end
- && __name[__pos] == *__beg)
- ++__beg, ++__pos;
- if (__len != __pos)
- __tmperr |= ios_base::failbit;
- }
- }
+
+ __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7,
+ __io, __tmperr);
if (!__tmperr)
__tm->tm_wday = __tmpwday;
else
do_get_monthname(iter_type __beg, iter_type __end,
ios_base& __io, ios_base::iostate& __err, tm* __tm) const
{
- typedef char_traits<_CharT> __traits_type;
const locale& __loc = __io._M_getloc();
const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
- const char_type* __months[12];
+ const char_type* __months[24];
__tp._M_months_abbreviated(__months);
+ __tp._M_months(__months + 12);
int __tmpmon;
ios_base::iostate __tmperr = ios_base::goodbit;
- __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12,
- __io, __tmperr);
-
- // Check to see if non-abbreviated name exists, and extract.
- // NB: Assumes both _M_months and _M_months_abbreviated organized in
- // exact same order, first to last, such that the resulting
- // __months array with the same index points to a month, and that
- // month's abbreviated form.
- // NB: Also assumes that an abbreviated name is a subset of the name.
- if (!__tmperr && __beg != __end)
- {
- size_t __pos = __traits_type::length(__months[__tmpmon]);
- __tp._M_months(__months);
- const char_type* __name = __months[__tmpmon];
- if (__name[__pos] == *__beg)
- {
- // Extract the rest of it.
- const size_t __len = __traits_type::length(__name);
- while (__pos < __len && __beg != __end
- && __name[__pos] == *__beg)
- ++__beg, ++__pos;
- if (__len != __pos)
- __tmperr |= ios_base::failbit;
- }
- }
+
+ __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12,
+ __io, __tmperr);
if (!__tmperr)
__tm->tm_mon = __tmpmon;
else
{
const locale& __loc = __io._M_getloc();
const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+ int __tmpyear;
+ ios_base::iostate __tmperr = ios_base::goodbit;
- size_t __i = 0;
- int __value = 0;
- for (; __beg != __end && __i < 4; ++__beg, ++__i)
- {
- const char __c = __ctype.narrow(*__beg, '*');
- if (__c >= '0' && __c <= '9')
- __value = __value * 10 + (__c - '0');
- else
- break;
- }
- if (__i == 2 || __i == 4)
- __tm->tm_year = __i == 2 ? __value : __value - 1900;
+ __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 9999, 4,
+ __io, __tmperr);
+ if (!__tmperr)
+ __tm->tm_year = __tmpyear < 0 ? __tmpyear + 100 : __tmpyear - 1900;
else
__err |= ios_base::failbit;
return __beg;
}
+#if __cplusplus >= 201103L
+ template<typename _CharT, typename _InIter>
+ inline
+ _InIter
+ time_get<_CharT, _InIter>::
+ get(iter_type __s, iter_type __end, ios_base& __io,
+ ios_base::iostate& __err, tm* __tm, const char_type* __fmt,
+ const char_type* __fmtend) const
+ {
+ const locale& __loc = __io._M_getloc();
+ ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
+ __err = ios_base::goodbit;
+ while (__fmt != __fmtend &&
+ __err == ios_base::goodbit)
+ {
+ if (__s == __end)
+ {
+ __err = ios_base::eofbit | ios_base::failbit;
+ break;
+ }
+ else if (__ctype.narrow(*__fmt, 0) == '%')
+ {
+ char __format;
+ char __mod = 0;
+ if (++__fmt == __fmtend)
+ {
+ __err = ios_base::failbit;
+ break;
+ }
+ const char __c = __ctype.narrow(*__fmt, 0);
+ if (__c != 'E' && __c != 'O')
+ __format = __c;
+ else if (++__fmt != __fmtend)
+ {
+ __mod = __c;
+ __format = __ctype.narrow(*__fmt, 0);
+ }
+ else
+ {
+ __err = ios_base::failbit;
+ break;
+ }
+ __s = this->do_get(__s, __end, __io, __err, __tm, __format,
+ __mod);
+ ++__fmt;
+ }
+ else if (__ctype.is(ctype_base::space, *__fmt))
+ {
+ ++__fmt;
+ while (__fmt != __fmtend &&
+ __ctype.is(ctype_base::space, *__fmt))
+ ++__fmt;
+
+ while (__s != __end &&
+ __ctype.is(ctype_base::space, *__s))
+ ++__s;
+ }
+ // TODO real case-insensitive comparison
+ else if (__ctype.tolower(*__s) == __ctype.tolower(*__fmt) ||
+ __ctype.toupper(*__s) == __ctype.toupper(*__fmt))
+ {
+ ++__s;
+ ++__fmt;
+ }
+ else
+ {
+ __err = ios_base::failbit;
+ break;
+ }
+ }
+ return __s;
+ }
+
+ template<typename _CharT, typename _InIter>
+ inline
+ _InIter
+ time_get<_CharT, _InIter>::
+ do_get(iter_type __beg, iter_type __end, ios_base& __io,
+ ios_base::iostate& __err, tm* __tm,
+ char __format, char __mod) const
+ {
+ const locale& __loc = __io._M_getloc();
+ ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
+ __err = ios_base::goodbit;
+
+ char_type __fmt[4];
+ __fmt[0] = __ctype.widen('%');
+ if (!__mod)
+ {
+ __fmt[1] = __format;
+ __fmt[2] = char_type();
+ }
+ else
+ {
+ __fmt[1] = __mod;
+ __fmt[2] = __format;
+ __fmt[3] = char_type();
+ }
+
+ __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, __fmt);
+ if (__beg == __end)
+ __err |= ios_base::eofbit;
+ return __beg;
+ }
+
+#endif // __cplusplus >= 201103L
+
template<typename _CharT, typename _OutIter>
_OutIter
time_put<_CharT, _OutIter>::
// NB: This size is arbitrary. Should this be a data member,
// initialized at construction?
const size_t __maxlen = 128;
- char_type* __res =
- static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
+ char_type __res[__maxlen];
// NB: In IEE 1003.1-200x, and perhaps other locale models, it
// is possible that the format character will be longer than one
// Inhibit implicit instantiations for required instantiations,
// which are defined via explicit instantiations elsewhere.
- // NB: This syntax is a GNU extension.
#if _GLIBCXX_EXTERN_TEMPLATE
extern template class moneypunct<char, false>;
extern template class moneypunct<char, true>;
extern template class moneypunct_byname<char, false>;
extern template class moneypunct_byname<char, true>;
- extern template class _GLIBCXX_LDBL_NAMESPACE money_get<char>;
- extern template class _GLIBCXX_LDBL_NAMESPACE money_put<char>;
+ extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<char>;
+ extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<char>;
extern template class __timepunct<char>;
extern template class time_put<char>;
extern template class time_put_byname<char>;
extern template class moneypunct<wchar_t, true>;
extern template class moneypunct_byname<wchar_t, false>;
extern template class moneypunct_byname<wchar_t, true>;
- extern template class _GLIBCXX_LDBL_NAMESPACE money_get<wchar_t>;
- extern template class _GLIBCXX_LDBL_NAMESPACE money_put<wchar_t>;
+ extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<wchar_t>;
+ extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<wchar_t>;
extern template class __timepunct<wchar_t>;
extern template class time_put<wchar_t>;
extern template class time_put_byname<wchar_t>;
#endif
#endif
-_GLIBCXX_END_NAMESPACE
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
#endif