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