763 lines · c
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef _LIBCPP___LOCALE_DIR_TIME_H10#define _LIBCPP___LOCALE_DIR_TIME_H11 12#include <__algorithm/copy.h>13#include <__config>14#include <__locale_dir/get_c_locale.h>15#include <__locale_dir/scan_keyword.h>16#include <ios>17 18#if _LIBCPP_HAS_LOCALIZATION19 20# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)21# pragma GCC system_header22# endif23 24_LIBCPP_BEGIN_NAMESPACE_STD25 26template <class _CharT, class _InputIterator>27_LIBCPP_HIDE_FROM_ABI int __get_up_to_n_digits(28 _InputIterator& __b, _InputIterator __e, ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n) {29 // Precondition: __n >= 130 if (__b == __e) {31 __err |= ios_base::eofbit | ios_base::failbit;32 return 0;33 }34 // get first digit35 _CharT __c = *__b;36 if (!__ct.is(ctype_base::digit, __c)) {37 __err |= ios_base::failbit;38 return 0;39 }40 int __r = __ct.narrow(__c, 0) - '0';41 for (++__b, (void)--__n; __b != __e && __n > 0; ++__b, (void)--__n) {42 // get next digit43 __c = *__b;44 if (!__ct.is(ctype_base::digit, __c))45 return __r;46 __r = __r * 10 + __ct.narrow(__c, 0) - '0';47 }48 if (__b == __e)49 __err |= ios_base::eofbit;50 return __r;51}52 53class _LIBCPP_EXPORTED_FROM_ABI time_base {54public:55 enum dateorder { no_order, dmy, mdy, ymd, ydm };56};57 58template <class _CharT>59class __time_get_c_storage {60protected:61 typedef basic_string<_CharT> string_type;62 63 virtual const string_type* __weeks() const;64 virtual const string_type* __months() const;65 virtual const string_type* __am_pm() const;66 virtual const string_type& __c() const;67 virtual const string_type& __r() const;68 virtual const string_type& __x() const;69 virtual const string_type& __X() const;70 71 _LIBCPP_HIDE_FROM_ABI ~__time_get_c_storage() {}72};73 74template <>75_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage<char>::__weeks() const;76template <>77_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage<char>::__months() const;78template <>79_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage<char>::__am_pm() const;80template <>81_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage<char>::__c() const;82template <>83_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage<char>::__r() const;84template <>85_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage<char>::__x() const;86template <>87_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage<char>::__X() const;88 89# if _LIBCPP_HAS_WIDE_CHARACTERS90template <>91_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage<wchar_t>::__weeks() const;92template <>93_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage<wchar_t>::__months() const;94template <>95_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage<wchar_t>::__am_pm() const;96template <>97_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage<wchar_t>::__c() const;98template <>99_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage<wchar_t>::__r() const;100template <>101_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage<wchar_t>::__x() const;102template <>103_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage<wchar_t>::__X() const;104# endif105 106template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >107class time_get : public locale::facet, public time_base, private __time_get_c_storage<_CharT> {108public:109 typedef _CharT char_type;110 typedef _InputIterator iter_type;111 typedef time_base::dateorder dateorder;112 typedef basic_string<char_type> string_type;113 114 _LIBCPP_HIDE_FROM_ABI explicit time_get(size_t __refs = 0) : locale::facet(__refs) {}115 116 _LIBCPP_HIDE_FROM_ABI dateorder date_order() const { return this->do_date_order(); }117 118 _LIBCPP_HIDE_FROM_ABI iter_type119 get_time(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {120 return do_get_time(__b, __e, __iob, __err, __tm);121 }122 123 _LIBCPP_HIDE_FROM_ABI iter_type124 get_date(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {125 return do_get_date(__b, __e, __iob, __err, __tm);126 }127 128 _LIBCPP_HIDE_FROM_ABI iter_type129 get_weekday(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {130 return do_get_weekday(__b, __e, __iob, __err, __tm);131 }132 133 _LIBCPP_HIDE_FROM_ABI iter_type134 get_monthname(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {135 return do_get_monthname(__b, __e, __iob, __err, __tm);136 }137 138 _LIBCPP_HIDE_FROM_ABI iter_type139 get_year(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {140 return do_get_year(__b, __e, __iob, __err, __tm);141 }142 143 _LIBCPP_HIDE_FROM_ABI iter_type144 get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char __mod = 0)145 const {146 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);147 }148 149 iter_type150 get(iter_type __b,151 iter_type __e,152 ios_base& __iob,153 ios_base::iostate& __err,154 tm* __tm,155 const char_type* __fmtb,156 const char_type* __fmte) const;157 158 static locale::id id;159 160protected:161 _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_get() override {}162 163 virtual dateorder do_date_order() const;164 virtual iter_type165 do_get_time(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const;166 virtual iter_type167 do_get_date(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const;168 virtual iter_type169 do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const;170 virtual iter_type171 do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const;172 virtual iter_type173 do_get_year(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const;174 virtual iter_type do_get(175 iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char __mod) const;176 177private:178 void __get_white_space(iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;179 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;180 181 void __get_weekdayname(182 int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;183 void __get_monthname(184 int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;185 void __get_day(int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;186 void187 __get_month(int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;188 void189 __get_year(int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;190 void191 __get_year4(int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;192 void193 __get_hour(int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;194 void195 __get_12_hour(int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;196 void197 __get_am_pm(int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;198 void199 __get_minute(int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;200 void201 __get_second(int& __s, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;202 void203 __get_weekday(int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;204 void __get_day_year_num(205 int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;206};207 208template <class _CharT, class _InputIterator>209locale::id time_get<_CharT, _InputIterator>::id;210 211// time_get primitives212 213template <class _CharT, class _InputIterator>214void time_get<_CharT, _InputIterator>::__get_weekdayname(215 int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {216 // Note: ignoring case comes from the POSIX strptime spec217 const string_type* __wk = this->__weeks();218 ptrdiff_t __i = std::__scan_keyword(__b, __e, __wk, __wk + 14, __ct, __err, false) - __wk;219 if (__i < 14)220 __w = __i % 7;221}222 223template <class _CharT, class _InputIterator>224void time_get<_CharT, _InputIterator>::__get_monthname(225 int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {226 // Note: ignoring case comes from the POSIX strptime spec227 const string_type* __month = this->__months();228 ptrdiff_t __i = std::__scan_keyword(__b, __e, __month, __month + 24, __ct, __err, false) - __month;229 if (__i < 24)230 __m = __i % 12;231}232 233template <class _CharT, class _InputIterator>234void time_get<_CharT, _InputIterator>::__get_day(235 int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {236 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2);237 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)238 __d = __t;239 else240 __err |= ios_base::failbit;241}242 243template <class _CharT, class _InputIterator>244void time_get<_CharT, _InputIterator>::__get_month(245 int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {246 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;247 if (!(__err & ios_base::failbit) && 0 <= __t && __t <= 11)248 __m = __t;249 else250 __err |= ios_base::failbit;251}252 253template <class _CharT, class _InputIterator>254void time_get<_CharT, _InputIterator>::__get_year(255 int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {256 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 4);257 if (!(__err & ios_base::failbit)) {258 if (__t < 69)259 __t += 2000;260 else if (69 <= __t && __t <= 99)261 __t += 1900;262 __y = __t - 1900;263 }264}265 266template <class _CharT, class _InputIterator>267void time_get<_CharT, _InputIterator>::__get_year4(268 int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {269 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 4);270 if (!(__err & ios_base::failbit))271 __y = __t - 1900;272}273 274template <class _CharT, class _InputIterator>275void time_get<_CharT, _InputIterator>::__get_hour(276 int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {277 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2);278 if (!(__err & ios_base::failbit) && __t <= 23)279 __h = __t;280 else281 __err |= ios_base::failbit;282}283 284template <class _CharT, class _InputIterator>285void time_get<_CharT, _InputIterator>::__get_12_hour(286 int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {287 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2);288 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)289 __h = __t;290 else291 __err |= ios_base::failbit;292}293 294template <class _CharT, class _InputIterator>295void time_get<_CharT, _InputIterator>::__get_minute(296 int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {297 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2);298 if (!(__err & ios_base::failbit) && __t <= 59)299 __m = __t;300 else301 __err |= ios_base::failbit;302}303 304template <class _CharT, class _InputIterator>305void time_get<_CharT, _InputIterator>::__get_second(306 int& __s, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {307 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2);308 if (!(__err & ios_base::failbit) && __t <= 60)309 __s = __t;310 else311 __err |= ios_base::failbit;312}313 314template <class _CharT, class _InputIterator>315void time_get<_CharT, _InputIterator>::__get_weekday(316 int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {317 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 1);318 if (!(__err & ios_base::failbit) && __t <= 6)319 __w = __t;320 else321 __err |= ios_base::failbit;322}323 324template <class _CharT, class _InputIterator>325void time_get<_CharT, _InputIterator>::__get_day_year_num(326 int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {327 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 3);328 if (!(__err & ios_base::failbit) && __t <= 365)329 __d = __t;330 else331 __err |= ios_base::failbit;332}333 334template <class _CharT, class _InputIterator>335void time_get<_CharT, _InputIterator>::__get_white_space(336 iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {337 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)338 ;339 if (__b == __e)340 __err |= ios_base::eofbit;341}342 343template <class _CharT, class _InputIterator>344void time_get<_CharT, _InputIterator>::__get_am_pm(345 int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {346 const string_type* __ap = this->__am_pm();347 if (__ap[0].size() + __ap[1].size() == 0) {348 __err |= ios_base::failbit;349 return;350 }351 ptrdiff_t __i = std::__scan_keyword(__b, __e, __ap, __ap + 2, __ct, __err, false) - __ap;352 if (__i == 0 && __h == 12)353 __h = 0;354 else if (__i == 1 && __h < 12)355 __h += 12;356}357 358template <class _CharT, class _InputIterator>359void time_get<_CharT, _InputIterator>::__get_percent(360 iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {361 if (__b == __e) {362 __err |= ios_base::eofbit | ios_base::failbit;363 return;364 }365 if (__ct.narrow(*__b, 0) != '%')366 __err |= ios_base::failbit;367 else if (++__b == __e)368 __err |= ios_base::eofbit;369}370 371// time_get end primitives372 373template <class _CharT, class _InputIterator>374_InputIterator time_get<_CharT, _InputIterator>::get(375 iter_type __b,376 iter_type __e,377 ios_base& __iob,378 ios_base::iostate& __err,379 tm* __tm,380 const char_type* __fmtb,381 const char_type* __fmte) const {382 const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc());383 __err = ios_base::goodbit;384 while (__fmtb != __fmte && __err == ios_base::goodbit) {385 if (__b == __e) {386 __err = ios_base::failbit;387 break;388 }389 if (__ct.narrow(*__fmtb, 0) == '%') {390 if (++__fmtb == __fmte) {391 __err = ios_base::failbit;392 break;393 }394 char __cmd = __ct.narrow(*__fmtb, 0);395 char __opt = '\0';396 if (__cmd == 'E' || __cmd == '0') {397 if (++__fmtb == __fmte) {398 __err = ios_base::failbit;399 break;400 }401 __opt = __cmd;402 __cmd = __ct.narrow(*__fmtb, 0);403 }404 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);405 ++__fmtb;406 } else if (__ct.is(ctype_base::space, *__fmtb)) {407 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)408 ;409 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)410 ;411 } else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb)) {412 ++__b;413 ++__fmtb;414 } else415 __err = ios_base::failbit;416 }417 if (__b == __e)418 __err |= ios_base::eofbit;419 return __b;420}421 422template <class _CharT, class _InputIterator>423typename time_get<_CharT, _InputIterator>::dateorder time_get<_CharT, _InputIterator>::do_date_order() const {424 return mdy;425}426 427template <class _CharT, class _InputIterator>428_InputIterator time_get<_CharT, _InputIterator>::do_get_time(429 iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {430 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};431 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt) / sizeof(__fmt[0]));432}433 434template <class _CharT, class _InputIterator>435_InputIterator time_get<_CharT, _InputIterator>::do_get_date(436 iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {437 const string_type& __fmt = this->__x();438 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());439}440 441template <class _CharT, class _InputIterator>442_InputIterator time_get<_CharT, _InputIterator>::do_get_weekday(443 iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {444 const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc());445 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);446 return __b;447}448 449template <class _CharT, class _InputIterator>450_InputIterator time_get<_CharT, _InputIterator>::do_get_monthname(451 iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {452 const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc());453 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);454 return __b;455}456 457template <class _CharT, class _InputIterator>458_InputIterator time_get<_CharT, _InputIterator>::do_get_year(459 iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {460 const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc());461 __get_year(__tm->tm_year, __b, __e, __err, __ct);462 return __b;463}464 465template <class _CharT, class _InputIterator>466_InputIterator time_get<_CharT, _InputIterator>::do_get(467 iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char) const {468 __err = ios_base::goodbit;469 const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc());470 switch (__fmt) {471 case 'a':472 case 'A':473 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);474 break;475 case 'b':476 case 'B':477 case 'h':478 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);479 break;480 case 'c': {481 const string_type& __fm = this->__c();482 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());483 } break;484 case 'd':485 case 'e':486 __get_day(__tm->tm_mday, __b, __e, __err, __ct);487 break;488 case 'D': {489 const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};490 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0]));491 } break;492 case 'F': {493 const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};494 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0]));495 } break;496 case 'H':497 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);498 break;499 case 'I':500 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);501 break;502 case 'j':503 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);504 break;505 case 'm':506 __get_month(__tm->tm_mon, __b, __e, __err, __ct);507 break;508 case 'M':509 __get_minute(__tm->tm_min, __b, __e, __err, __ct);510 break;511 case 'n':512 case 't':513 __get_white_space(__b, __e, __err, __ct);514 break;515 case 'p':516 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);517 break;518 case 'r': {519 const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};520 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0]));521 } break;522 case 'R': {523 const char_type __fm[] = {'%', 'H', ':', '%', 'M'};524 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0]));525 } break;526 case 'S':527 __get_second(__tm->tm_sec, __b, __e, __err, __ct);528 break;529 case 'T': {530 const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};531 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0]));532 } break;533 case 'w':534 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);535 break;536 case 'x':537 return do_get_date(__b, __e, __iob, __err, __tm);538 case 'X': {539 const string_type& __fm = this->__X();540 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());541 } break;542 case 'y':543 __get_year(__tm->tm_year, __b, __e, __err, __ct);544 break;545 case 'Y':546 __get_year4(__tm->tm_year, __b, __e, __err, __ct);547 break;548 case '%':549 __get_percent(__b, __e, __err, __ct);550 break;551 default:552 __err |= ios_base::failbit;553 }554 return __b;555}556 557extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<char>;558# if _LIBCPP_HAS_WIDE_CHARACTERS559extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<wchar_t>;560# endif561 562class _LIBCPP_EXPORTED_FROM_ABI __time_get {563protected:564 __locale::__locale_t __loc_;565 566 __time_get(const char* __nm);567 __time_get(const string& __nm);568 ~__time_get();569};570 571template <class _CharT>572class __time_get_storage : public __time_get {573protected:574 typedef basic_string<_CharT> string_type;575 576 string_type __weeks_[14];577 string_type __months_[24];578 string_type __am_pm_[2];579 string_type __c_;580 string_type __r_;581 string_type __x_;582 string_type __X_;583 584 explicit __time_get_storage(const char* __nm);585 explicit __time_get_storage(const string& __nm);586 587 _LIBCPP_HIDE_FROM_ABI ~__time_get_storage() {}588 589 time_base::dateorder __do_date_order() const;590 591private:592 void init(const ctype<_CharT>&);593 string_type __analyze(char __fmt, const ctype<_CharT>&);594};595 596# define _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(_CharT) \597 template <> \598 _LIBCPP_EXPORTED_FROM_ABI time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \599 template <> \600 _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const char*); \601 template <> \602 _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const string&); \603 template <> \604 void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \605 template <> \606 __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); \607 extern template _LIBCPP_EXPORTED_FROM_ABI time_base::dateorder __time_get_storage<_CharT>::__do_date_order() \608 const; \609 extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const char*); \610 extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const string&);611 612_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(char)613# if _LIBCPP_HAS_WIDE_CHARACTERS614_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(wchar_t)615# endif616# undef _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION617 618template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >619class time_get_byname : public time_get<_CharT, _InputIterator>, private __time_get_storage<_CharT> {620public:621 typedef time_base::dateorder dateorder;622 typedef _InputIterator iter_type;623 typedef _CharT char_type;624 typedef basic_string<char_type> string_type;625 626 _LIBCPP_HIDE_FROM_ABI explicit time_get_byname(const char* __nm, size_t __refs = 0)627 : time_get<_CharT, _InputIterator>(__refs), __time_get_storage<_CharT>(__nm) {}628 _LIBCPP_HIDE_FROM_ABI explicit time_get_byname(const string& __nm, size_t __refs = 0)629 : time_get<_CharT, _InputIterator>(__refs), __time_get_storage<_CharT>(__nm) {}630 631protected:632 _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_get_byname() override {}633 634 _LIBCPP_HIDE_FROM_ABI_VIRTUAL dateorder do_date_order() const override { return this->__do_date_order(); }635 636private:637 _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __weeks() const override { return this->__weeks_; }638 _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __months() const override { return this->__months_; }639 _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __am_pm() const override { return this->__am_pm_; }640 _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __c() const override { return this->__c_; }641 _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __r() const override { return this->__r_; }642 _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __x() const override { return this->__x_; }643 _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __X() const override { return this->__X_; }644};645 646extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<char>;647# if _LIBCPP_HAS_WIDE_CHARACTERS648extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<wchar_t>;649# endif650 651class _LIBCPP_EXPORTED_FROM_ABI __time_put {652 __locale::__locale_t __loc_;653 654protected:655 _LIBCPP_HIDE_FROM_ABI __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}656 __time_put(const char* __nm);657 __time_put(const string& __nm);658 ~__time_put();659 void __do_put(char* __nb, char*& __ne, const tm* __tm, char __fmt, char __mod) const;660# if _LIBCPP_HAS_WIDE_CHARACTERS661 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm, char __fmt, char __mod) const;662# endif663};664 665template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >666class time_put : public locale::facet, private __time_put {667public:668 typedef _CharT char_type;669 typedef _OutputIterator iter_type;670 671 _LIBCPP_HIDE_FROM_ABI explicit time_put(size_t __refs = 0) : locale::facet(__refs) {}672 673 iter_type674 put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, const char_type* __pb, const char_type* __pe)675 const;676 677 _LIBCPP_HIDE_FROM_ABI iter_type678 put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, char __fmt, char __mod = 0) const {679 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);680 }681 682 static locale::id id;683 684protected:685 _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_put() override {}686 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm, char __fmt, char __mod) const;687 688 _LIBCPP_HIDE_FROM_ABI explicit time_put(const char* __nm, size_t __refs) : locale::facet(__refs), __time_put(__nm) {}689 _LIBCPP_HIDE_FROM_ABI explicit time_put(const string& __nm, size_t __refs)690 : locale::facet(__refs), __time_put(__nm) {}691};692 693template <class _CharT, class _OutputIterator>694locale::id time_put<_CharT, _OutputIterator>::id;695 696template <class _CharT, class _OutputIterator>697_OutputIterator time_put<_CharT, _OutputIterator>::put(698 iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, const char_type* __pb, const char_type* __pe)699 const {700 const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc());701 for (; __pb != __pe; ++__pb) {702 if (__ct.narrow(*__pb, 0) == '%') {703 if (++__pb == __pe) {704 *__s++ = __pb[-1];705 break;706 }707 char __mod = 0;708 char __fmt = __ct.narrow(*__pb, 0);709 if (__fmt == 'E' || __fmt == 'O') {710 if (++__pb == __pe) {711 *__s++ = __pb[-2];712 *__s++ = __pb[-1];713 break;714 }715 __mod = __fmt;716 __fmt = __ct.narrow(*__pb, 0);717 }718 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);719 } else720 *__s++ = *__pb;721 }722 return __s;723}724 725template <class _CharT, class _OutputIterator>726_OutputIterator time_put<_CharT, _OutputIterator>::do_put(727 iter_type __s, ios_base&, char_type, const tm* __tm, char __fmt, char __mod) const {728 char_type __nar[100];729 char_type* __nb = __nar;730 char_type* __ne = __nb + 100;731 __do_put(__nb, __ne, __tm, __fmt, __mod);732 return std::copy(__nb, __ne, __s);733}734 735extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<char>;736# if _LIBCPP_HAS_WIDE_CHARACTERS737extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<wchar_t>;738# endif739 740template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >741class time_put_byname : public time_put<_CharT, _OutputIterator> {742public:743 _LIBCPP_HIDE_FROM_ABI explicit time_put_byname(const char* __nm, size_t __refs = 0)744 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}745 746 _LIBCPP_HIDE_FROM_ABI explicit time_put_byname(const string& __nm, size_t __refs = 0)747 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}748 749protected:750 _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_put_byname() override {}751};752 753extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<char>;754# if _LIBCPP_HAS_WIDE_CHARACTERS755extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<wchar_t>;756# endif757 758_LIBCPP_END_NAMESPACE_STD759 760#endif // _LIBCPP_HAS_LOCALIZATION761 762#endif // _LIBCPP___LOCALE_DIR_TIME_H763