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
26 template <class _CharT, class _InputIterator>
__get_up_to_n_digits(_InputIterator & __b,_InputIterator __e,ios_base::iostate & __err,const ctype<_CharT> & __ct,int __n)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
53 class _LIBCPP_EXPORTED_FROM_ABI time_base {
54 public:
55 enum dateorder { no_order, dmy, mdy, ymd, ydm };
56 };
57
58 template <class _CharT>
59 class __time_get_c_storage {
60 protected:
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
~__time_get_c_storage()71 _LIBCPP_HIDE_FROM_ABI ~__time_get_c_storage() {}
72 };
73
74 template <>
75 _LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage<char>::__weeks() const;
76 template <>
77 _LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage<char>::__months() const;
78 template <>
79 _LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage<char>::__am_pm() const;
80 template <>
81 _LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage<char>::__c() const;
82 template <>
83 _LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage<char>::__r() const;
84 template <>
85 _LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage<char>::__x() const;
86 template <>
87 _LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage<char>::__X() const;
88
89 # if _LIBCPP_HAS_WIDE_CHARACTERS
90 template <>
91 _LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage<wchar_t>::__weeks() const;
92 template <>
93 _LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage<wchar_t>::__months() const;
94 template <>
95 _LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage<wchar_t>::__am_pm() const;
96 template <>
97 _LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage<wchar_t>::__c() const;
98 template <>
99 _LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage<wchar_t>::__r() const;
100 template <>
101 _LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage<wchar_t>::__x() const;
102 template <>
103 _LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage<wchar_t>::__X() const;
104 # endif
105
106 template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
107 class time_get : public locale::facet, public time_base, private __time_get_c_storage<_CharT> {
108 public:
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
facet(__refs)114 _LIBCPP_HIDE_FROM_ABI explicit time_get(size_t __refs = 0) : locale::facet(__refs) {}
115
date_order()116 _LIBCPP_HIDE_FROM_ABI dateorder date_order() const { return this->do_date_order(); }
117
118 _LIBCPP_HIDE_FROM_ABI iter_type
get_time(iter_type __b,iter_type __e,ios_base & __iob,ios_base::iostate & __err,tm * __tm)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
get_date(iter_type __b,iter_type __e,ios_base & __iob,ios_base::iostate & __err,tm * __tm)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
get_weekday(iter_type __b,iter_type __e,ios_base & __iob,ios_base::iostate & __err,tm * __tm)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
get_monthname(iter_type __b,iter_type __e,ios_base & __iob,ios_base::iostate & __err,tm * __tm)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
get_year(iter_type __b,iter_type __e,ios_base & __iob,ios_base::iostate & __err,tm * __tm)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
160 protected:
~time_get()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
177 private:
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
208 template <class _CharT, class _InputIterator>
209 locale::id time_get<_CharT, _InputIterator>::id;
210
211 // time_get primitives
212
213 template <class _CharT, class _InputIterator>
__get_weekdayname(int & __w,iter_type & __b,iter_type __e,ios_base::iostate & __err,const ctype<char_type> & __ct)214 void 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
223 template <class _CharT, class _InputIterator>
__get_monthname(int & __m,iter_type & __b,iter_type __e,ios_base::iostate & __err,const ctype<char_type> & __ct)224 void 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
233 template <class _CharT, class _InputIterator>
__get_day(int & __d,iter_type & __b,iter_type __e,ios_base::iostate & __err,const ctype<char_type> & __ct)234 void 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
243 template <class _CharT, class _InputIterator>
__get_month(int & __m,iter_type & __b,iter_type __e,ios_base::iostate & __err,const ctype<char_type> & __ct)244 void 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
253 template <class _CharT, class _InputIterator>
__get_year(int & __y,iter_type & __b,iter_type __e,ios_base::iostate & __err,const ctype<char_type> & __ct)254 void 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
266 template <class _CharT, class _InputIterator>
__get_year4(int & __y,iter_type & __b,iter_type __e,ios_base::iostate & __err,const ctype<char_type> & __ct)267 void 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
274 template <class _CharT, class _InputIterator>
__get_hour(int & __h,iter_type & __b,iter_type __e,ios_base::iostate & __err,const ctype<char_type> & __ct)275 void 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
284 template <class _CharT, class _InputIterator>
__get_12_hour(int & __h,iter_type & __b,iter_type __e,ios_base::iostate & __err,const ctype<char_type> & __ct)285 void 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
294 template <class _CharT, class _InputIterator>
__get_minute(int & __m,iter_type & __b,iter_type __e,ios_base::iostate & __err,const ctype<char_type> & __ct)295 void 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
304 template <class _CharT, class _InputIterator>
__get_second(int & __s,iter_type & __b,iter_type __e,ios_base::iostate & __err,const ctype<char_type> & __ct)305 void 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
314 template <class _CharT, class _InputIterator>
__get_weekday(int & __w,iter_type & __b,iter_type __e,ios_base::iostate & __err,const ctype<char_type> & __ct)315 void 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
324 template <class _CharT, class _InputIterator>
__get_day_year_num(int & __d,iter_type & __b,iter_type __e,ios_base::iostate & __err,const ctype<char_type> & __ct)325 void 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
334 template <class _CharT, class _InputIterator>
__get_white_space(iter_type & __b,iter_type __e,ios_base::iostate & __err,const ctype<char_type> & __ct)335 void 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
343 template <class _CharT, class _InputIterator>
__get_am_pm(int & __h,iter_type & __b,iter_type __e,ios_base::iostate & __err,const ctype<char_type> & __ct)344 void 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
358 template <class _CharT, class _InputIterator>
__get_percent(iter_type & __b,iter_type __e,ios_base::iostate & __err,const ctype<char_type> & __ct)359 void 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
373 template <class _CharT, class _InputIterator>
get(iter_type __b,iter_type __e,ios_base & __iob,ios_base::iostate & __err,tm * __tm,const char_type * __fmtb,const char_type * __fmte)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
422 template <class _CharT, class _InputIterator>
do_date_order()423 typename time_get<_CharT, _InputIterator>::dateorder time_get<_CharT, _InputIterator>::do_date_order() const {
424 return mdy;
425 }
426
427 template <class _CharT, class _InputIterator>
do_get_time(iter_type __b,iter_type __e,ios_base & __iob,ios_base::iostate & __err,tm * __tm)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
434 template <class _CharT, class _InputIterator>
do_get_date(iter_type __b,iter_type __e,ios_base & __iob,ios_base::iostate & __err,tm * __tm)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
441 template <class _CharT, class _InputIterator>
do_get_weekday(iter_type __b,iter_type __e,ios_base & __iob,ios_base::iostate & __err,tm * __tm)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
449 template <class _CharT, class _InputIterator>
do_get_monthname(iter_type __b,iter_type __e,ios_base & __iob,ios_base::iostate & __err,tm * __tm)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
457 template <class _CharT, class _InputIterator>
do_get_year(iter_type __b,iter_type __e,ios_base & __iob,ios_base::iostate & __err,tm * __tm)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
465 template <class _CharT, class _InputIterator>
do_get(iter_type __b,iter_type __e,ios_base & __iob,ios_base::iostate & __err,tm * __tm,char __fmt,char)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
557 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<char>;
558 # if _LIBCPP_HAS_WIDE_CHARACTERS
559 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<wchar_t>;
560 # endif
561
562 class _LIBCPP_EXPORTED_FROM_ABI __time_get {
563 protected:
564 __locale::__locale_t __loc_;
565
566 __time_get(const char* __nm);
567 __time_get(const string& __nm);
568 ~__time_get();
569 };
570
571 template <class _CharT>
572 class __time_get_storage : public __time_get {
573 protected:
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
~__time_get_storage()587 _LIBCPP_HIDE_FROM_ABI ~__time_get_storage() {}
588
589 time_base::dateorder __do_date_order() const;
590
591 private:
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
_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(wchar_t)618 _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(wchar_t)
619 # endif
620 # undef _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION
621
622 template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
623 class time_get_byname : public time_get<_CharT, _InputIterator>, private __time_get_storage<_CharT> {
624 public:
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
635 protected:
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
640 private:
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
650 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<char>;
651 # if _LIBCPP_HAS_WIDE_CHARACTERS
652 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<wchar_t>;
653 # endif
654
655 class _LIBCPP_EXPORTED_FROM_ABI __time_put {
656 __locale::__locale_t __loc_;
657
658 protected:
__time_put()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
669 template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
670 class time_put : public locale::facet, private __time_put {
671 public:
672 typedef _CharT char_type;
673 typedef _OutputIterator iter_type;
674
facet(__refs)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
688 protected:
~time_put()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
time_put(const char * __nm,size_t __refs)692 _LIBCPP_HIDE_FROM_ABI explicit time_put(const char* __nm, size_t __refs) : locale::facet(__refs), __time_put(__nm) {}
time_put(const string & __nm,size_t __refs)693 _LIBCPP_HIDE_FROM_ABI explicit time_put(const string& __nm, size_t __refs)
694 : locale::facet(__refs), __time_put(__nm) {}
695 };
696
697 template <class _CharT, class _OutputIterator>
698 locale::id time_put<_CharT, _OutputIterator>::id;
699
700 template <class _CharT, class _OutputIterator>
put(iter_type __s,ios_base & __iob,char_type __fl,const tm * __tm,const char_type * __pb,const char_type * __pe)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
729 template <class _CharT, class _OutputIterator>
do_put(iter_type __s,ios_base &,char_type,const tm * __tm,char __fmt,char __mod)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
739 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<char>;
740 # if _LIBCPP_HAS_WIDE_CHARACTERS
741 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<wchar_t>;
742 # endif
743
744 template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
745 class time_put_byname : public time_put<_CharT, _OutputIterator> {
746 public:
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
753 protected:
~time_put_byname()754 _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_put_byname() override {}
755 };
756
757 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<char>;
758 # if _LIBCPP_HAS_WIDE_CHARACTERS
759 extern 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
767