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/ctype.h>
15#include <__locale_dir/ctype_base.h>
16#include <__locale_dir/get_c_locale.h>
17#include <__locale_dir/locale.h>
18#include <__locale_dir/scan_keyword.h>
19#include <ios>
20
21#if _LIBCPP_HAS_LOCALIZATION
22
23# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
24# pragma GCC system_header
25# endif
26
27_LIBCPP_BEGIN_NAMESPACE_STD
28_LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
29
30template <class _CharT, class _InputIterator>
31_LIBCPP_HIDE_FROM_ABI int __get_up_to_n_digits(
32 _InputIterator& __b, _InputIterator __e, ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n) {
33 // Precondition: __n >= 1
34 if (__b == __e) {
35 __err |= ios_base::eofbit | ios_base::failbit;
36 return 0;
37 }
38 // get first digit
39 _CharT __c = *__b;
40 if (!__ct.is(ctype_base::digit, __c)) {
41 __err |= ios_base::failbit;
42 return 0;
43 }
44 int __r = __ct.narrow(__c, 0) - '0';
45 for (++__b, (void)--__n; __b != __e && __n > 0; ++__b, (void)--__n) {
46 // get next digit
47 __c = *__b;
48 if (!__ct.is(ctype_base::digit, __c))
49 return __r;
50 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
51 }
52 if (__b == __e)
53 __err |= ios_base::eofbit;
54 return __r;
55}
56
57class _LIBCPP_EXPORTED_FROM_ABI time_base {
58public:
59 enum dateorder { no_order, dmy, mdy, ymd, ydm };
60};
61
62template <class _CharT>
63class __time_get_c_storage {
64protected:
65 typedef basic_string<_CharT> string_type;
66
67 virtual const string_type* __weeks() const;
68 virtual const string_type* __months() const;
69 virtual const string_type* __am_pm() const;
70 virtual const string_type& __c() const;
71 virtual const string_type& __r() const;
72 virtual const string_type& __x() const;
73 virtual const string_type& __X() const;
74
75 _LIBCPP_HIDE_FROM_ABI ~__time_get_c_storage() {}
76};
77
78template <>
79_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage<char>::__weeks() const;
80template <>
81_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage<char>::__months() const;
82template <>
83_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage<char>::__am_pm() const;
84template <>
85_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage<char>::__c() const;
86template <>
87_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage<char>::__r() const;
88template <>
89_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage<char>::__x() const;
90template <>
91_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage<char>::__X() const;
92
93# if _LIBCPP_HAS_WIDE_CHARACTERS
94template <>
95_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage<wchar_t>::__weeks() const;
96template <>
97_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage<wchar_t>::__months() const;
98template <>
99_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage<wchar_t>::__am_pm() const;
100template <>
101_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage<wchar_t>::__c() const;
102template <>
103_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage<wchar_t>::__r() const;
104template <>
105_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage<wchar_t>::__x() const;
106template <>
107_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage<wchar_t>::__X() const;
108# endif
109
110template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
111class time_get : public locale::facet, public time_base, private __time_get_c_storage<_CharT> {
112public:
113 typedef _CharT char_type;
114 typedef _InputIterator iter_type;
115 typedef time_base::dateorder dateorder;
116 typedef basic_string<char_type> string_type;
117
118 _LIBCPP_HIDE_FROM_ABI explicit time_get(size_t __refs = 0) : locale::facet(__refs) {}
119
120 _LIBCPP_HIDE_FROM_ABI dateorder date_order() const { return this->do_date_order(); }
121
122 _LIBCPP_HIDE_FROM_ABI iter_type
123 get_time(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {
124 return do_get_time(__b, __e, __iob, __err, __tm);
125 }
126
127 _LIBCPP_HIDE_FROM_ABI iter_type
128 get_date(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {
129 return do_get_date(__b, __e, __iob, __err, __tm);
130 }
131
132 _LIBCPP_HIDE_FROM_ABI iter_type
133 get_weekday(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {
134 return do_get_weekday(__b, __e, __iob, __err, __tm);
135 }
136
137 _LIBCPP_HIDE_FROM_ABI iter_type
138 get_monthname(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {
139 return do_get_monthname(__b, __e, __iob, __err, __tm);
140 }
141
142 _LIBCPP_HIDE_FROM_ABI iter_type
143 get_year(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {
144 return do_get_year(__b, __e, __iob, __err, __tm);
145 }
146
147 _LIBCPP_HIDE_FROM_ABI iter_type
148 get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char __mod = 0)
149 const {
150 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
151 }
152
153 iter_type
154 get(iter_type __b,
155 iter_type __e,
156 ios_base& __iob,
157 ios_base::iostate& __err,
158 tm* __tm,
159 const char_type* __fmtb,
160 const char_type* __fmte) const;
161
162 static locale::id id;
163
164protected:
165 _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_get() override {}
166
167 virtual dateorder do_date_order() const;
168 virtual iter_type
169 do_get_time(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const;
170 virtual iter_type
171 do_get_date(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const;
172 virtual iter_type
173 do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const;
174 virtual iter_type
175 do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const;
176 virtual iter_type
177 do_get_year(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const;
178 virtual iter_type do_get(
179 iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char __mod) const;
180
181private:
182 void __get_white_space(iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
183 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
184
185 void __get_weekdayname(
186 int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
187 void __get_monthname(
188 int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
189 void __get_day(int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
190 void
191 __get_month(int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
192 void
193 __get_year(int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
194 void
195 __get_year4(int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
196 void
197 __get_hour(int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
198 void
199 __get_12_hour(int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
200 void
201 __get_am_pm(int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
202 void
203 __get_minute(int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
204 void
205 __get_second(int& __s, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
206 void
207 __get_weekday(int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
208 void __get_day_year_num(
209 int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const;
210};
211
212template <class _CharT, class _InputIterator>
213locale::id time_get<_CharT, _InputIterator>::id;
214
215// time_get primitives
216
217template <class _CharT, class _InputIterator>
218void time_get<_CharT, _InputIterator>::__get_weekdayname(
219 int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {
220 // Note: ignoring case comes from the POSIX strptime spec
221 const string_type* __wk = this->__weeks();
222 ptrdiff_t __i = std::__scan_keyword(__b, __e, __wk, __wk + 14, __ct, __err, false) - __wk;
223 if (__i < 14)
224 __w = __i % 7;
225}
226
227template <class _CharT, class _InputIterator>
228void time_get<_CharT, _InputIterator>::__get_monthname(
229 int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {
230 // Note: ignoring case comes from the POSIX strptime spec
231 const string_type* __month = this->__months();
232 ptrdiff_t __i = std::__scan_keyword(__b, __e, __month, __month + 24, __ct, __err, false) - __month;
233 if (__i < 24)
234 __m = __i % 12;
235}
236
237template <class _CharT, class _InputIterator>
238void time_get<_CharT, _InputIterator>::__get_day(
239 int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {
240 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2);
241 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
242 __d = __t;
243 else
244 __err |= ios_base::failbit;
245}
246
247template <class _CharT, class _InputIterator>
248void time_get<_CharT, _InputIterator>::__get_month(
249 int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {
250 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
251 if (!(__err & ios_base::failbit) && 0 <= __t && __t <= 11)
252 __m = __t;
253 else
254 __err |= ios_base::failbit;
255}
256
257template <class _CharT, class _InputIterator>
258void time_get<_CharT, _InputIterator>::__get_year(
259 int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {
260 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 4);
261 if (!(__err & ios_base::failbit)) {
262 if (__t < 69)
263 __t += 2000;
264 else if (69 <= __t && __t <= 99)
265 __t += 1900;
266 __y = __t - 1900;
267 }
268}
269
270template <class _CharT, class _InputIterator>
271void time_get<_CharT, _InputIterator>::__get_year4(
272 int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {
273 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 4);
274 if (!(__err & ios_base::failbit))
275 __y = __t - 1900;
276}
277
278template <class _CharT, class _InputIterator>
279void time_get<_CharT, _InputIterator>::__get_hour(
280 int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {
281 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2);
282 if (!(__err & ios_base::failbit) && __t <= 23)
283 __h = __t;
284 else
285 __err |= ios_base::failbit;
286}
287
288template <class _CharT, class _InputIterator>
289void time_get<_CharT, _InputIterator>::__get_12_hour(
290 int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {
291 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2);
292 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
293 __h = __t;
294 else
295 __err |= ios_base::failbit;
296}
297
298template <class _CharT, class _InputIterator>
299void time_get<_CharT, _InputIterator>::__get_minute(
300 int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {
301 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2);
302 if (!(__err & ios_base::failbit) && __t <= 59)
303 __m = __t;
304 else
305 __err |= ios_base::failbit;
306}
307
308template <class _CharT, class _InputIterator>
309void time_get<_CharT, _InputIterator>::__get_second(
310 int& __s, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {
311 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2);
312 if (!(__err & ios_base::failbit) && __t <= 60)
313 __s = __t;
314 else
315 __err |= ios_base::failbit;
316}
317
318template <class _CharT, class _InputIterator>
319void time_get<_CharT, _InputIterator>::__get_weekday(
320 int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {
321 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 1);
322 if (!(__err & ios_base::failbit) && __t <= 6)
323 __w = __t;
324 else
325 __err |= ios_base::failbit;
326}
327
328template <class _CharT, class _InputIterator>
329void time_get<_CharT, _InputIterator>::__get_day_year_num(
330 int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {
331 int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 3);
332 if (!(__err & ios_base::failbit) && __t <= 365)
333 __d = __t;
334 else
335 __err |= ios_base::failbit;
336}
337
338template <class _CharT, class _InputIterator>
339void time_get<_CharT, _InputIterator>::__get_white_space(
340 iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {
341 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
342 ;
343 if (__b == __e)
344 __err |= ios_base::eofbit;
345}
346
347template <class _CharT, class _InputIterator>
348void time_get<_CharT, _InputIterator>::__get_am_pm(
349 int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {
350 const string_type* __ap = this->__am_pm();
351 if (__ap[0].size() + __ap[1].size() == 0) {
352 __err |= ios_base::failbit;
353 return;
354 }
355 ptrdiff_t __i = std::__scan_keyword(__b, __e, __ap, __ap + 2, __ct, __err, false) - __ap;
356 if (__i == 0 && __h == 12)
357 __h = 0;
358 else if (__i == 1 && __h < 12)
359 __h += 12;
360}
361
362template <class _CharT, class _InputIterator>
363void time_get<_CharT, _InputIterator>::__get_percent(
364 iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype<char_type>& __ct) const {
365 if (__b == __e) {
366 __err |= ios_base::eofbit | ios_base::failbit;
367 return;
368 }
369 if (__ct.narrow(*__b, 0) != '%')
370 __err |= ios_base::failbit;
371 else if (++__b == __e)
372 __err |= ios_base::eofbit;
373}
374
375// time_get end primitives
376
377template <class _CharT, class _InputIterator>
378_InputIterator time_get<_CharT, _InputIterator>::get(
379 iter_type __b,
380 iter_type __e,
381 ios_base& __iob,
382 ios_base::iostate& __err,
383 tm* __tm,
384 const char_type* __fmtb,
385 const char_type* __fmte) const {
386 const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc());
387 __err = ios_base::goodbit;
388 while (__fmtb != __fmte && __err == ios_base::goodbit) {
389 if (__b == __e) {
390 __err = ios_base::failbit;
391 break;
392 }
393 if (__ct.narrow(*__fmtb, 0) == '%') {
394 if (++__fmtb == __fmte) {
395 __err = ios_base::failbit;
396 break;
397 }
398 char __cmd = __ct.narrow(*__fmtb, 0);
399 char __opt = '\0';
400 if (__cmd == 'E' || __cmd == '0') {
401 if (++__fmtb == __fmte) {
402 __err = ios_base::failbit;
403 break;
404 }
405 __opt = __cmd;
406 __cmd = __ct.narrow(*__fmtb, 0);
407 }
408 __b = do_get(__b, __e, __iob, __err, __tm, fmt: __cmd, mod: __opt);
409 ++__fmtb;
410 } else if (__ct.is(ctype_base::space, *__fmtb)) {
411 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
412 ;
413 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
414 ;
415 } else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb)) {
416 ++__b;
417 ++__fmtb;
418 } else
419 __err = ios_base::failbit;
420 }
421 if (__b == __e)
422 __err |= ios_base::eofbit;
423 return __b;
424}
425
426template <class _CharT, class _InputIterator>
427typename time_get<_CharT, _InputIterator>::dateorder time_get<_CharT, _InputIterator>::do_date_order() const {
428 return mdy;
429}
430
431template <class _CharT, class _InputIterator>
432_InputIterator time_get<_CharT, _InputIterator>::do_get_time(
433 iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {
434 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
435 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt) / sizeof(__fmt[0]));
436}
437
438template <class _CharT, class _InputIterator>
439_InputIterator time_get<_CharT, _InputIterator>::do_get_date(
440 iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {
441 const string_type& __fmt = this->__x();
442 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
443}
444
445template <class _CharT, class _InputIterator>
446_InputIterator time_get<_CharT, _InputIterator>::do_get_weekday(
447 iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {
448 const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc());
449 __get_weekdayname(w&: __tm->tm_wday, __b, __e, __err, __ct);
450 return __b;
451}
452
453template <class _CharT, class _InputIterator>
454_InputIterator time_get<_CharT, _InputIterator>::do_get_monthname(
455 iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {
456 const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc());
457 __get_monthname(m&: __tm->tm_mon, __b, __e, __err, __ct);
458 return __b;
459}
460
461template <class _CharT, class _InputIterator>
462_InputIterator time_get<_CharT, _InputIterator>::do_get_year(
463 iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const {
464 const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc());
465 __get_year(y&: __tm->tm_year, __b, __e, __err, __ct);
466 return __b;
467}
468
469template <class _CharT, class _InputIterator>
470_InputIterator time_get<_CharT, _InputIterator>::do_get(
471 iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char) const {
472 __err = ios_base::goodbit;
473 const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc());
474 switch (__fmt) {
475 case 'a':
476 case 'A':
477 __get_weekdayname(w&: __tm->tm_wday, __b, __e, __err, __ct);
478 break;
479 case 'b':
480 case 'B':
481 case 'h':
482 __get_monthname(m&: __tm->tm_mon, __b, __e, __err, __ct);
483 break;
484 case 'c': {
485 const string_type& __fm = this->__c();
486 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
487 } break;
488 case 'd':
489 case 'e':
490 __get_day(d&: __tm->tm_mday, __b, __e, __err, __ct);
491 break;
492 case 'D': {
493 const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
494 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0]));
495 } break;
496 case 'F': {
497 const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
498 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0]));
499 } break;
500 case 'H':
501 __get_hour(h&: __tm->tm_hour, __b, __e, __err, __ct);
502 break;
503 case 'I':
504 __get_12_hour(h&: __tm->tm_hour, __b, __e, __err, __ct);
505 break;
506 case 'j':
507 __get_day_year_num(d&: __tm->tm_yday, __b, __e, __err, __ct);
508 break;
509 case 'm':
510 __get_month(m&: __tm->tm_mon, __b, __e, __err, __ct);
511 break;
512 case 'M':
513 __get_minute(m&: __tm->tm_min, __b, __e, __err, __ct);
514 break;
515 case 'n':
516 case 't':
517 __get_white_space(__b, __e, __err, __ct);
518 break;
519 case 'p':
520 __get_am_pm(h&: __tm->tm_hour, __b, __e, __err, __ct);
521 break;
522 case 'r': {
523 const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
524 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0]));
525 } break;
526 case 'R': {
527 const char_type __fm[] = {'%', 'H', ':', '%', 'M'};
528 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0]));
529 } break;
530 case 'S':
531 __get_second(s&: __tm->tm_sec, __b, __e, __err, __ct);
532 break;
533 case 'T': {
534 const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
535 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0]));
536 } break;
537 case 'w':
538 __get_weekday(w&: __tm->tm_wday, __b, __e, __err, __ct);
539 break;
540 case 'x':
541 return do_get_date(__b, __e, __iob, __err, __tm);
542 case 'X': {
543 const string_type& __fm = this->__X();
544 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
545 } break;
546 case 'y':
547 __get_year(y&: __tm->tm_year, __b, __e, __err, __ct);
548 break;
549 case 'Y':
550 __get_year4(y&: __tm->tm_year, __b, __e, __err, __ct);
551 break;
552 case '%':
553 __get_percent(__b, __e, __err, __ct);
554 break;
555 default:
556 __err |= ios_base::failbit;
557 }
558 return __b;
559}
560
561extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<char>;
562# if _LIBCPP_HAS_WIDE_CHARACTERS
563extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<wchar_t>;
564# endif
565
566class _LIBCPP_EXPORTED_FROM_ABI __time_get {
567protected:
568 __locale::__locale_t __loc_;
569
570 __time_get(const char* __nm);
571 __time_get(const string& __nm);
572 ~__time_get();
573};
574
575template <class _CharT>
576class __time_get_storage : public __time_get {
577protected:
578 typedef basic_string<_CharT> string_type;
579
580 string_type __weeks_[14];
581 string_type __months_[24];
582 string_type __am_pm_[2];
583 string_type __c_;
584 string_type __r_;
585 string_type __x_;
586 string_type __X_;
587
588 explicit __time_get_storage(const char* __nm);
589 explicit __time_get_storage(const string& __nm);
590
591 _LIBCPP_HIDE_FROM_ABI ~__time_get_storage() {}
592
593 time_base::dateorder __do_date_order() const;
594
595private:
596 void init(const ctype<_CharT>&);
597 string_type __analyze(char __fmt, const ctype<_CharT>&);
598};
599
600# define _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(_CharT) \
601 template <> \
602 _LIBCPP_EXPORTED_FROM_ABI time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \
603 template <> \
604 _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const char*); \
605 template <> \
606 _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const string&); \
607 template <> \
608 void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \
609 template <> \
610 __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); \
611 extern template _LIBCPP_EXPORTED_FROM_ABI time_base::dateorder __time_get_storage<_CharT>::__do_date_order() \
612 const; \
613 extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const char*); \
614 extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const string&);
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_EXPLICIT_ABI_ANNOTATIONS
763_LIBCPP_END_NAMESPACE_STD
764
765#endif // _LIBCPP_HAS_LOCALIZATION
766
767#endif // _LIBCPP___LOCALE_DIR_TIME_H
768