[1166] | 1 | // Locale support -*- C++ -*-
|
---|
| 2 |
|
---|
| 3 | // Copyright (C) 2007-2021 Free Software Foundation, Inc.
|
---|
| 4 | //
|
---|
| 5 | // This file is part of the GNU ISO C++ Library. This library is free
|
---|
| 6 | // software; you can redistribute it and/or modify it under the
|
---|
| 7 | // terms of the GNU General Public License as published by the
|
---|
| 8 | // Free Software Foundation; either version 3, or (at your option)
|
---|
| 9 | // any later version.
|
---|
| 10 |
|
---|
| 11 | // This library is distributed in the hope that it will be useful,
|
---|
| 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
| 14 | // GNU General Public License for more details.
|
---|
| 15 |
|
---|
| 16 | // Under Section 7 of GPL version 3, you are granted additional
|
---|
| 17 | // permissions described in the GCC Runtime Library Exception, version
|
---|
| 18 | // 3.1, as published by the Free Software Foundation.
|
---|
| 19 |
|
---|
| 20 | // You should have received a copy of the GNU General Public License and
|
---|
| 21 | // a copy of the GCC Runtime Library Exception along with this program;
|
---|
| 22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
---|
| 23 | // <http://www.gnu.org/licenses/>.
|
---|
| 24 |
|
---|
| 25 | /** @file bits/locale_facets_nonio.tcc
|
---|
| 26 | * This is an internal header file, included by other library headers.
|
---|
| 27 | * Do not attempt to use it directly. @headername{locale}
|
---|
| 28 | */
|
---|
| 29 |
|
---|
| 30 | #ifndef _LOCALE_FACETS_NONIO_TCC
|
---|
| 31 | #define _LOCALE_FACETS_NONIO_TCC 1
|
---|
| 32 |
|
---|
| 33 | #pragma GCC system_header
|
---|
| 34 |
|
---|
| 35 | namespace std _GLIBCXX_VISIBILITY(default)
|
---|
| 36 | {
|
---|
| 37 | _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
---|
| 38 |
|
---|
| 39 | template<typename _CharT, bool _Intl>
|
---|
| 40 | struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
|
---|
| 41 | {
|
---|
| 42 | const __moneypunct_cache<_CharT, _Intl>*
|
---|
| 43 | operator() (const locale& __loc) const
|
---|
| 44 | {
|
---|
| 45 | const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
|
---|
| 46 | const locale::facet** __caches = __loc._M_impl->_M_caches;
|
---|
| 47 | if (!__caches[__i])
|
---|
| 48 | {
|
---|
| 49 | __moneypunct_cache<_CharT, _Intl>* __tmp = 0;
|
---|
| 50 | __try
|
---|
| 51 | {
|
---|
| 52 | __tmp = new __moneypunct_cache<_CharT, _Intl>;
|
---|
| 53 | __tmp->_M_cache(__loc);
|
---|
| 54 | }
|
---|
| 55 | __catch(...)
|
---|
| 56 | {
|
---|
| 57 | delete __tmp;
|
---|
| 58 | __throw_exception_again;
|
---|
| 59 | }
|
---|
| 60 | __loc._M_impl->_M_install_cache(__tmp, __i);
|
---|
| 61 | }
|
---|
| 62 | return static_cast<
|
---|
| 63 | const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
|
---|
| 64 | }
|
---|
| 65 | };
|
---|
| 66 |
|
---|
| 67 | template<typename _CharT, bool _Intl>
|
---|
| 68 | void
|
---|
| 69 | __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
|
---|
| 70 | {
|
---|
| 71 | const moneypunct<_CharT, _Intl>& __mp =
|
---|
| 72 | use_facet<moneypunct<_CharT, _Intl> >(__loc);
|
---|
| 73 |
|
---|
| 74 | _M_decimal_point = __mp.decimal_point();
|
---|
| 75 | _M_thousands_sep = __mp.thousands_sep();
|
---|
| 76 | _M_frac_digits = __mp.frac_digits();
|
---|
| 77 |
|
---|
| 78 | char* __grouping = 0;
|
---|
| 79 | _CharT* __curr_symbol = 0;
|
---|
| 80 | _CharT* __positive_sign = 0;
|
---|
| 81 | _CharT* __negative_sign = 0;
|
---|
| 82 | __try
|
---|
| 83 | {
|
---|
| 84 | const string& __g = __mp.grouping();
|
---|
| 85 | _M_grouping_size = __g.size();
|
---|
| 86 | __grouping = new char[_M_grouping_size];
|
---|
| 87 | __g.copy(__grouping, _M_grouping_size);
|
---|
| 88 | _M_use_grouping = (_M_grouping_size
|
---|
| 89 | && static_cast<signed char>(__grouping[0]) > 0
|
---|
| 90 | && (__grouping[0]
|
---|
| 91 | != __gnu_cxx::__numeric_traits<char>::__max));
|
---|
| 92 |
|
---|
| 93 | const basic_string<_CharT>& __cs = __mp.curr_symbol();
|
---|
| 94 | _M_curr_symbol_size = __cs.size();
|
---|
| 95 | __curr_symbol = new _CharT[_M_curr_symbol_size];
|
---|
| 96 | __cs.copy(__curr_symbol, _M_curr_symbol_size);
|
---|
| 97 |
|
---|
| 98 | const basic_string<_CharT>& __ps = __mp.positive_sign();
|
---|
| 99 | _M_positive_sign_size = __ps.size();
|
---|
| 100 | __positive_sign = new _CharT[_M_positive_sign_size];
|
---|
| 101 | __ps.copy(__positive_sign, _M_positive_sign_size);
|
---|
| 102 |
|
---|
| 103 | const basic_string<_CharT>& __ns = __mp.negative_sign();
|
---|
| 104 | _M_negative_sign_size = __ns.size();
|
---|
| 105 | __negative_sign = new _CharT[_M_negative_sign_size];
|
---|
| 106 | __ns.copy(__negative_sign, _M_negative_sign_size);
|
---|
| 107 |
|
---|
| 108 | _M_pos_format = __mp.pos_format();
|
---|
| 109 | _M_neg_format = __mp.neg_format();
|
---|
| 110 |
|
---|
| 111 | const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
|
---|
| 112 | __ct.widen(money_base::_S_atoms,
|
---|
| 113 | money_base::_S_atoms + money_base::_S_end, _M_atoms);
|
---|
| 114 |
|
---|
| 115 | _M_grouping = __grouping;
|
---|
| 116 | _M_curr_symbol = __curr_symbol;
|
---|
| 117 | _M_positive_sign = __positive_sign;
|
---|
| 118 | _M_negative_sign = __negative_sign;
|
---|
| 119 | _M_allocated = true;
|
---|
| 120 | }
|
---|
| 121 | __catch(...)
|
---|
| 122 | {
|
---|
| 123 | delete [] __grouping;
|
---|
| 124 | delete [] __curr_symbol;
|
---|
| 125 | delete [] __positive_sign;
|
---|
| 126 | delete [] __negative_sign;
|
---|
| 127 | __throw_exception_again;
|
---|
| 128 | }
|
---|
| 129 | }
|
---|
| 130 |
|
---|
| 131 | _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
|
---|
| 132 |
|
---|
| 133 | template<typename _CharT, typename _InIter>
|
---|
| 134 | template<bool _Intl>
|
---|
| 135 | _InIter
|
---|
| 136 | money_get<_CharT, _InIter>::
|
---|
| 137 | _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
|
---|
| 138 | ios_base::iostate& __err, string& __units) const
|
---|
| 139 | {
|
---|
| 140 | typedef char_traits<_CharT> __traits_type;
|
---|
| 141 | typedef typename string_type::size_type size_type;
|
---|
| 142 | typedef money_base::part part;
|
---|
| 143 | typedef __moneypunct_cache<_CharT, _Intl> __cache_type;
|
---|
| 144 |
|
---|
| 145 | const locale& __loc = __io._M_getloc();
|
---|
| 146 | const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
|
---|
| 147 |
|
---|
| 148 | __use_cache<__cache_type> __uc;
|
---|
| 149 | const __cache_type* __lc = __uc(__loc);
|
---|
| 150 | const char_type* __lit = __lc->_M_atoms;
|
---|
| 151 |
|
---|
| 152 | // Deduced sign.
|
---|
| 153 | bool __negative = false;
|
---|
| 154 | // Sign size.
|
---|
| 155 | size_type __sign_size = 0;
|
---|
| 156 | // True if sign is mandatory.
|
---|
| 157 | const bool __mandatory_sign = (__lc->_M_positive_sign_size
|
---|
| 158 | && __lc->_M_negative_sign_size);
|
---|
| 159 | // String of grouping info from thousands_sep plucked from __units.
|
---|
| 160 | string __grouping_tmp;
|
---|
| 161 | if (__lc->_M_use_grouping)
|
---|
| 162 | __grouping_tmp.reserve(32);
|
---|
| 163 | // Last position before the decimal point.
|
---|
| 164 | int __last_pos = 0;
|
---|
| 165 | // Separator positions, then, possibly, fractional digits.
|
---|
| 166 | int __n = 0;
|
---|
| 167 | // If input iterator is in a valid state.
|
---|
| 168 | bool __testvalid = true;
|
---|
| 169 | // Flag marking when a decimal point is found.
|
---|
| 170 | bool __testdecfound = false;
|
---|
| 171 |
|
---|
| 172 | // The tentative returned string is stored here.
|
---|
| 173 | string __res;
|
---|
| 174 | __res.reserve(32);
|
---|
| 175 |
|
---|
| 176 | const char_type* __lit_zero = __lit + money_base::_S_zero;
|
---|
| 177 | const money_base::pattern __p = __lc->_M_neg_format;
|
---|
| 178 | for (int __i = 0; __i < 4 && __testvalid; ++__i)
|
---|
| 179 | {
|
---|
| 180 | const part __which = static_cast<part>(__p.field[__i]);
|
---|
| 181 | switch (__which)
|
---|
| 182 | {
|
---|
| 183 | case money_base::symbol:
|
---|
| 184 | // According to 22.2.6.1.2, p2, symbol is required
|
---|
| 185 | // if (__io.flags() & ios_base::showbase), otherwise
|
---|
| 186 | // is optional and consumed only if other characters
|
---|
| 187 | // are needed to complete the format.
|
---|
| 188 | if (__io.flags() & ios_base::showbase || __sign_size > 1
|
---|
| 189 | || __i == 0
|
---|
| 190 | || (__i == 1 && (__mandatory_sign
|
---|
| 191 | || (static_cast<part>(__p.field[0])
|
---|
| 192 | == money_base::sign)
|
---|
| 193 | || (static_cast<part>(__p.field[2])
|
---|
| 194 | == money_base::space)))
|
---|
| 195 | || (__i == 2 && ((static_cast<part>(__p.field[3])
|
---|
| 196 | == money_base::value)
|
---|
| 197 | || (__mandatory_sign
|
---|
| 198 | && (static_cast<part>(__p.field[3])
|
---|
| 199 | == money_base::sign)))))
|
---|
| 200 | {
|
---|
| 201 | const size_type __len = __lc->_M_curr_symbol_size;
|
---|
| 202 | size_type __j = 0;
|
---|
| 203 | for (; __beg != __end && __j < __len
|
---|
| 204 | && *__beg == __lc->_M_curr_symbol[__j];
|
---|
| 205 | ++__beg, (void)++__j);
|
---|
| 206 | if (__j != __len
|
---|
| 207 | && (__j || __io.flags() & ios_base::showbase))
|
---|
| 208 | __testvalid = false;
|
---|
| 209 | }
|
---|
| 210 | break;
|
---|
| 211 | case money_base::sign:
|
---|
| 212 | // Sign might not exist, or be more than one character long.
|
---|
| 213 | if (__lc->_M_positive_sign_size && __beg != __end
|
---|
| 214 | && *__beg == __lc->_M_positive_sign[0])
|
---|
| 215 | {
|
---|
| 216 | __sign_size = __lc->_M_positive_sign_size;
|
---|
| 217 | ++__beg;
|
---|
| 218 | }
|
---|
| 219 | else if (__lc->_M_negative_sign_size && __beg != __end
|
---|
| 220 | && *__beg == __lc->_M_negative_sign[0])
|
---|
| 221 | {
|
---|
| 222 | __negative = true;
|
---|
| 223 | __sign_size = __lc->_M_negative_sign_size;
|
---|
| 224 | ++__beg;
|
---|
| 225 | }
|
---|
| 226 | else if (__lc->_M_positive_sign_size
|
---|
| 227 | && !__lc->_M_negative_sign_size)
|
---|
| 228 | // "... if no sign is detected, the result is given the sign
|
---|
| 229 | // that corresponds to the source of the empty string"
|
---|
| 230 | __negative = true;
|
---|
| 231 | else if (__mandatory_sign)
|
---|
| 232 | __testvalid = false;
|
---|
| 233 | break;
|
---|
| 234 | case money_base::value:
|
---|
| 235 | // Extract digits, remove and stash away the
|
---|
| 236 | // grouping of found thousands separators.
|
---|
| 237 | for (; __beg != __end; ++__beg)
|
---|
| 238 | {
|
---|
| 239 | const char_type __c = *__beg;
|
---|
| 240 | const char_type* __q = __traits_type::find(__lit_zero,
|
---|
| 241 | 10, __c);
|
---|
| 242 | if (__q != 0)
|
---|
| 243 | {
|
---|
| 244 | __res += money_base::_S_atoms[__q - __lit];
|
---|
| 245 | ++__n;
|
---|
| 246 | }
|
---|
| 247 | else if (__c == __lc->_M_decimal_point
|
---|
| 248 | && !__testdecfound)
|
---|
| 249 | {
|
---|
| 250 | if (__lc->_M_frac_digits <= 0)
|
---|
| 251 | break;
|
---|
| 252 |
|
---|
| 253 | __last_pos = __n;
|
---|
| 254 | __n = 0;
|
---|
| 255 | __testdecfound = true;
|
---|
| 256 | }
|
---|
| 257 | else if (__lc->_M_use_grouping
|
---|
| 258 | && __c == __lc->_M_thousands_sep
|
---|
| 259 | && !__testdecfound)
|
---|
| 260 | {
|
---|
| 261 | if (__n)
|
---|
| 262 | {
|
---|
| 263 | // Mark position for later analysis.
|
---|
| 264 | __grouping_tmp += static_cast<char>(__n);
|
---|
| 265 | __n = 0;
|
---|
| 266 | }
|
---|
| 267 | else
|
---|
| 268 | {
|
---|
| 269 | __testvalid = false;
|
---|
| 270 | break;
|
---|
| 271 | }
|
---|
| 272 | }
|
---|
| 273 | else
|
---|
| 274 | break;
|
---|
| 275 | }
|
---|
| 276 | if (__res.empty())
|
---|
| 277 | __testvalid = false;
|
---|
| 278 | break;
|
---|
| 279 | case money_base::space:
|
---|
| 280 | // At least one space is required.
|
---|
| 281 | if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
|
---|
| 282 | ++__beg;
|
---|
| 283 | else
|
---|
| 284 | __testvalid = false;
|
---|
| 285 | // fallthrough
|
---|
| 286 | case money_base::none:
|
---|
| 287 | // Only if not at the end of the pattern.
|
---|
| 288 | if (__i != 3)
|
---|
| 289 | for (; __beg != __end
|
---|
| 290 | && __ctype.is(ctype_base::space, *__beg); ++__beg);
|
---|
| 291 | break;
|
---|
| 292 | }
|
---|
| 293 | }
|
---|
| 294 |
|
---|
| 295 | // Need to get the rest of the sign characters, if they exist.
|
---|
| 296 | if (__sign_size > 1 && __testvalid)
|
---|
| 297 | {
|
---|
| 298 | const char_type* __sign = __negative ? __lc->_M_negative_sign
|
---|
| 299 | : __lc->_M_positive_sign;
|
---|
| 300 | size_type __i = 1;
|
---|
| 301 | for (; __beg != __end && __i < __sign_size
|
---|
| 302 | && *__beg == __sign[__i]; ++__beg, (void)++__i);
|
---|
| 303 |
|
---|
| 304 | if (__i != __sign_size)
|
---|
| 305 | __testvalid = false;
|
---|
| 306 | }
|
---|
| 307 |
|
---|
| 308 | if (__testvalid)
|
---|
| 309 | {
|
---|
| 310 | // Strip leading zeros.
|
---|
| 311 | if (__res.size() > 1)
|
---|
| 312 | {
|
---|
| 313 | const size_type __first = __res.find_first_not_of('0');
|
---|
| 314 | const bool __only_zeros = __first == string::npos;
|
---|
| 315 | if (__first)
|
---|
| 316 | __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
|
---|
| 317 | }
|
---|
| 318 |
|
---|
| 319 | // 22.2.6.1.2, p4
|
---|
| 320 | if (__negative && __res[0] != '0')
|
---|
| 321 | __res.insert(__res.begin(), '-');
|
---|
| 322 |
|
---|
| 323 | // Test for grouping fidelity.
|
---|
| 324 | if (__grouping_tmp.size())
|
---|
| 325 | {
|
---|
| 326 | // Add the ending grouping.
|
---|
| 327 | __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
|
---|
| 328 | : __n);
|
---|
| 329 | if (!std::__verify_grouping(__lc->_M_grouping,
|
---|
| 330 | __lc->_M_grouping_size,
|
---|
| 331 | __grouping_tmp))
|
---|
| 332 | __err |= ios_base::failbit;
|
---|
| 333 | }
|
---|
| 334 |
|
---|
| 335 | // Iff not enough digits were supplied after the decimal-point.
|
---|
| 336 | if (__testdecfound && __n != __lc->_M_frac_digits)
|
---|
| 337 | __testvalid = false;
|
---|
| 338 | }
|
---|
| 339 |
|
---|
| 340 | // Iff valid sequence is not recognized.
|
---|
| 341 | if (!__testvalid)
|
---|
| 342 | __err |= ios_base::failbit;
|
---|
| 343 | else
|
---|
| 344 | __units.swap(__res);
|
---|
| 345 |
|
---|
| 346 | // Iff no more characters are available.
|
---|
| 347 | if (__beg == __end)
|
---|
| 348 | __err |= ios_base::eofbit;
|
---|
| 349 | return __beg;
|
---|
| 350 | }
|
---|
| 351 |
|
---|
| 352 | #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
|
---|
| 353 | && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
|
---|
| 354 | template<typename _CharT, typename _InIter>
|
---|
| 355 | _InIter
|
---|
| 356 | money_get<_CharT, _InIter>::
|
---|
| 357 | __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
|
---|
| 358 | ios_base::iostate& __err, double& __units) const
|
---|
| 359 | {
|
---|
| 360 | string __str;
|
---|
| 361 | __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
|
---|
| 362 | : _M_extract<false>(__beg, __end, __io, __err, __str);
|
---|
| 363 | std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
|
---|
| 364 | return __beg;
|
---|
| 365 | }
|
---|
| 366 | #endif
|
---|
| 367 |
|
---|
| 368 | template<typename _CharT, typename _InIter>
|
---|
| 369 | _InIter
|
---|
| 370 | money_get<_CharT, _InIter>::
|
---|
| 371 | do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
|
---|
| 372 | ios_base::iostate& __err, long double& __units) const
|
---|
| 373 | {
|
---|
| 374 | string __str;
|
---|
| 375 | __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
|
---|
| 376 | : _M_extract<false>(__beg, __end, __io, __err, __str);
|
---|
| 377 | std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
|
---|
| 378 | return __beg;
|
---|
| 379 | }
|
---|
| 380 |
|
---|
| 381 | template<typename _CharT, typename _InIter>
|
---|
| 382 | _InIter
|
---|
| 383 | money_get<_CharT, _InIter>::
|
---|
| 384 | do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
|
---|
| 385 | ios_base::iostate& __err, string_type& __digits) const
|
---|
| 386 | {
|
---|
| 387 | typedef typename string::size_type size_type;
|
---|
| 388 |
|
---|
| 389 | const locale& __loc = __io._M_getloc();
|
---|
| 390 | const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
|
---|
| 391 |
|
---|
| 392 | string __str;
|
---|
| 393 | __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
|
---|
| 394 | : _M_extract<false>(__beg, __end, __io, __err, __str);
|
---|
| 395 | const size_type __len = __str.size();
|
---|
| 396 | if (__len)
|
---|
| 397 | {
|
---|
| 398 | __digits.resize(__len);
|
---|
| 399 | __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]);
|
---|
| 400 | }
|
---|
| 401 | return __beg;
|
---|
| 402 | }
|
---|
| 403 |
|
---|
| 404 | #if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
|
---|
| 405 | && defined __LONG_DOUBLE_IEEE128__
|
---|
| 406 | template<typename _CharT, typename _InIter>
|
---|
| 407 | _InIter
|
---|
| 408 | money_get<_CharT, _InIter>::
|
---|
| 409 | __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
|
---|
| 410 | ios_base::iostate& __err, __ibm128& __units) const
|
---|
| 411 | {
|
---|
| 412 | string __str;
|
---|
| 413 | __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
|
---|
| 414 | : _M_extract<false>(__beg, __end, __io, __err, __str);
|
---|
| 415 | std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
|
---|
| 416 | return __beg;
|
---|
| 417 | }
|
---|
| 418 | #endif
|
---|
| 419 |
|
---|
| 420 | template<typename _CharT, typename _OutIter>
|
---|
| 421 | template<bool _Intl>
|
---|
| 422 | _OutIter
|
---|
| 423 | money_put<_CharT, _OutIter>::
|
---|
| 424 | _M_insert(iter_type __s, ios_base& __io, char_type __fill,
|
---|
| 425 | const string_type& __digits) const
|
---|
| 426 | {
|
---|
| 427 | typedef typename string_type::size_type size_type;
|
---|
| 428 | typedef money_base::part part;
|
---|
| 429 | typedef __moneypunct_cache<_CharT, _Intl> __cache_type;
|
---|
| 430 |
|
---|
| 431 | const locale& __loc = __io._M_getloc();
|
---|
| 432 | const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
|
---|
| 433 |
|
---|
| 434 | __use_cache<__cache_type> __uc;
|
---|
| 435 | const __cache_type* __lc = __uc(__loc);
|
---|
| 436 | const char_type* __lit = __lc->_M_atoms;
|
---|
| 437 |
|
---|
| 438 | // Determine if negative or positive formats are to be used, and
|
---|
| 439 | // discard leading negative_sign if it is present.
|
---|
| 440 | const char_type* __beg = __digits.data();
|
---|
| 441 |
|
---|
| 442 | money_base::pattern __p;
|
---|
| 443 | const char_type* __sign;
|
---|
| 444 | size_type __sign_size;
|
---|
| 445 | if (!(*__beg == __lit[money_base::_S_minus]))
|
---|
| 446 | {
|
---|
| 447 | __p = __lc->_M_pos_format;
|
---|
| 448 | __sign = __lc->_M_positive_sign;
|
---|
| 449 | __sign_size = __lc->_M_positive_sign_size;
|
---|
| 450 | }
|
---|
| 451 | else
|
---|
| 452 | {
|
---|
| 453 | __p = __lc->_M_neg_format;
|
---|
| 454 | __sign = __lc->_M_negative_sign;
|
---|
| 455 | __sign_size = __lc->_M_negative_sign_size;
|
---|
| 456 | if (__digits.size())
|
---|
| 457 | ++__beg;
|
---|
| 458 | }
|
---|
| 459 |
|
---|
| 460 | // Look for valid numbers in the ctype facet within input digits.
|
---|
| 461 | size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
|
---|
| 462 | __beg + __digits.size()) - __beg;
|
---|
| 463 | if (__len)
|
---|
| 464 | {
|
---|
| 465 | // Assume valid input, and attempt to format.
|
---|
| 466 | // Break down input numbers into base components, as follows:
|
---|
| 467 | // final_value = grouped units + (decimal point) + (digits)
|
---|
| 468 | string_type __value;
|
---|
| 469 | __value.reserve(2 * __len);
|
---|
| 470 |
|
---|
| 471 | // Add thousands separators to non-decimal digits, per
|
---|
| 472 | // grouping rules.
|
---|
| 473 | long __paddec = __len - __lc->_M_frac_digits;
|
---|
| 474 | if (__paddec > 0)
|
---|
| 475 | {
|
---|
| 476 | if (__lc->_M_frac_digits < 0)
|
---|
| 477 | __paddec = __len;
|
---|
| 478 | if (__lc->_M_grouping_size)
|
---|
| 479 | {
|
---|
| 480 | __value.assign(2 * __paddec, char_type());
|
---|
| 481 | _CharT* __vend =
|
---|
| 482 | std::__add_grouping(&__value[0], __lc->_M_thousands_sep,
|
---|
| 483 | __lc->_M_grouping,
|
---|
| 484 | __lc->_M_grouping_size,
|
---|
| 485 | __beg, __beg + __paddec);
|
---|
| 486 | __value.erase(__vend - &__value[0]);
|
---|
| 487 | }
|
---|
| 488 | else
|
---|
| 489 | __value.assign(__beg, __paddec);
|
---|
| 490 | }
|
---|
| 491 |
|
---|
| 492 | // Deal with decimal point, decimal digits.
|
---|
| 493 | if (__lc->_M_frac_digits > 0)
|
---|
| 494 | {
|
---|
| 495 | __value += __lc->_M_decimal_point;
|
---|
| 496 | if (__paddec >= 0)
|
---|
| 497 | __value.append(__beg + __paddec, __lc->_M_frac_digits);
|
---|
| 498 | else
|
---|
| 499 | {
|
---|
| 500 | // Have to pad zeros in the decimal position.
|
---|
| 501 | __value.append(-__paddec, __lit[money_base::_S_zero]);
|
---|
| 502 | __value.append(__beg, __len);
|
---|
| 503 | }
|
---|
| 504 | }
|
---|
| 505 |
|
---|
| 506 | // Calculate length of resulting string.
|
---|
| 507 | const ios_base::fmtflags __f = __io.flags()
|
---|
| 508 | & ios_base::adjustfield;
|
---|
| 509 | __len = __value.size() + __sign_size;
|
---|
| 510 | __len += ((__io.flags() & ios_base::showbase)
|
---|
| 511 | ? __lc->_M_curr_symbol_size : 0);
|
---|
| 512 |
|
---|
| 513 | string_type __res;
|
---|
| 514 | __res.reserve(2 * __len);
|
---|
| 515 |
|
---|
| 516 | const size_type __width = static_cast<size_type>(__io.width());
|
---|
| 517 | const bool __testipad = (__f == ios_base::internal
|
---|
| 518 | && __len < __width);
|
---|
| 519 | // Fit formatted digits into the required pattern.
|
---|
| 520 | for (int __i = 0; __i < 4; ++__i)
|
---|
| 521 | {
|
---|
| 522 | const part __which = static_cast<part>(__p.field[__i]);
|
---|
| 523 | switch (__which)
|
---|
| 524 | {
|
---|
| 525 | case money_base::symbol:
|
---|
| 526 | if (__io.flags() & ios_base::showbase)
|
---|
| 527 | __res.append(__lc->_M_curr_symbol,
|
---|
| 528 | __lc->_M_curr_symbol_size);
|
---|
| 529 | break;
|
---|
| 530 | case money_base::sign:
|
---|
| 531 | // Sign might not exist, or be more than one
|
---|
| 532 | // character long. In that case, add in the rest
|
---|
| 533 | // below.
|
---|
| 534 | if (__sign_size)
|
---|
| 535 | __res += __sign[0];
|
---|
| 536 | break;
|
---|
| 537 | case money_base::value:
|
---|
| 538 | __res += __value;
|
---|
| 539 | break;
|
---|
| 540 | case money_base::space:
|
---|
| 541 | // At least one space is required, but if internal
|
---|
| 542 | // formatting is required, an arbitrary number of
|
---|
| 543 | // fill spaces will be necessary.
|
---|
| 544 | if (__testipad)
|
---|
| 545 | __res.append(__width - __len, __fill);
|
---|
| 546 | else
|
---|
| 547 | __res += __fill;
|
---|
| 548 | break;
|
---|
| 549 | case money_base::none:
|
---|
| 550 | if (__testipad)
|
---|
| 551 | __res.append(__width - __len, __fill);
|
---|
| 552 | break;
|
---|
| 553 | }
|
---|
| 554 | }
|
---|
| 555 |
|
---|
| 556 | // Special case of multi-part sign parts.
|
---|
| 557 | if (__sign_size > 1)
|
---|
| 558 | __res.append(__sign + 1, __sign_size - 1);
|
---|
| 559 |
|
---|
| 560 | // Pad, if still necessary.
|
---|
| 561 | __len = __res.size();
|
---|
| 562 | if (__width > __len)
|
---|
| 563 | {
|
---|
| 564 | if (__f == ios_base::left)
|
---|
| 565 | // After.
|
---|
| 566 | __res.append(__width - __len, __fill);
|
---|
| 567 | else
|
---|
| 568 | // Before.
|
---|
| 569 | __res.insert(0, __width - __len, __fill);
|
---|
| 570 | __len = __width;
|
---|
| 571 | }
|
---|
| 572 |
|
---|
| 573 | // Write resulting, fully-formatted string to output iterator.
|
---|
| 574 | __s = std::__write(__s, __res.data(), __len);
|
---|
| 575 | }
|
---|
| 576 | __io.width(0);
|
---|
| 577 | return __s;
|
---|
| 578 | }
|
---|
| 579 |
|
---|
| 580 | #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
|
---|
| 581 | && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
|
---|
| 582 | template<typename _CharT, typename _OutIter>
|
---|
| 583 | _OutIter
|
---|
| 584 | money_put<_CharT, _OutIter>::
|
---|
| 585 | __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
|
---|
| 586 | double __units) const
|
---|
| 587 | { return this->do_put(__s, __intl, __io, __fill, (long double) __units); }
|
---|
| 588 | #endif
|
---|
| 589 |
|
---|
| 590 | template<typename _CharT, typename _OutIter>
|
---|
| 591 | _OutIter
|
---|
| 592 | money_put<_CharT, _OutIter>::
|
---|
| 593 | do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
|
---|
| 594 | long double __units) const
|
---|
| 595 | {
|
---|
| 596 | const locale __loc = __io.getloc();
|
---|
| 597 | const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
|
---|
| 598 | #if _GLIBCXX_USE_C99_STDIO
|
---|
| 599 | // First try a buffer perhaps big enough.
|
---|
| 600 | int __cs_size = 64;
|
---|
| 601 | char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
|
---|
| 602 | // _GLIBCXX_RESOLVE_LIB_DEFECTS
|
---|
| 603 | // 328. Bad sprintf format modifier in money_put<>::do_put()
|
---|
| 604 | int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
|
---|
| 605 | "%.*Lf", 0, __units);
|
---|
| 606 | // If the buffer was not large enough, try again with the correct size.
|
---|
| 607 | if (__len >= __cs_size)
|
---|
| 608 | {
|
---|
| 609 | __cs_size = __len + 1;
|
---|
| 610 | __cs = static_cast<char*>(__builtin_alloca(__cs_size));
|
---|
| 611 | __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
|
---|
| 612 | "%.*Lf", 0, __units);
|
---|
| 613 | }
|
---|
| 614 | #else
|
---|
| 615 | // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
|
---|
| 616 | const int __cs_size =
|
---|
| 617 | __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
|
---|
| 618 | char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
|
---|
| 619 | int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf",
|
---|
| 620 | 0, __units);
|
---|
| 621 | #endif
|
---|
| 622 | string_type __digits(__len, char_type());
|
---|
| 623 | __ctype.widen(__cs, __cs + __len, &__digits[0]);
|
---|
| 624 | return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
|
---|
| 625 | : _M_insert<false>(__s, __io, __fill, __digits);
|
---|
| 626 | }
|
---|
| 627 |
|
---|
| 628 | template<typename _CharT, typename _OutIter>
|
---|
| 629 | _OutIter
|
---|
| 630 | money_put<_CharT, _OutIter>::
|
---|
| 631 | do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
|
---|
| 632 | const string_type& __digits) const
|
---|
| 633 | { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
|
---|
| 634 | : _M_insert<false>(__s, __io, __fill, __digits); }
|
---|
| 635 |
|
---|
| 636 | #if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
|
---|
| 637 | && defined __LONG_DOUBLE_IEEE128__
|
---|
| 638 | template<typename _CharT, typename _OutIter>
|
---|
| 639 | _OutIter
|
---|
| 640 | money_put<_CharT, _OutIter>::
|
---|
| 641 | __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
|
---|
| 642 | __ibm128 __units) const
|
---|
| 643 | {
|
---|
| 644 | const locale __loc = __io.getloc();
|
---|
| 645 | const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
|
---|
| 646 | #if _GLIBCXX_USE_C99_STDIO
|
---|
| 647 | // First try a buffer perhaps big enough.
|
---|
| 648 | int __cs_size = 64;
|
---|
| 649 | char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
|
---|
| 650 | // _GLIBCXX_RESOLVE_LIB_DEFECTS
|
---|
| 651 | // 328. Bad sprintf format modifier in money_put<>::do_put()
|
---|
| 652 | int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
|
---|
| 653 | "%.*Lf", 0, __units);
|
---|
| 654 | // If the buffer was not large enough, try again with the correct size.
|
---|
| 655 | if (__len >= __cs_size)
|
---|
| 656 | {
|
---|
| 657 | __cs_size = __len + 1;
|
---|
| 658 | __cs = static_cast<char*>(__builtin_alloca(__cs_size));
|
---|
| 659 | __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
|
---|
| 660 | "%.*Lf", 0, __units);
|
---|
| 661 | }
|
---|
| 662 | #else
|
---|
| 663 | // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
|
---|
| 664 | const int __cs_size =
|
---|
| 665 | __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
|
---|
| 666 | char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
|
---|
| 667 | int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf",
|
---|
| 668 | 0, __units);
|
---|
| 669 | #endif
|
---|
| 670 | string_type __digits(__len, char_type());
|
---|
| 671 | __ctype.widen(__cs, __cs + __len, &__digits[0]);
|
---|
| 672 | return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
|
---|
| 673 | : _M_insert<false>(__s, __io, __fill, __digits);
|
---|
| 674 | }
|
---|
| 675 | #endif
|
---|
| 676 |
|
---|
| 677 | _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
|
---|
| 678 |
|
---|
| 679 | // NB: Not especially useful. Without an ios_base object or some
|
---|
| 680 | // kind of locale reference, we are left clawing at the air where
|
---|
| 681 | // the side of the mountain used to be...
|
---|
| 682 | template<typename _CharT, typename _InIter>
|
---|
| 683 | time_base::dateorder
|
---|
| 684 | time_get<_CharT, _InIter>::do_date_order() const
|
---|
| 685 | { return time_base::no_order; }
|
---|
| 686 |
|
---|
| 687 | // Expand a strftime format string and parse it. E.g., do_get_date() may
|
---|
| 688 | // pass %m/%d/%Y => extracted characters.
|
---|
| 689 | template<typename _CharT, typename _InIter>
|
---|
| 690 | _InIter
|
---|
| 691 | time_get<_CharT, _InIter>::
|
---|
| 692 | _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
|
---|
| 693 | ios_base::iostate& __err, tm* __tm,
|
---|
| 694 | const _CharT* __format) const
|
---|
| 695 | {
|
---|
| 696 | const locale& __loc = __io._M_getloc();
|
---|
| 697 | const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
|
---|
| 698 | const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
|
---|
| 699 | const size_t __len = char_traits<_CharT>::length(__format);
|
---|
| 700 |
|
---|
| 701 | ios_base::iostate __tmperr = ios_base::goodbit;
|
---|
| 702 | size_t __i = 0;
|
---|
| 703 | for (; __beg != __end && __i < __len && !__tmperr; ++__i)
|
---|
| 704 | {
|
---|
| 705 | if (__ctype.narrow(__format[__i], 0) == '%')
|
---|
| 706 | {
|
---|
| 707 | // Verify valid formatting code, attempt to extract.
|
---|
| 708 | char __c = __ctype.narrow(__format[++__i], 0);
|
---|
| 709 | int __mem = 0;
|
---|
| 710 | if (__c == 'E' || __c == 'O')
|
---|
| 711 | __c = __ctype.narrow(__format[++__i], 0);
|
---|
| 712 | switch (__c)
|
---|
| 713 | {
|
---|
| 714 | const char* __cs;
|
---|
| 715 | _CharT __wcs[10];
|
---|
| 716 | case 'a':
|
---|
| 717 | // Abbreviated weekday name [tm_wday]
|
---|
| 718 | const char_type* __days1[7];
|
---|
| 719 | __tp._M_days_abbreviated(__days1);
|
---|
| 720 | __beg = _M_extract_name(__beg, __end, __mem, __days1,
|
---|
| 721 | 7, __io, __tmperr);
|
---|
| 722 | if (!__tmperr)
|
---|
| 723 | __tm->tm_wday = __mem;
|
---|
| 724 | break;
|
---|
| 725 | case 'A':
|
---|
| 726 | // Weekday name [tm_wday].
|
---|
| 727 | const char_type* __days2[7];
|
---|
| 728 | __tp._M_days(__days2);
|
---|
| 729 | __beg = _M_extract_name(__beg, __end, __mem, __days2,
|
---|
| 730 | 7, __io, __tmperr);
|
---|
| 731 | if (!__tmperr)
|
---|
| 732 | __tm->tm_wday = __mem;
|
---|
| 733 | break;
|
---|
| 734 | case 'h':
|
---|
| 735 | case 'b':
|
---|
| 736 | // Abbreviated month name [tm_mon]
|
---|
| 737 | const char_type* __months1[12];
|
---|
| 738 | __tp._M_months_abbreviated(__months1);
|
---|
| 739 | __beg = _M_extract_name(__beg, __end, __mem,
|
---|
| 740 | __months1, 12, __io, __tmperr);
|
---|
| 741 | if (!__tmperr)
|
---|
| 742 | __tm->tm_mon = __mem;
|
---|
| 743 | break;
|
---|
| 744 | case 'B':
|
---|
| 745 | // Month name [tm_mon].
|
---|
| 746 | const char_type* __months2[12];
|
---|
| 747 | __tp._M_months(__months2);
|
---|
| 748 | __beg = _M_extract_name(__beg, __end, __mem,
|
---|
| 749 | __months2, 12, __io, __tmperr);
|
---|
| 750 | if (!__tmperr)
|
---|
| 751 | __tm->tm_mon = __mem;
|
---|
| 752 | break;
|
---|
| 753 | case 'c':
|
---|
| 754 | // Default time and date representation.
|
---|
| 755 | const char_type* __dt[2];
|
---|
| 756 | __tp._M_date_time_formats(__dt);
|
---|
| 757 | __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
|
---|
| 758 | __tm, __dt[0]);
|
---|
| 759 | break;
|
---|
| 760 | case 'd':
|
---|
| 761 | // Day [01, 31]. [tm_mday]
|
---|
| 762 | __beg = _M_extract_num(__beg, __end, __mem, 1, 31, 2,
|
---|
| 763 | __io, __tmperr);
|
---|
| 764 | if (!__tmperr)
|
---|
| 765 | __tm->tm_mday = __mem;
|
---|
| 766 | break;
|
---|
| 767 | case 'e':
|
---|
| 768 | // Day [1, 31], with single digits preceded by
|
---|
| 769 | // space. [tm_mday]
|
---|
| 770 | if (__ctype.is(ctype_base::space, *__beg))
|
---|
| 771 | __beg = _M_extract_num(++__beg, __end, __mem, 1, 9,
|
---|
| 772 | 1, __io, __tmperr);
|
---|
| 773 | else
|
---|
| 774 | __beg = _M_extract_num(__beg, __end, __mem, 10, 31,
|
---|
| 775 | 2, __io, __tmperr);
|
---|
| 776 | if (!__tmperr)
|
---|
| 777 | __tm->tm_mday = __mem;
|
---|
| 778 | break;
|
---|
| 779 | case 'D':
|
---|
| 780 | // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
|
---|
| 781 | __cs = "%m/%d/%y";
|
---|
| 782 | __ctype.widen(__cs, __cs + 9, __wcs);
|
---|
| 783 | __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
|
---|
| 784 | __tm, __wcs);
|
---|
| 785 | break;
|
---|
| 786 | case 'H':
|
---|
| 787 | // Hour [00, 23]. [tm_hour]
|
---|
| 788 | __beg = _M_extract_num(__beg, __end, __mem, 0, 23, 2,
|
---|
| 789 | __io, __tmperr);
|
---|
| 790 | if (!__tmperr)
|
---|
| 791 | __tm->tm_hour = __mem;
|
---|
| 792 | break;
|
---|
| 793 | case 'I':
|
---|
| 794 | // Hour [01, 12]. [tm_hour]
|
---|
| 795 | __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
|
---|
| 796 | __io, __tmperr);
|
---|
| 797 | if (!__tmperr)
|
---|
| 798 | __tm->tm_hour = __mem;
|
---|
| 799 | break;
|
---|
| 800 | case 'm':
|
---|
| 801 | // Month [01, 12]. [tm_mon]
|
---|
| 802 | __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
|
---|
| 803 | __io, __tmperr);
|
---|
| 804 | if (!__tmperr)
|
---|
| 805 | __tm->tm_mon = __mem - 1;
|
---|
| 806 | break;
|
---|
| 807 | case 'M':
|
---|
| 808 | // Minute [00, 59]. [tm_min]
|
---|
| 809 | __beg = _M_extract_num(__beg, __end, __mem, 0, 59, 2,
|
---|
| 810 | __io, __tmperr);
|
---|
| 811 | if (!__tmperr)
|
---|
| 812 | __tm->tm_min = __mem;
|
---|
| 813 | break;
|
---|
| 814 | case 'n':
|
---|
| 815 | if (__ctype.narrow(*__beg, 0) == '\n')
|
---|
| 816 | ++__beg;
|
---|
| 817 | else
|
---|
| 818 | __tmperr |= ios_base::failbit;
|
---|
| 819 | break;
|
---|
| 820 | case 'R':
|
---|
| 821 | // Equivalent to (%H:%M).
|
---|
| 822 | __cs = "%H:%M";
|
---|
| 823 | __ctype.widen(__cs, __cs + 6, __wcs);
|
---|
| 824 | __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
|
---|
| 825 | __tm, __wcs);
|
---|
| 826 | break;
|
---|
| 827 | case 'S':
|
---|
| 828 | // Seconds. [tm_sec]
|
---|
| 829 | // [00, 60] in C99 (one leap-second), [00, 61] in C89.
|
---|
| 830 | #if _GLIBCXX_USE_C99
|
---|
| 831 | __beg = _M_extract_num(__beg, __end, __mem, 0, 60, 2,
|
---|
| 832 | #else
|
---|
| 833 | __beg = _M_extract_num(__beg, __end, __mem, 0, 61, 2,
|
---|
| 834 | #endif
|
---|
| 835 | __io, __tmperr);
|
---|
| 836 | if (!__tmperr)
|
---|
| 837 | __tm->tm_sec = __mem;
|
---|
| 838 | break;
|
---|
| 839 | case 't':
|
---|
| 840 | if (__ctype.narrow(*__beg, 0) == '\t')
|
---|
| 841 | ++__beg;
|
---|
| 842 | else
|
---|
| 843 | __tmperr |= ios_base::failbit;
|
---|
| 844 | break;
|
---|
| 845 | case 'T':
|
---|
| 846 | // Equivalent to (%H:%M:%S).
|
---|
| 847 | __cs = "%H:%M:%S";
|
---|
| 848 | __ctype.widen(__cs, __cs + 9, __wcs);
|
---|
| 849 | __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
|
---|
| 850 | __tm, __wcs);
|
---|
| 851 | break;
|
---|
| 852 | case 'x':
|
---|
| 853 | // Locale's date.
|
---|
| 854 | const char_type* __dates[2];
|
---|
| 855 | __tp._M_date_formats(__dates);
|
---|
| 856 | __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
|
---|
| 857 | __tm, __dates[0]);
|
---|
| 858 | break;
|
---|
| 859 | case 'X':
|
---|
| 860 | // Locale's time.
|
---|
| 861 | const char_type* __times[2];
|
---|
| 862 | __tp._M_time_formats(__times);
|
---|
| 863 | __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
|
---|
| 864 | __tm, __times[0]);
|
---|
| 865 | break;
|
---|
| 866 | case 'y':
|
---|
| 867 | case 'C': // C99
|
---|
| 868 | // Two digit year.
|
---|
| 869 | case 'Y':
|
---|
| 870 | // Year [1900).
|
---|
| 871 | // NB: We parse either two digits, implicitly years since
|
---|
| 872 | // 1900, or 4 digits, full year. In both cases we can
|
---|
| 873 | // reconstruct [tm_year]. See also libstdc++/26701.
|
---|
| 874 | __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
|
---|
| 875 | __io, __tmperr);
|
---|
| 876 | if (!__tmperr)
|
---|
| 877 | __tm->tm_year = __mem < 0 ? __mem + 100 : __mem - 1900;
|
---|
| 878 | break;
|
---|
| 879 | case 'Z':
|
---|
| 880 | // Timezone info.
|
---|
| 881 | if (__ctype.is(ctype_base::upper, *__beg))
|
---|
| 882 | {
|
---|
| 883 | int __tmp;
|
---|
| 884 | __beg = _M_extract_name(__beg, __end, __tmp,
|
---|
| 885 | __timepunct_cache<_CharT>::_S_timezones,
|
---|
| 886 | 14, __io, __tmperr);
|
---|
| 887 |
|
---|
| 888 | // GMT requires special effort.
|
---|
| 889 | if (__beg != __end && !__tmperr && __tmp == 0
|
---|
| 890 | && (*__beg == __ctype.widen('-')
|
---|
| 891 | || *__beg == __ctype.widen('+')))
|
---|
| 892 | {
|
---|
| 893 | __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
|
---|
| 894 | __io, __tmperr);
|
---|
| 895 | __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
|
---|
| 896 | __io, __tmperr);
|
---|
| 897 | }
|
---|
| 898 | }
|
---|
| 899 | else
|
---|
| 900 | __tmperr |= ios_base::failbit;
|
---|
| 901 | break;
|
---|
| 902 | default:
|
---|
| 903 | // Not recognized.
|
---|
| 904 | __tmperr |= ios_base::failbit;
|
---|
| 905 | }
|
---|
| 906 | }
|
---|
| 907 | else
|
---|
| 908 | {
|
---|
| 909 | // Verify format and input match, extract and discard.
|
---|
| 910 | if (__format[__i] == *__beg)
|
---|
| 911 | ++__beg;
|
---|
| 912 | else
|
---|
| 913 | __tmperr |= ios_base::failbit;
|
---|
| 914 | }
|
---|
| 915 | }
|
---|
| 916 |
|
---|
| 917 | if (__tmperr || __i != __len)
|
---|
| 918 | __err |= ios_base::failbit;
|
---|
| 919 |
|
---|
| 920 | return __beg;
|
---|
| 921 | }
|
---|
| 922 |
|
---|
| 923 | template<typename _CharT, typename _InIter>
|
---|
| 924 | _InIter
|
---|
| 925 | time_get<_CharT, _InIter>::
|
---|
| 926 | _M_extract_num(iter_type __beg, iter_type __end, int& __member,
|
---|
| 927 | int __min, int __max, size_t __len,
|
---|
| 928 | ios_base& __io, ios_base::iostate& __err) const
|
---|
| 929 | {
|
---|
| 930 | const locale& __loc = __io._M_getloc();
|
---|
| 931 | const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
|
---|
| 932 |
|
---|
| 933 | // As-is works for __len = 1, 2, 4, the values actually used.
|
---|
| 934 | int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
|
---|
| 935 |
|
---|
| 936 | ++__min;
|
---|
| 937 | size_t __i = 0;
|
---|
| 938 | int __value = 0;
|
---|
| 939 | for (; __beg != __end && __i < __len; ++__beg, (void)++__i)
|
---|
| 940 | {
|
---|
| 941 | const char __c = __ctype.narrow(*__beg, '*');
|
---|
| 942 | if (__c >= '0' && __c <= '9')
|
---|
| 943 | {
|
---|
| 944 | __value = __value * 10 + (__c - '0');
|
---|
| 945 | const int __valuec = __value * __mult;
|
---|
| 946 | if (__valuec > __max || __valuec + __mult < __min)
|
---|
| 947 | break;
|
---|
| 948 | __mult /= 10;
|
---|
| 949 | }
|
---|
| 950 | else
|
---|
| 951 | break;
|
---|
| 952 | }
|
---|
| 953 | if (__i == __len)
|
---|
| 954 | __member = __value;
|
---|
| 955 | // Special encoding for do_get_year, 'y', and 'Y' above.
|
---|
| 956 | else if (__len == 4 && __i == 2)
|
---|
| 957 | __member = __value - 100;
|
---|
| 958 | else
|
---|
| 959 | __err |= ios_base::failbit;
|
---|
| 960 |
|
---|
| 961 | return __beg;
|
---|
| 962 | }
|
---|
| 963 |
|
---|
| 964 | // Assumptions:
|
---|
| 965 | // All elements in __names are unique.
|
---|
| 966 | template<typename _CharT, typename _InIter>
|
---|
| 967 | _InIter
|
---|
| 968 | time_get<_CharT, _InIter>::
|
---|
| 969 | _M_extract_name(iter_type __beg, iter_type __end, int& __member,
|
---|
| 970 | const _CharT** __names, size_t __indexlen,
|
---|
| 971 | ios_base& __io, ios_base::iostate& __err) const
|
---|
| 972 | {
|
---|
| 973 | typedef char_traits<_CharT> __traits_type;
|
---|
| 974 | const locale& __loc = __io._M_getloc();
|
---|
| 975 | const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
|
---|
| 976 |
|
---|
| 977 | int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
|
---|
| 978 | * __indexlen));
|
---|
| 979 | size_t __nmatches = 0;
|
---|
| 980 | size_t __pos = 0;
|
---|
| 981 | bool __testvalid = true;
|
---|
| 982 | const char_type* __name;
|
---|
| 983 |
|
---|
| 984 | // Look for initial matches.
|
---|
| 985 | // NB: Some of the locale data is in the form of all lowercase
|
---|
| 986 | // names, and some is in the form of initially-capitalized
|
---|
| 987 | // names. Look for both.
|
---|
| 988 | if (__beg != __end)
|
---|
| 989 | {
|
---|
| 990 | const char_type __c = *__beg;
|
---|
| 991 | for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
|
---|
| 992 | if (__c == __names[__i1][0]
|
---|
| 993 | || __c == __ctype.toupper(__names[__i1][0]))
|
---|
| 994 | __matches[__nmatches++] = __i1;
|
---|
| 995 | }
|
---|
| 996 |
|
---|
| 997 | while (__nmatches > 1)
|
---|
| 998 | {
|
---|
| 999 | // Find smallest matching string.
|
---|
| 1000 | size_t __minlen = __traits_type::length(__names[__matches[0]]);
|
---|
| 1001 | for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
|
---|
| 1002 | __minlen = std::min(__minlen,
|
---|
| 1003 | __traits_type::length(__names[__matches[__i2]]));
|
---|
| 1004 | ++__beg;
|
---|
| 1005 | ++__pos;
|
---|
| 1006 | if (__pos < __minlen && __beg != __end)
|
---|
| 1007 | for (size_t __i3 = 0; __i3 < __nmatches;)
|
---|
| 1008 | {
|
---|
| 1009 | __name = __names[__matches[__i3]];
|
---|
| 1010 | if (!(__name[__pos] == *__beg))
|
---|
| 1011 | __matches[__i3] = __matches[--__nmatches];
|
---|
| 1012 | else
|
---|
| 1013 | ++__i3;
|
---|
| 1014 | }
|
---|
| 1015 | else
|
---|
| 1016 | break;
|
---|
| 1017 | }
|
---|
| 1018 |
|
---|
| 1019 | if (__nmatches == 1)
|
---|
| 1020 | {
|
---|
| 1021 | // Make sure found name is completely extracted.
|
---|
| 1022 | ++__beg;
|
---|
| 1023 | ++__pos;
|
---|
| 1024 | __name = __names[__matches[0]];
|
---|
| 1025 | const size_t __len = __traits_type::length(__name);
|
---|
| 1026 | while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
|
---|
| 1027 | ++__beg, (void)++__pos;
|
---|
| 1028 |
|
---|
| 1029 | if (__len == __pos)
|
---|
| 1030 | __member = __matches[0];
|
---|
| 1031 | else
|
---|
| 1032 | __testvalid = false;
|
---|
| 1033 | }
|
---|
| 1034 | else
|
---|
| 1035 | __testvalid = false;
|
---|
| 1036 | if (!__testvalid)
|
---|
| 1037 | __err |= ios_base::failbit;
|
---|
| 1038 |
|
---|
| 1039 | return __beg;
|
---|
| 1040 | }
|
---|
| 1041 |
|
---|
| 1042 | template<typename _CharT, typename _InIter>
|
---|
| 1043 | _InIter
|
---|
| 1044 | time_get<_CharT, _InIter>::
|
---|
| 1045 | _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
|
---|
| 1046 | const _CharT** __names, size_t __indexlen,
|
---|
| 1047 | ios_base& __io, ios_base::iostate& __err) const
|
---|
| 1048 | {
|
---|
| 1049 | typedef char_traits<_CharT> __traits_type;
|
---|
| 1050 | const locale& __loc = __io._M_getloc();
|
---|
| 1051 | const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
|
---|
| 1052 |
|
---|
| 1053 | int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
|
---|
| 1054 | * __indexlen));
|
---|
| 1055 | size_t __nmatches = 0;
|
---|
| 1056 | size_t* __matches_lengths = 0;
|
---|
| 1057 | size_t __pos = 0;
|
---|
| 1058 |
|
---|
| 1059 | if (__beg != __end)
|
---|
| 1060 | {
|
---|
| 1061 | const char_type __c = *__beg;
|
---|
| 1062 | for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
|
---|
| 1063 | if (__c == __names[__i][0]
|
---|
| 1064 | || __c == __ctype.toupper(__names[__i][0]))
|
---|
| 1065 | __matches[__nmatches++] = __i;
|
---|
| 1066 | }
|
---|
| 1067 |
|
---|
| 1068 | if (__nmatches)
|
---|
| 1069 | {
|
---|
| 1070 | ++__beg;
|
---|
| 1071 | ++__pos;
|
---|
| 1072 |
|
---|
| 1073 | __matches_lengths
|
---|
| 1074 | = static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
|
---|
| 1075 | * __nmatches));
|
---|
| 1076 | for (size_t __i = 0; __i < __nmatches; ++__i)
|
---|
| 1077 | __matches_lengths[__i]
|
---|
| 1078 | = __traits_type::length(__names[__matches[__i]]);
|
---|
| 1079 | }
|
---|
| 1080 |
|
---|
| 1081 | for (; __beg != __end; ++__beg, (void)++__pos)
|
---|
| 1082 | {
|
---|
| 1083 | size_t __nskipped = 0;
|
---|
| 1084 | const char_type __c = *__beg;
|
---|
| 1085 | for (size_t __i = 0; __i < __nmatches;)
|
---|
| 1086 | {
|
---|
| 1087 | const char_type* __name = __names[__matches[__i]];
|
---|
| 1088 | if (__pos >= __matches_lengths[__i])
|
---|
| 1089 | ++__nskipped, ++__i;
|
---|
| 1090 | else if (!(__name[__pos] == __c))
|
---|
| 1091 | {
|
---|
| 1092 | --__nmatches;
|
---|
| 1093 | __matches[__i] = __matches[__nmatches];
|
---|
| 1094 | __matches_lengths[__i] = __matches_lengths[__nmatches];
|
---|
| 1095 | }
|
---|
| 1096 | else
|
---|
| 1097 | ++__i;
|
---|
| 1098 | }
|
---|
| 1099 | if (__nskipped == __nmatches)
|
---|
| 1100 | break;
|
---|
| 1101 | }
|
---|
| 1102 |
|
---|
| 1103 | if ((__nmatches == 1 && __matches_lengths[0] == __pos)
|
---|
| 1104 | || (__nmatches == 2 && (__matches_lengths[0] == __pos
|
---|
| 1105 | || __matches_lengths[1] == __pos)))
|
---|
| 1106 | __member = (__matches[0] >= (int)__indexlen
|
---|
| 1107 | ? __matches[0] - (int)__indexlen : __matches[0]);
|
---|
| 1108 | else
|
---|
| 1109 | __err |= ios_base::failbit;
|
---|
| 1110 |
|
---|
| 1111 | return __beg;
|
---|
| 1112 | }
|
---|
| 1113 |
|
---|
| 1114 | template<typename _CharT, typename _InIter>
|
---|
| 1115 | _InIter
|
---|
| 1116 | time_get<_CharT, _InIter>::
|
---|
| 1117 | do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
|
---|
| 1118 | ios_base::iostate& __err, tm* __tm) const
|
---|
| 1119 | {
|
---|
| 1120 | const locale& __loc = __io._M_getloc();
|
---|
| 1121 | const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
|
---|
| 1122 | const char_type* __times[2];
|
---|
| 1123 | __tp._M_time_formats(__times);
|
---|
| 1124 | __beg = _M_extract_via_format(__beg, __end, __io, __err,
|
---|
| 1125 | __tm, __times[0]);
|
---|
| 1126 | if (__beg == __end)
|
---|
| 1127 | __err |= ios_base::eofbit;
|
---|
| 1128 | return __beg;
|
---|
| 1129 | }
|
---|
| 1130 |
|
---|
| 1131 | template<typename _CharT, typename _InIter>
|
---|
| 1132 | _InIter
|
---|
| 1133 | time_get<_CharT, _InIter>::
|
---|
| 1134 | do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
|
---|
| 1135 | ios_base::iostate& __err, tm* __tm) const
|
---|
| 1136 | {
|
---|
| 1137 | const locale& __loc = __io._M_getloc();
|
---|
| 1138 | const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
|
---|
| 1139 | const char_type* __dates[2];
|
---|
| 1140 | __tp._M_date_formats(__dates);
|
---|
| 1141 | __beg = _M_extract_via_format(__beg, __end, __io, __err,
|
---|
| 1142 | __tm, __dates[0]);
|
---|
| 1143 | if (__beg == __end)
|
---|
| 1144 | __err |= ios_base::eofbit;
|
---|
| 1145 | return __beg;
|
---|
| 1146 | }
|
---|
| 1147 |
|
---|
| 1148 | template<typename _CharT, typename _InIter>
|
---|
| 1149 | _InIter
|
---|
| 1150 | time_get<_CharT, _InIter>::
|
---|
| 1151 | do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
|
---|
| 1152 | ios_base::iostate& __err, tm* __tm) const
|
---|
| 1153 | {
|
---|
| 1154 | const locale& __loc = __io._M_getloc();
|
---|
| 1155 | const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
|
---|
| 1156 | const char_type* __days[14];
|
---|
| 1157 | __tp._M_days_abbreviated(__days);
|
---|
| 1158 | __tp._M_days(__days + 7);
|
---|
| 1159 | int __tmpwday;
|
---|
| 1160 | ios_base::iostate __tmperr = ios_base::goodbit;
|
---|
| 1161 |
|
---|
| 1162 | __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7,
|
---|
| 1163 | __io, __tmperr);
|
---|
| 1164 | if (!__tmperr)
|
---|
| 1165 | __tm->tm_wday = __tmpwday;
|
---|
| 1166 | else
|
---|
| 1167 | __err |= ios_base::failbit;
|
---|
| 1168 |
|
---|
| 1169 | if (__beg == __end)
|
---|
| 1170 | __err |= ios_base::eofbit;
|
---|
| 1171 | return __beg;
|
---|
| 1172 | }
|
---|
| 1173 |
|
---|
| 1174 | template<typename _CharT, typename _InIter>
|
---|
| 1175 | _InIter
|
---|
| 1176 | time_get<_CharT, _InIter>::
|
---|
| 1177 | do_get_monthname(iter_type __beg, iter_type __end,
|
---|
| 1178 | ios_base& __io, ios_base::iostate& __err, tm* __tm) const
|
---|
| 1179 | {
|
---|
| 1180 | const locale& __loc = __io._M_getloc();
|
---|
| 1181 | const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
|
---|
| 1182 | const char_type* __months[24];
|
---|
| 1183 | __tp._M_months_abbreviated(__months);
|
---|
| 1184 | __tp._M_months(__months + 12);
|
---|
| 1185 | int __tmpmon;
|
---|
| 1186 | ios_base::iostate __tmperr = ios_base::goodbit;
|
---|
| 1187 |
|
---|
| 1188 | __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12,
|
---|
| 1189 | __io, __tmperr);
|
---|
| 1190 | if (!__tmperr)
|
---|
| 1191 | __tm->tm_mon = __tmpmon;
|
---|
| 1192 | else
|
---|
| 1193 | __err |= ios_base::failbit;
|
---|
| 1194 |
|
---|
| 1195 | if (__beg == __end)
|
---|
| 1196 | __err |= ios_base::eofbit;
|
---|
| 1197 | return __beg;
|
---|
| 1198 | }
|
---|
| 1199 |
|
---|
| 1200 | template<typename _CharT, typename _InIter>
|
---|
| 1201 | _InIter
|
---|
| 1202 | time_get<_CharT, _InIter>::
|
---|
| 1203 | do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
|
---|
| 1204 | ios_base::iostate& __err, tm* __tm) const
|
---|
| 1205 | {
|
---|
| 1206 | int __tmpyear;
|
---|
| 1207 | ios_base::iostate __tmperr = ios_base::goodbit;
|
---|
| 1208 |
|
---|
| 1209 | __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 9999, 4,
|
---|
| 1210 | __io, __tmperr);
|
---|
| 1211 | if (!__tmperr)
|
---|
| 1212 | __tm->tm_year = __tmpyear < 0 ? __tmpyear + 100 : __tmpyear - 1900;
|
---|
| 1213 | else
|
---|
| 1214 | __err |= ios_base::failbit;
|
---|
| 1215 |
|
---|
| 1216 | if (__beg == __end)
|
---|
| 1217 | __err |= ios_base::eofbit;
|
---|
| 1218 | return __beg;
|
---|
| 1219 | }
|
---|
| 1220 |
|
---|
| 1221 | #if __cplusplus >= 201103L
|
---|
| 1222 | template<typename _CharT, typename _InIter>
|
---|
| 1223 | inline
|
---|
| 1224 | _InIter
|
---|
| 1225 | time_get<_CharT, _InIter>::
|
---|
| 1226 | get(iter_type __s, iter_type __end, ios_base& __io,
|
---|
| 1227 | ios_base::iostate& __err, tm* __tm, const char_type* __fmt,
|
---|
| 1228 | const char_type* __fmtend) const
|
---|
| 1229 | {
|
---|
| 1230 | const locale& __loc = __io._M_getloc();
|
---|
| 1231 | ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
|
---|
| 1232 | __err = ios_base::goodbit;
|
---|
| 1233 | while (__fmt != __fmtend &&
|
---|
| 1234 | __err == ios_base::goodbit)
|
---|
| 1235 | {
|
---|
| 1236 | if (__s == __end)
|
---|
| 1237 | {
|
---|
| 1238 | __err = ios_base::eofbit | ios_base::failbit;
|
---|
| 1239 | break;
|
---|
| 1240 | }
|
---|
| 1241 | else if (__ctype.narrow(*__fmt, 0) == '%')
|
---|
| 1242 | {
|
---|
| 1243 | char __format;
|
---|
| 1244 | char __mod = 0;
|
---|
| 1245 | if (++__fmt == __fmtend)
|
---|
| 1246 | {
|
---|
| 1247 | __err = ios_base::failbit;
|
---|
| 1248 | break;
|
---|
| 1249 | }
|
---|
| 1250 | const char __c = __ctype.narrow(*__fmt, 0);
|
---|
| 1251 | if (__c != 'E' && __c != 'O')
|
---|
| 1252 | __format = __c;
|
---|
| 1253 | else if (++__fmt != __fmtend)
|
---|
| 1254 | {
|
---|
| 1255 | __mod = __c;
|
---|
| 1256 | __format = __ctype.narrow(*__fmt, 0);
|
---|
| 1257 | }
|
---|
| 1258 | else
|
---|
| 1259 | {
|
---|
| 1260 | __err = ios_base::failbit;
|
---|
| 1261 | break;
|
---|
| 1262 | }
|
---|
| 1263 | __s = this->do_get(__s, __end, __io, __err, __tm, __format,
|
---|
| 1264 | __mod);
|
---|
| 1265 | ++__fmt;
|
---|
| 1266 | }
|
---|
| 1267 | else if (__ctype.is(ctype_base::space, *__fmt))
|
---|
| 1268 | {
|
---|
| 1269 | ++__fmt;
|
---|
| 1270 | while (__fmt != __fmtend &&
|
---|
| 1271 | __ctype.is(ctype_base::space, *__fmt))
|
---|
| 1272 | ++__fmt;
|
---|
| 1273 |
|
---|
| 1274 | while (__s != __end &&
|
---|
| 1275 | __ctype.is(ctype_base::space, *__s))
|
---|
| 1276 | ++__s;
|
---|
| 1277 | }
|
---|
| 1278 | // TODO real case-insensitive comparison
|
---|
| 1279 | else if (__ctype.tolower(*__s) == __ctype.tolower(*__fmt) ||
|
---|
| 1280 | __ctype.toupper(*__s) == __ctype.toupper(*__fmt))
|
---|
| 1281 | {
|
---|
| 1282 | ++__s;
|
---|
| 1283 | ++__fmt;
|
---|
| 1284 | }
|
---|
| 1285 | else
|
---|
| 1286 | {
|
---|
| 1287 | __err = ios_base::failbit;
|
---|
| 1288 | break;
|
---|
| 1289 | }
|
---|
| 1290 | }
|
---|
| 1291 | return __s;
|
---|
| 1292 | }
|
---|
| 1293 |
|
---|
| 1294 | template<typename _CharT, typename _InIter>
|
---|
| 1295 | inline
|
---|
| 1296 | _InIter
|
---|
| 1297 | time_get<_CharT, _InIter>::
|
---|
| 1298 | do_get(iter_type __beg, iter_type __end, ios_base& __io,
|
---|
| 1299 | ios_base::iostate& __err, tm* __tm,
|
---|
| 1300 | char __format, char __mod) const
|
---|
| 1301 | {
|
---|
| 1302 | const locale& __loc = __io._M_getloc();
|
---|
| 1303 | ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
|
---|
| 1304 | __err = ios_base::goodbit;
|
---|
| 1305 |
|
---|
| 1306 | char_type __fmt[4];
|
---|
| 1307 | __fmt[0] = __ctype.widen('%');
|
---|
| 1308 | if (!__mod)
|
---|
| 1309 | {
|
---|
| 1310 | __fmt[1] = __format;
|
---|
| 1311 | __fmt[2] = char_type();
|
---|
| 1312 | }
|
---|
| 1313 | else
|
---|
| 1314 | {
|
---|
| 1315 | __fmt[1] = __mod;
|
---|
| 1316 | __fmt[2] = __format;
|
---|
| 1317 | __fmt[3] = char_type();
|
---|
| 1318 | }
|
---|
| 1319 |
|
---|
| 1320 | __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, __fmt);
|
---|
| 1321 | if (__beg == __end)
|
---|
| 1322 | __err |= ios_base::eofbit;
|
---|
| 1323 | return __beg;
|
---|
| 1324 | }
|
---|
| 1325 |
|
---|
| 1326 | #endif // __cplusplus >= 201103L
|
---|
| 1327 |
|
---|
| 1328 | template<typename _CharT, typename _OutIter>
|
---|
| 1329 | _OutIter
|
---|
| 1330 | time_put<_CharT, _OutIter>::
|
---|
| 1331 | put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
|
---|
| 1332 | const _CharT* __beg, const _CharT* __end) const
|
---|
| 1333 | {
|
---|
| 1334 | const locale& __loc = __io._M_getloc();
|
---|
| 1335 | ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
|
---|
| 1336 | for (; __beg != __end; ++__beg)
|
---|
| 1337 | if (__ctype.narrow(*__beg, 0) != '%')
|
---|
| 1338 | {
|
---|
| 1339 | *__s = *__beg;
|
---|
| 1340 | ++__s;
|
---|
| 1341 | }
|
---|
| 1342 | else if (++__beg != __end)
|
---|
| 1343 | {
|
---|
| 1344 | char __format;
|
---|
| 1345 | char __mod = 0;
|
---|
| 1346 | const char __c = __ctype.narrow(*__beg, 0);
|
---|
| 1347 | if (__c != 'E' && __c != 'O')
|
---|
| 1348 | __format = __c;
|
---|
| 1349 | else if (++__beg != __end)
|
---|
| 1350 | {
|
---|
| 1351 | __mod = __c;
|
---|
| 1352 | __format = __ctype.narrow(*__beg, 0);
|
---|
| 1353 | }
|
---|
| 1354 | else
|
---|
| 1355 | break;
|
---|
| 1356 | __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
|
---|
| 1357 | }
|
---|
| 1358 | else
|
---|
| 1359 | break;
|
---|
| 1360 | return __s;
|
---|
| 1361 | }
|
---|
| 1362 |
|
---|
| 1363 | template<typename _CharT, typename _OutIter>
|
---|
| 1364 | _OutIter
|
---|
| 1365 | time_put<_CharT, _OutIter>::
|
---|
| 1366 | do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
|
---|
| 1367 | char __format, char __mod) const
|
---|
| 1368 | {
|
---|
| 1369 | const locale& __loc = __io._M_getloc();
|
---|
| 1370 | ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
|
---|
| 1371 | __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
|
---|
| 1372 |
|
---|
| 1373 | // NB: This size is arbitrary. Should this be a data member,
|
---|
| 1374 | // initialized at construction?
|
---|
| 1375 | const size_t __maxlen = 128;
|
---|
| 1376 | char_type __res[__maxlen];
|
---|
| 1377 |
|
---|
| 1378 | // NB: In IEE 1003.1-200x, and perhaps other locale models, it
|
---|
| 1379 | // is possible that the format character will be longer than one
|
---|
| 1380 | // character. Possibilities include 'E' or 'O' followed by a
|
---|
| 1381 | // format character: if __mod is not the default argument, assume
|
---|
| 1382 | // it's a valid modifier.
|
---|
| 1383 | char_type __fmt[4];
|
---|
| 1384 | __fmt[0] = __ctype.widen('%');
|
---|
| 1385 | if (!__mod)
|
---|
| 1386 | {
|
---|
| 1387 | __fmt[1] = __format;
|
---|
| 1388 | __fmt[2] = char_type();
|
---|
| 1389 | }
|
---|
| 1390 | else
|
---|
| 1391 | {
|
---|
| 1392 | __fmt[1] = __mod;
|
---|
| 1393 | __fmt[2] = __format;
|
---|
| 1394 | __fmt[3] = char_type();
|
---|
| 1395 | }
|
---|
| 1396 |
|
---|
| 1397 | __tp._M_put(__res, __maxlen, __fmt, __tm);
|
---|
| 1398 |
|
---|
| 1399 | // Write resulting, fully-formatted string to output iterator.
|
---|
| 1400 | return std::__write(__s, __res, char_traits<char_type>::length(__res));
|
---|
| 1401 | }
|
---|
| 1402 |
|
---|
| 1403 |
|
---|
| 1404 | // Inhibit implicit instantiations for required instantiations,
|
---|
| 1405 | // which are defined via explicit instantiations elsewhere.
|
---|
| 1406 | #if _GLIBCXX_EXTERN_TEMPLATE
|
---|
| 1407 | extern template class moneypunct<char, false>;
|
---|
| 1408 | extern template class moneypunct<char, true>;
|
---|
| 1409 | extern template class moneypunct_byname<char, false>;
|
---|
| 1410 | extern template class moneypunct_byname<char, true>;
|
---|
| 1411 | extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<char>;
|
---|
| 1412 | extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<char>;
|
---|
| 1413 | extern template class __timepunct<char>;
|
---|
| 1414 | extern template class time_put<char>;
|
---|
| 1415 | extern template class time_put_byname<char>;
|
---|
| 1416 | extern template class time_get<char>;
|
---|
| 1417 | extern template class time_get_byname<char>;
|
---|
| 1418 | extern template class messages<char>;
|
---|
| 1419 | extern template class messages_byname<char>;
|
---|
| 1420 |
|
---|
| 1421 | extern template
|
---|
| 1422 | const moneypunct<char, true>&
|
---|
| 1423 | use_facet<moneypunct<char, true> >(const locale&);
|
---|
| 1424 |
|
---|
| 1425 | extern template
|
---|
| 1426 | const moneypunct<char, false>&
|
---|
| 1427 | use_facet<moneypunct<char, false> >(const locale&);
|
---|
| 1428 |
|
---|
| 1429 | extern template
|
---|
| 1430 | const money_put<char>&
|
---|
| 1431 | use_facet<money_put<char> >(const locale&);
|
---|
| 1432 |
|
---|
| 1433 | extern template
|
---|
| 1434 | const money_get<char>&
|
---|
| 1435 | use_facet<money_get<char> >(const locale&);
|
---|
| 1436 |
|
---|
| 1437 | extern template
|
---|
| 1438 | const __timepunct<char>&
|
---|
| 1439 | use_facet<__timepunct<char> >(const locale&);
|
---|
| 1440 |
|
---|
| 1441 | extern template
|
---|
| 1442 | const time_put<char>&
|
---|
| 1443 | use_facet<time_put<char> >(const locale&);
|
---|
| 1444 |
|
---|
| 1445 | extern template
|
---|
| 1446 | const time_get<char>&
|
---|
| 1447 | use_facet<time_get<char> >(const locale&);
|
---|
| 1448 |
|
---|
| 1449 | extern template
|
---|
| 1450 | const messages<char>&
|
---|
| 1451 | use_facet<messages<char> >(const locale&);
|
---|
| 1452 |
|
---|
| 1453 | extern template
|
---|
| 1454 | bool
|
---|
| 1455 | has_facet<moneypunct<char> >(const locale&);
|
---|
| 1456 |
|
---|
| 1457 | extern template
|
---|
| 1458 | bool
|
---|
| 1459 | has_facet<money_put<char> >(const locale&);
|
---|
| 1460 |
|
---|
| 1461 | extern template
|
---|
| 1462 | bool
|
---|
| 1463 | has_facet<money_get<char> >(const locale&);
|
---|
| 1464 |
|
---|
| 1465 | extern template
|
---|
| 1466 | bool
|
---|
| 1467 | has_facet<__timepunct<char> >(const locale&);
|
---|
| 1468 |
|
---|
| 1469 | extern template
|
---|
| 1470 | bool
|
---|
| 1471 | has_facet<time_put<char> >(const locale&);
|
---|
| 1472 |
|
---|
| 1473 | extern template
|
---|
| 1474 | bool
|
---|
| 1475 | has_facet<time_get<char> >(const locale&);
|
---|
| 1476 |
|
---|
| 1477 | extern template
|
---|
| 1478 | bool
|
---|
| 1479 | has_facet<messages<char> >(const locale&);
|
---|
| 1480 |
|
---|
| 1481 | #ifdef _GLIBCXX_USE_WCHAR_T
|
---|
| 1482 | extern template class moneypunct<wchar_t, false>;
|
---|
| 1483 | extern template class moneypunct<wchar_t, true>;
|
---|
| 1484 | extern template class moneypunct_byname<wchar_t, false>;
|
---|
| 1485 | extern template class moneypunct_byname<wchar_t, true>;
|
---|
| 1486 | extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<wchar_t>;
|
---|
| 1487 | extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<wchar_t>;
|
---|
| 1488 | extern template class __timepunct<wchar_t>;
|
---|
| 1489 | extern template class time_put<wchar_t>;
|
---|
| 1490 | extern template class time_put_byname<wchar_t>;
|
---|
| 1491 | extern template class time_get<wchar_t>;
|
---|
| 1492 | extern template class time_get_byname<wchar_t>;
|
---|
| 1493 | extern template class messages<wchar_t>;
|
---|
| 1494 | extern template class messages_byname<wchar_t>;
|
---|
| 1495 |
|
---|
| 1496 | extern template
|
---|
| 1497 | const moneypunct<wchar_t, true>&
|
---|
| 1498 | use_facet<moneypunct<wchar_t, true> >(const locale&);
|
---|
| 1499 |
|
---|
| 1500 | extern template
|
---|
| 1501 | const moneypunct<wchar_t, false>&
|
---|
| 1502 | use_facet<moneypunct<wchar_t, false> >(const locale&);
|
---|
| 1503 |
|
---|
| 1504 | extern template
|
---|
| 1505 | const money_put<wchar_t>&
|
---|
| 1506 | use_facet<money_put<wchar_t> >(const locale&);
|
---|
| 1507 |
|
---|
| 1508 | extern template
|
---|
| 1509 | const money_get<wchar_t>&
|
---|
| 1510 | use_facet<money_get<wchar_t> >(const locale&);
|
---|
| 1511 |
|
---|
| 1512 | extern template
|
---|
| 1513 | const __timepunct<wchar_t>&
|
---|
| 1514 | use_facet<__timepunct<wchar_t> >(const locale&);
|
---|
| 1515 |
|
---|
| 1516 | extern template
|
---|
| 1517 | const time_put<wchar_t>&
|
---|
| 1518 | use_facet<time_put<wchar_t> >(const locale&);
|
---|
| 1519 |
|
---|
| 1520 | extern template
|
---|
| 1521 | const time_get<wchar_t>&
|
---|
| 1522 | use_facet<time_get<wchar_t> >(const locale&);
|
---|
| 1523 |
|
---|
| 1524 | extern template
|
---|
| 1525 | const messages<wchar_t>&
|
---|
| 1526 | use_facet<messages<wchar_t> >(const locale&);
|
---|
| 1527 |
|
---|
| 1528 | extern template
|
---|
| 1529 | bool
|
---|
| 1530 | has_facet<moneypunct<wchar_t> >(const locale&);
|
---|
| 1531 |
|
---|
| 1532 | extern template
|
---|
| 1533 | bool
|
---|
| 1534 | has_facet<money_put<wchar_t> >(const locale&);
|
---|
| 1535 |
|
---|
| 1536 | extern template
|
---|
| 1537 | bool
|
---|
| 1538 | has_facet<money_get<wchar_t> >(const locale&);
|
---|
| 1539 |
|
---|
| 1540 | extern template
|
---|
| 1541 | bool
|
---|
| 1542 | has_facet<__timepunct<wchar_t> >(const locale&);
|
---|
| 1543 |
|
---|
| 1544 | extern template
|
---|
| 1545 | bool
|
---|
| 1546 | has_facet<time_put<wchar_t> >(const locale&);
|
---|
| 1547 |
|
---|
| 1548 | extern template
|
---|
| 1549 | bool
|
---|
| 1550 | has_facet<time_get<wchar_t> >(const locale&);
|
---|
| 1551 |
|
---|
| 1552 | extern template
|
---|
| 1553 | bool
|
---|
| 1554 | has_facet<messages<wchar_t> >(const locale&);
|
---|
| 1555 | #endif
|
---|
| 1556 | #endif
|
---|
| 1557 |
|
---|
| 1558 | _GLIBCXX_END_NAMESPACE_VERSION
|
---|
| 1559 | } // namespace std
|
---|
| 1560 |
|
---|
| 1561 | #endif
|
---|