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