master
  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-exception
  6//
  7//===----------------------------------------------------------------------===//
  8
  9#ifndef _LIBCPP___LOCALE_DIR_TIME_H
 10#define _LIBCPP___LOCALE_DIR_TIME_H
 11
 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_LOCALIZATION
 19
 20#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 21#    pragma GCC system_header
 22#  endif
 23
 24_LIBCPP_BEGIN_NAMESPACE_STD
 25
 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 >= 1
 30  if (__b == __e) {
 31    __err |= ios_base::eofbit | ios_base::failbit;
 32    return 0;
 33  }
 34  // get first digit
 35  _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 digit
 43    __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_CHARACTERS
 90template <>
 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#  endif
105
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_type
119  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_type
124  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_type
129  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_type
134  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_type
139  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_type
144  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_type
150  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_type
165  do_get_time(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const;
166  virtual iter_type
167  do_get_date(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const;
168  virtual iter_type
169  do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const;
170  virtual iter_type
171  do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const;
172  virtual iter_type
173  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  void
187  __get_month(int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
188  void
189  __get_year(int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
190  void
191  __get_year4(int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
192  void
193  __get_hour(int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
194  void
195  __get_12_hour(int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
196  void
197  __get_am_pm(int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
198  void
199  __get_minute(int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
200  void
201  __get_second(int& __s, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
202  void
203  __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 primitives
212
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 spec
217  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 spec
227  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  else
240    __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  else
250    __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  else
281    __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  else
291    __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  else
301    __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  else
311    __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  else
321    __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  else
331    __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 primitives
372
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    } else
415      __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_CHARACTERS
559extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<wchar_t>;
560#  endif
561
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    _LIBCPP_EXPORTED_FROM_ABI void __time_get_storage<_CharT>::init(const ctype<_CharT>&);                             \
605    template <>                                                                                                        \
606    _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze(           \
607        char, const ctype<_CharT>&);                                                                                   \
608    extern template _LIBCPP_EXPORTED_FROM_ABI time_base::dateorder __time_get_storage<_CharT>::__do_date_order()       \
609        const;                                                                                                         \
610    extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const char*);             \
611    extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const string&);           \
612    extern template _LIBCPP_EXPORTED_FROM_ABI void __time_get_storage<_CharT>::init(const ctype<_CharT>&);             \
613    extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::string_type                                  \
614    __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&);
615
616_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(char)
617#  if _LIBCPP_HAS_WIDE_CHARACTERS
618_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(wchar_t)
619#  endif
620#  undef _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION
621
622template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
623class time_get_byname : public time_get<_CharT, _InputIterator>, private __time_get_storage<_CharT> {
624public:
625  typedef time_base::dateorder dateorder;
626  typedef _InputIterator iter_type;
627  typedef _CharT char_type;
628  typedef basic_string<char_type> string_type;
629
630  _LIBCPP_HIDE_FROM_ABI explicit time_get_byname(const char* __nm, size_t __refs = 0)
631      : time_get<_CharT, _InputIterator>(__refs), __time_get_storage<_CharT>(__nm) {}
632  _LIBCPP_HIDE_FROM_ABI explicit time_get_byname(const string& __nm, size_t __refs = 0)
633      : time_get<_CharT, _InputIterator>(__refs), __time_get_storage<_CharT>(__nm) {}
634
635protected:
636  _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_get_byname() override {}
637
638  _LIBCPP_HIDE_FROM_ABI_VIRTUAL dateorder do_date_order() const override { return this->__do_date_order(); }
639
640private:
641  _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __weeks() const override { return this->__weeks_; }
642  _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __months() const override { return this->__months_; }
643  _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __am_pm() const override { return this->__am_pm_; }
644  _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __c() const override { return this->__c_; }
645  _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __r() const override { return this->__r_; }
646  _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __x() const override { return this->__x_; }
647  _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __X() const override { return this->__X_; }
648};
649
650extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<char>;
651#  if _LIBCPP_HAS_WIDE_CHARACTERS
652extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<wchar_t>;
653#  endif
654
655class _LIBCPP_EXPORTED_FROM_ABI __time_put {
656  __locale::__locale_t __loc_;
657
658protected:
659  _LIBCPP_HIDE_FROM_ABI __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
660  __time_put(const char* __nm);
661  __time_put(const string& __nm);
662  ~__time_put();
663  void __do_put(char* __nb, char*& __ne, const tm* __tm, char __fmt, char __mod) const;
664#  if _LIBCPP_HAS_WIDE_CHARACTERS
665  void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm, char __fmt, char __mod) const;
666#  endif
667};
668
669template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
670class time_put : public locale::facet, private __time_put {
671public:
672  typedef _CharT char_type;
673  typedef _OutputIterator iter_type;
674
675  _LIBCPP_HIDE_FROM_ABI explicit time_put(size_t __refs = 0) : locale::facet(__refs) {}
676
677  iter_type
678  put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, const char_type* __pb, const char_type* __pe)
679      const;
680
681  _LIBCPP_HIDE_FROM_ABI iter_type
682  put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, char __fmt, char __mod = 0) const {
683    return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
684  }
685
686  static locale::id id;
687
688protected:
689  _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_put() override {}
690  virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm, char __fmt, char __mod) const;
691
692  _LIBCPP_HIDE_FROM_ABI explicit time_put(const char* __nm, size_t __refs) : locale::facet(__refs), __time_put(__nm) {}
693  _LIBCPP_HIDE_FROM_ABI explicit time_put(const string& __nm, size_t __refs)
694      : locale::facet(__refs), __time_put(__nm) {}
695};
696
697template <class _CharT, class _OutputIterator>
698locale::id time_put<_CharT, _OutputIterator>::id;
699
700template <class _CharT, class _OutputIterator>
701_OutputIterator time_put<_CharT, _OutputIterator>::put(
702    iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, const char_type* __pb, const char_type* __pe)
703    const {
704  const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc());
705  for (; __pb != __pe; ++__pb) {
706    if (__ct.narrow(*__pb, 0) == '%') {
707      if (++__pb == __pe) {
708        *__s++ = __pb[-1];
709        break;
710      }
711      char __mod = 0;
712      char __fmt = __ct.narrow(*__pb, 0);
713      if (__fmt == 'E' || __fmt == 'O') {
714        if (++__pb == __pe) {
715          *__s++ = __pb[-2];
716          *__s++ = __pb[-1];
717          break;
718        }
719        __mod = __fmt;
720        __fmt = __ct.narrow(*__pb, 0);
721      }
722      __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
723    } else
724      *__s++ = *__pb;
725  }
726  return __s;
727}
728
729template <class _CharT, class _OutputIterator>
730_OutputIterator time_put<_CharT, _OutputIterator>::do_put(
731    iter_type __s, ios_base&, char_type, const tm* __tm, char __fmt, char __mod) const {
732  char_type __nar[100];
733  char_type* __nb = __nar;
734  char_type* __ne = __nb + 100;
735  __do_put(__nb, __ne, __tm, __fmt, __mod);
736  return std::copy(__nb, __ne, __s);
737}
738
739extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<char>;
740#  if _LIBCPP_HAS_WIDE_CHARACTERS
741extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<wchar_t>;
742#  endif
743
744template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
745class time_put_byname : public time_put<_CharT, _OutputIterator> {
746public:
747  _LIBCPP_HIDE_FROM_ABI explicit time_put_byname(const char* __nm, size_t __refs = 0)
748      : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
749
750  _LIBCPP_HIDE_FROM_ABI explicit time_put_byname(const string& __nm, size_t __refs = 0)
751      : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
752
753protected:
754  _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_put_byname() override {}
755};
756
757extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<char>;
758#  if _LIBCPP_HAS_WIDE_CHARACTERS
759extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<wchar_t>;
760#  endif
761
762_LIBCPP_END_NAMESPACE_STD
763
764#endif // _LIBCPP_HAS_LOCALIZATION
765
766#endif // _LIBCPP___LOCALE_DIR_TIME_H