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