1e5d2d3eaSMark de Wever // -*- C++ -*- 2e5d2d3eaSMark de Wever //===----------------------------------------------------------------------===// 3e5d2d3eaSMark de Wever // 4e5d2d3eaSMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5e5d2d3eaSMark de Wever // See https://llvm.org/LICENSE.txt for license information. 6e5d2d3eaSMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7e5d2d3eaSMark de Wever // 8e5d2d3eaSMark de Wever //===----------------------------------------------------------------------===// 9e5d2d3eaSMark de Wever 10e5d2d3eaSMark de Wever #ifndef _LIBCPP___CHRONO_PARSER_STD_FORMAT_SPEC_H 11e5d2d3eaSMark de Wever #define _LIBCPP___CHRONO_PARSER_STD_FORMAT_SPEC_H 12e5d2d3eaSMark de Wever 13e5d2d3eaSMark de Wever #include <__config> 1487d56c59SLouis Dionne 15c6f3b7bcSNikolas Klauser #if _LIBCPP_HAS_LOCALIZATION 1687d56c59SLouis Dionne 17e5d2d3eaSMark de Wever # include <__format/concepts.h> 18e5d2d3eaSMark de Wever # include <__format/format_error.h> 19e5d2d3eaSMark de Wever # include <__format/format_parse_context.h> 20e5d2d3eaSMark de Wever # include <__format/formatter_string.h> 21e5d2d3eaSMark de Wever # include <__format/parser_std_format_spec.h> 22e5d2d3eaSMark de Wever # include <string_view> 23e5d2d3eaSMark de Wever 24e5d2d3eaSMark de Wever # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 25e5d2d3eaSMark de Wever # pragma GCC system_header 26e5d2d3eaSMark de Wever # endif 27e5d2d3eaSMark de Wever 28e5d2d3eaSMark de Wever _LIBCPP_BEGIN_NAMESPACE_STD 29e5d2d3eaSMark de Wever 30dff62f52SMark de Wever # if _LIBCPP_STD_VER >= 20 31e5d2d3eaSMark de Wever 32e5d2d3eaSMark de Wever namespace __format_spec { 33e5d2d3eaSMark de Wever 34e5d2d3eaSMark de Wever // By not placing this constant in the formatter class it's not duplicated for char and wchar_t 35719c3dc6SMark de Wever inline constexpr __fields __fields_chrono_fractional{ 36719c3dc6SMark de Wever .__precision_ = true, .__locale_specific_form_ = true, .__type_ = false}; 37e5d2d3eaSMark de Wever inline constexpr __fields __fields_chrono{.__locale_specific_form_ = true, .__type_ = false}; 38e5d2d3eaSMark de Wever 39e5d2d3eaSMark de Wever /// Flags available or required in a chrono type. 40e5d2d3eaSMark de Wever /// 41e5d2d3eaSMark de Wever /// The caller of the chrono formatter lists the types it has available and the 42e5d2d3eaSMark de Wever /// validation tests whether the requested type spec (e.g. %M) is available in 43e5d2d3eaSMark de Wever /// the formatter. 44e5d2d3eaSMark de Wever /// When the type in the chrono-format-spec isn't present in the data a 45e5d2d3eaSMark de Wever /// \ref format_error is thrown. 46e5d2d3eaSMark de Wever enum class __flags { 47e5d2d3eaSMark de Wever __second = 0x1, 48e5d2d3eaSMark de Wever __minute = 0x2, 49e5d2d3eaSMark de Wever __hour = 0x4, 50e5d2d3eaSMark de Wever __time = __hour | __minute | __second, 51e5d2d3eaSMark de Wever 52e5d2d3eaSMark de Wever __day = 0x8, 53e5d2d3eaSMark de Wever __month = 0x10, 54e5d2d3eaSMark de Wever __year = 0x20, 55e5d2d3eaSMark de Wever 56e5d2d3eaSMark de Wever __weekday = 0x40, 57e5d2d3eaSMark de Wever 58e5d2d3eaSMark de Wever __month_day = __day | __month, 59e5d2d3eaSMark de Wever __month_weekday = __weekday | __month, 60e5d2d3eaSMark de Wever __year_month = __month | __year, 61e5d2d3eaSMark de Wever __date = __day | __month | __year | __weekday, 62e5d2d3eaSMark de Wever 63e5d2d3eaSMark de Wever __date_time = __date | __time, 64e5d2d3eaSMark de Wever 65e5d2d3eaSMark de Wever __duration = 0x80 | __time, 66e5d2d3eaSMark de Wever 67e5d2d3eaSMark de Wever __time_zone = 0x100, 68e5d2d3eaSMark de Wever 69e5d2d3eaSMark de Wever __clock = __date_time | __time_zone 70e5d2d3eaSMark de Wever }; 71e5d2d3eaSMark de Wever 72e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr __flags operator&(__flags __lhs, __flags __rhs) { 73e5d2d3eaSMark de Wever return static_cast<__flags>(static_cast<unsigned>(__lhs) & static_cast<unsigned>(__rhs)); 74e5d2d3eaSMark de Wever } 75e5d2d3eaSMark de Wever 76e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_second(__flags __flags) { 77e5d2d3eaSMark de Wever if ((__flags & __flags::__second) != __flags::__second) 78e5d2d3eaSMark de Wever std::__throw_format_error("The supplied date time doesn't contain a second"); 79e5d2d3eaSMark de Wever } 80e5d2d3eaSMark de Wever 81e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_minute(__flags __flags) { 82e5d2d3eaSMark de Wever if ((__flags & __flags::__minute) != __flags::__minute) 83e5d2d3eaSMark de Wever std::__throw_format_error("The supplied date time doesn't contain a minute"); 84e5d2d3eaSMark de Wever } 85e5d2d3eaSMark de Wever 86e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_hour(__flags __flags) { 87e5d2d3eaSMark de Wever if ((__flags & __flags::__hour) != __flags::__hour) 88e5d2d3eaSMark de Wever std::__throw_format_error("The supplied date time doesn't contain an hour"); 89e5d2d3eaSMark de Wever } 90e5d2d3eaSMark de Wever 91e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_time(__flags __flags) { 92e5d2d3eaSMark de Wever if ((__flags & __flags::__time) != __flags::__time) 93e5d2d3eaSMark de Wever std::__throw_format_error("The supplied date time doesn't contain a time"); 94e5d2d3eaSMark de Wever } 95e5d2d3eaSMark de Wever 96e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_day(__flags __flags) { 97e5d2d3eaSMark de Wever if ((__flags & __flags::__day) != __flags::__day) 98e5d2d3eaSMark de Wever std::__throw_format_error("The supplied date time doesn't contain a day"); 99e5d2d3eaSMark de Wever } 100e5d2d3eaSMark de Wever 101e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_month(__flags __flags) { 102e5d2d3eaSMark de Wever if ((__flags & __flags::__month) != __flags::__month) 103e5d2d3eaSMark de Wever std::__throw_format_error("The supplied date time doesn't contain a month"); 104e5d2d3eaSMark de Wever } 105e5d2d3eaSMark de Wever 106e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_year(__flags __flags) { 107e5d2d3eaSMark de Wever if ((__flags & __flags::__year) != __flags::__year) 108e5d2d3eaSMark de Wever std::__throw_format_error("The supplied date time doesn't contain a year"); 109e5d2d3eaSMark de Wever } 110e5d2d3eaSMark de Wever 111e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_date(__flags __flags) { 112e5d2d3eaSMark de Wever if ((__flags & __flags::__date) != __flags::__date) 113e5d2d3eaSMark de Wever std::__throw_format_error("The supplied date time doesn't contain a date"); 114e5d2d3eaSMark de Wever } 115e5d2d3eaSMark de Wever 116e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_date_or_duration(__flags __flags) { 117e5d2d3eaSMark de Wever if (((__flags & __flags::__date) != __flags::__date) && ((__flags & __flags::__duration) != __flags::__duration)) 118e5d2d3eaSMark de Wever std::__throw_format_error("The supplied date time doesn't contain a date or duration"); 119e5d2d3eaSMark de Wever } 120e5d2d3eaSMark de Wever 121e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_date_time(__flags __flags) { 122e5d2d3eaSMark de Wever if ((__flags & __flags::__date_time) != __flags::__date_time) 123e5d2d3eaSMark de Wever std::__throw_format_error("The supplied date time doesn't contain a date and time"); 124e5d2d3eaSMark de Wever } 125e5d2d3eaSMark de Wever 126e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_weekday(__flags __flags) { 127e5d2d3eaSMark de Wever if ((__flags & __flags::__weekday) != __flags::__weekday) 128e5d2d3eaSMark de Wever std::__throw_format_error("The supplied date time doesn't contain a weekday"); 129e5d2d3eaSMark de Wever } 130e5d2d3eaSMark de Wever 131e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_duration(__flags __flags) { 132e5d2d3eaSMark de Wever if ((__flags & __flags::__duration) != __flags::__duration) 133e5d2d3eaSMark de Wever std::__throw_format_error("The supplied date time doesn't contain a duration"); 134e5d2d3eaSMark de Wever } 135e5d2d3eaSMark de Wever 136e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_time_zone(__flags __flags) { 137e5d2d3eaSMark de Wever if ((__flags & __flags::__time_zone) != __flags::__time_zone) 138e5d2d3eaSMark de Wever std::__throw_format_error("The supplied date time doesn't contain a time zone"); 139e5d2d3eaSMark de Wever } 140e5d2d3eaSMark de Wever 141e5d2d3eaSMark de Wever template <class _CharT> 142e5d2d3eaSMark de Wever class _LIBCPP_TEMPLATE_VIS __parser_chrono { 143*f6958523SNikolas Klauser using _ConstIterator _LIBCPP_NODEBUG = typename basic_format_parse_context<_CharT>::const_iterator; 144a845b5b4SLouis Dionne 145e5d2d3eaSMark de Wever public: 146b51e8acdSMark de Wever template <class _ParseContext> 147b51e8acdSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator 148b51e8acdSMark de Wever __parse(_ParseContext& __ctx, __fields __fields, __flags __flags) { 149b51e8acdSMark de Wever _ConstIterator __begin = __parser_.__parse(__ctx, __fields); 150b51e8acdSMark de Wever _ConstIterator __end = __ctx.end(); 151e5d2d3eaSMark de Wever if (__begin == __end) 152e5d2d3eaSMark de Wever return __begin; 153e5d2d3eaSMark de Wever 154a845b5b4SLouis Dionne _ConstIterator __last = __parse_chrono_specs(__begin, __end, __flags); 155e5d2d3eaSMark de Wever __chrono_specs_ = basic_string_view<_CharT>{__begin, __last}; 156e5d2d3eaSMark de Wever 157e5d2d3eaSMark de Wever return __last; 158e5d2d3eaSMark de Wever } 159e5d2d3eaSMark de Wever 160e5d2d3eaSMark de Wever __parser<_CharT> __parser_; 161e5d2d3eaSMark de Wever basic_string_view<_CharT> __chrono_specs_; 162e5d2d3eaSMark de Wever 163e5d2d3eaSMark de Wever private: 164a845b5b4SLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr _ConstIterator 165a845b5b4SLouis Dionne __parse_chrono_specs(_ConstIterator __begin, _ConstIterator __end, __flags __flags) { 1664f215fddSKonstantin Varlamov _LIBCPP_ASSERT_INTERNAL(__begin != __end, 167e5d2d3eaSMark de Wever "When called with an empty input the function will cause " 168e5d2d3eaSMark de Wever "undefined behavior by evaluating data not in the input"); 169e5d2d3eaSMark de Wever 170e5d2d3eaSMark de Wever if (*__begin != _CharT('%') && *__begin != _CharT('}')) 171402eb2efSMark de Wever std::__throw_format_error("The format specifier expects a '%' or a '}'"); 172e5d2d3eaSMark de Wever 173e5d2d3eaSMark de Wever do { 174e5d2d3eaSMark de Wever switch (*__begin) { 175e5d2d3eaSMark de Wever case _CharT('{'): 176402eb2efSMark de Wever std::__throw_format_error("The chrono specifiers contain a '{'"); 177e5d2d3eaSMark de Wever 178e5d2d3eaSMark de Wever case _CharT('}'): 179e5d2d3eaSMark de Wever return __begin; 180e5d2d3eaSMark de Wever 181e5d2d3eaSMark de Wever case _CharT('%'): 182e5d2d3eaSMark de Wever __parse_conversion_spec(__begin, __end, __flags); 183e5d2d3eaSMark de Wever [[fallthrough]]; 184e5d2d3eaSMark de Wever 185e5d2d3eaSMark de Wever default: 186e5d2d3eaSMark de Wever // All other literals 187e5d2d3eaSMark de Wever ++__begin; 188e5d2d3eaSMark de Wever } 189e5d2d3eaSMark de Wever 190e5d2d3eaSMark de Wever } while (__begin != __end && *__begin != _CharT('}')); 191e5d2d3eaSMark de Wever 192e5d2d3eaSMark de Wever return __begin; 193e5d2d3eaSMark de Wever } 194e5d2d3eaSMark de Wever 195e5d2d3eaSMark de Wever /// \pre *__begin == '%' 196e5d2d3eaSMark de Wever /// \post __begin points at the end parsed conversion-spec 197e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void 198a845b5b4SLouis Dionne __parse_conversion_spec(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) { 199e5d2d3eaSMark de Wever ++__begin; 200e5d2d3eaSMark de Wever if (__begin == __end) 201402eb2efSMark de Wever std::__throw_format_error("End of input while parsing a conversion specifier"); 202e5d2d3eaSMark de Wever 203e5d2d3eaSMark de Wever switch (*__begin) { 204e5d2d3eaSMark de Wever case _CharT('n'): 205e5d2d3eaSMark de Wever case _CharT('t'): 206e5d2d3eaSMark de Wever case _CharT('%'): 207e5d2d3eaSMark de Wever break; 208e5d2d3eaSMark de Wever 209e5d2d3eaSMark de Wever case _CharT('S'): 210e5d2d3eaSMark de Wever __format_spec::__validate_second(__flags); 211e5d2d3eaSMark de Wever break; 212e5d2d3eaSMark de Wever 213e5d2d3eaSMark de Wever case _CharT('M'): 214e5d2d3eaSMark de Wever __format_spec::__validate_minute(__flags); 215e5d2d3eaSMark de Wever break; 216e5d2d3eaSMark de Wever 217e5d2d3eaSMark de Wever case _CharT('p'): // TODO FMT does the formater require an hour or a time? 218e5d2d3eaSMark de Wever case _CharT('H'): 219e5d2d3eaSMark de Wever case _CharT('I'): 2207f5d130aSMark de Wever __parser_.__hour_ = true; 221e5d2d3eaSMark de Wever __validate_hour(__flags); 222e5d2d3eaSMark de Wever break; 223e5d2d3eaSMark de Wever 224e5d2d3eaSMark de Wever case _CharT('r'): 225e5d2d3eaSMark de Wever case _CharT('R'): 226e5d2d3eaSMark de Wever case _CharT('T'): 227e5d2d3eaSMark de Wever case _CharT('X'): 2287f5d130aSMark de Wever __parser_.__hour_ = true; 229e5d2d3eaSMark de Wever __format_spec::__validate_time(__flags); 230e5d2d3eaSMark de Wever break; 231e5d2d3eaSMark de Wever 232e5d2d3eaSMark de Wever case _CharT('d'): 233e5d2d3eaSMark de Wever case _CharT('e'): 234e5d2d3eaSMark de Wever __format_spec::__validate_day(__flags); 235e5d2d3eaSMark de Wever break; 236e5d2d3eaSMark de Wever 237e5d2d3eaSMark de Wever case _CharT('b'): 238e5d2d3eaSMark de Wever case _CharT('h'): 239e5d2d3eaSMark de Wever case _CharT('B'): 240e5d2d3eaSMark de Wever __parser_.__month_name_ = true; 241e5d2d3eaSMark de Wever [[fallthrough]]; 242e5d2d3eaSMark de Wever case _CharT('m'): 243e5d2d3eaSMark de Wever __format_spec::__validate_month(__flags); 244e5d2d3eaSMark de Wever break; 245e5d2d3eaSMark de Wever 246e5d2d3eaSMark de Wever case _CharT('y'): 247e5d2d3eaSMark de Wever case _CharT('C'): 248e5d2d3eaSMark de Wever case _CharT('Y'): 249e5d2d3eaSMark de Wever __format_spec::__validate_year(__flags); 250e5d2d3eaSMark de Wever break; 251e5d2d3eaSMark de Wever 252e5d2d3eaSMark de Wever case _CharT('j'): 253105fef5dSMark de Wever __parser_.__day_of_year_ = true; 254e5d2d3eaSMark de Wever __format_spec::__validate_date_or_duration(__flags); 255e5d2d3eaSMark de Wever break; 256e5d2d3eaSMark de Wever 257e5d2d3eaSMark de Wever case _CharT('g'): 258e5d2d3eaSMark de Wever case _CharT('G'): 259e5d2d3eaSMark de Wever case _CharT('U'): 260e5d2d3eaSMark de Wever case _CharT('V'): 261e5d2d3eaSMark de Wever case _CharT('W'): 262105fef5dSMark de Wever __parser_.__week_of_year_ = true; 263105fef5dSMark de Wever [[fallthrough]]; 264105fef5dSMark de Wever case _CharT('x'): 265105fef5dSMark de Wever case _CharT('D'): 266105fef5dSMark de Wever case _CharT('F'): 267e5d2d3eaSMark de Wever __format_spec::__validate_date(__flags); 268e5d2d3eaSMark de Wever break; 269e5d2d3eaSMark de Wever 270e5d2d3eaSMark de Wever case _CharT('c'): 271e5d2d3eaSMark de Wever __format_spec::__validate_date_time(__flags); 272e5d2d3eaSMark de Wever break; 273e5d2d3eaSMark de Wever 274e5d2d3eaSMark de Wever case _CharT('a'): 275e5d2d3eaSMark de Wever case _CharT('A'): 276e5d2d3eaSMark de Wever __parser_.__weekday_name_ = true; 277e5d2d3eaSMark de Wever [[fallthrough]]; 278e5d2d3eaSMark de Wever case _CharT('u'): 279e5d2d3eaSMark de Wever case _CharT('w'): 280105fef5dSMark de Wever __parser_.__weekday_ = true; 281105fef5dSMark de Wever __validate_weekday(__flags); 282e5d2d3eaSMark de Wever __format_spec::__validate_weekday(__flags); 283e5d2d3eaSMark de Wever break; 284e5d2d3eaSMark de Wever 285e5d2d3eaSMark de Wever case _CharT('q'): 286e5d2d3eaSMark de Wever case _CharT('Q'): 287e5d2d3eaSMark de Wever __format_spec::__validate_duration(__flags); 288e5d2d3eaSMark de Wever break; 289e5d2d3eaSMark de Wever 290e5d2d3eaSMark de Wever case _CharT('E'): 291e5d2d3eaSMark de Wever __parse_modifier_E(__begin, __end, __flags); 292e5d2d3eaSMark de Wever break; 293e5d2d3eaSMark de Wever 294e5d2d3eaSMark de Wever case _CharT('O'): 295e5d2d3eaSMark de Wever __parse_modifier_O(__begin, __end, __flags); 296e5d2d3eaSMark de Wever break; 297e5d2d3eaSMark de Wever 298e5d2d3eaSMark de Wever case _CharT('z'): 299e5d2d3eaSMark de Wever case _CharT('Z'): 300e5d2d3eaSMark de Wever // Currently there's no time zone information. However some clocks have a 301e5d2d3eaSMark de Wever // hard-coded "time zone", for these clocks the information can be used. 302e5d2d3eaSMark de Wever // TODO FMT implement time zones. 303e5d2d3eaSMark de Wever __format_spec::__validate_time_zone(__flags); 304e5d2d3eaSMark de Wever break; 305e5d2d3eaSMark de Wever 306e5d2d3eaSMark de Wever default: // unknown type; 307e5d2d3eaSMark de Wever std::__throw_format_error("The date time type specifier is invalid"); 308e5d2d3eaSMark de Wever } 309e5d2d3eaSMark de Wever } 310e5d2d3eaSMark de Wever 311e5d2d3eaSMark de Wever /// \pre *__begin == 'E' 312e5d2d3eaSMark de Wever /// \post __begin is incremented by one. 313e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void 314a845b5b4SLouis Dionne __parse_modifier_E(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) { 315e5d2d3eaSMark de Wever ++__begin; 316e5d2d3eaSMark de Wever if (__begin == __end) 317e5d2d3eaSMark de Wever std::__throw_format_error("End of input while parsing the modifier E"); 318e5d2d3eaSMark de Wever 319e5d2d3eaSMark de Wever switch (*__begin) { 320e5d2d3eaSMark de Wever case _CharT('X'): 3217f5d130aSMark de Wever __parser_.__hour_ = true; 322e5d2d3eaSMark de Wever __format_spec::__validate_time(__flags); 323e5d2d3eaSMark de Wever break; 324e5d2d3eaSMark de Wever 325e5d2d3eaSMark de Wever case _CharT('y'): 326e5d2d3eaSMark de Wever case _CharT('C'): 327e5d2d3eaSMark de Wever case _CharT('Y'): 328e5d2d3eaSMark de Wever __format_spec::__validate_year(__flags); 329e5d2d3eaSMark de Wever break; 330e5d2d3eaSMark de Wever 331e5d2d3eaSMark de Wever case _CharT('x'): 332e5d2d3eaSMark de Wever __format_spec::__validate_date(__flags); 333e5d2d3eaSMark de Wever break; 334e5d2d3eaSMark de Wever 335e5d2d3eaSMark de Wever case _CharT('c'): 336e5d2d3eaSMark de Wever __format_spec::__validate_date_time(__flags); 337e5d2d3eaSMark de Wever break; 338e5d2d3eaSMark de Wever 339e5d2d3eaSMark de Wever case _CharT('z'): 340e5d2d3eaSMark de Wever // Currently there's no time zone information. However some clocks have a 341e5d2d3eaSMark de Wever // hard-coded "time zone", for these clocks the information can be used. 342e5d2d3eaSMark de Wever // TODO FMT implement time zones. 343e5d2d3eaSMark de Wever __format_spec::__validate_time_zone(__flags); 344e5d2d3eaSMark de Wever break; 345e5d2d3eaSMark de Wever 346e5d2d3eaSMark de Wever default: 347e5d2d3eaSMark de Wever std::__throw_format_error("The date time type specifier for modifier E is invalid"); 348e5d2d3eaSMark de Wever } 349e5d2d3eaSMark de Wever } 350e5d2d3eaSMark de Wever 351e5d2d3eaSMark de Wever /// \pre *__begin == 'O' 352e5d2d3eaSMark de Wever /// \post __begin is incremented by one. 353e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void 354a845b5b4SLouis Dionne __parse_modifier_O(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) { 355e5d2d3eaSMark de Wever ++__begin; 356e5d2d3eaSMark de Wever if (__begin == __end) 357e5d2d3eaSMark de Wever std::__throw_format_error("End of input while parsing the modifier O"); 358e5d2d3eaSMark de Wever 359e5d2d3eaSMark de Wever switch (*__begin) { 360e5d2d3eaSMark de Wever case _CharT('S'): 361e5d2d3eaSMark de Wever __format_spec::__validate_second(__flags); 362e5d2d3eaSMark de Wever break; 363e5d2d3eaSMark de Wever 364e5d2d3eaSMark de Wever case _CharT('M'): 365e5d2d3eaSMark de Wever __format_spec::__validate_minute(__flags); 366e5d2d3eaSMark de Wever break; 367e5d2d3eaSMark de Wever 368e5d2d3eaSMark de Wever case _CharT('I'): 369e5d2d3eaSMark de Wever case _CharT('H'): 3707f5d130aSMark de Wever __parser_.__hour_ = true; 371e5d2d3eaSMark de Wever __format_spec::__validate_hour(__flags); 372e5d2d3eaSMark de Wever break; 373e5d2d3eaSMark de Wever 374e5d2d3eaSMark de Wever case _CharT('d'): 375e5d2d3eaSMark de Wever case _CharT('e'): 376e5d2d3eaSMark de Wever __format_spec::__validate_day(__flags); 377e5d2d3eaSMark de Wever break; 378e5d2d3eaSMark de Wever 379e5d2d3eaSMark de Wever case _CharT('m'): 380e5d2d3eaSMark de Wever __format_spec::__validate_month(__flags); 381e5d2d3eaSMark de Wever break; 382e5d2d3eaSMark de Wever 383e5d2d3eaSMark de Wever case _CharT('y'): 384e5d2d3eaSMark de Wever __format_spec::__validate_year(__flags); 385e5d2d3eaSMark de Wever break; 386e5d2d3eaSMark de Wever 387e5d2d3eaSMark de Wever case _CharT('U'): 388e5d2d3eaSMark de Wever case _CharT('V'): 389e5d2d3eaSMark de Wever case _CharT('W'): 390105fef5dSMark de Wever __parser_.__week_of_year_ = true; 391e5d2d3eaSMark de Wever __format_spec::__validate_date(__flags); 392e5d2d3eaSMark de Wever break; 393e5d2d3eaSMark de Wever 394e5d2d3eaSMark de Wever case _CharT('u'): 395e5d2d3eaSMark de Wever case _CharT('w'): 396105fef5dSMark de Wever __parser_.__weekday_ = true; 397e5d2d3eaSMark de Wever __format_spec::__validate_weekday(__flags); 398e5d2d3eaSMark de Wever break; 399e5d2d3eaSMark de Wever 400e5d2d3eaSMark de Wever case _CharT('z'): 401e5d2d3eaSMark de Wever // Currently there's no time zone information. However some clocks have a 402e5d2d3eaSMark de Wever // hard-coded "time zone", for these clocks the information can be used. 403e5d2d3eaSMark de Wever // TODO FMT implement time zones. 404e5d2d3eaSMark de Wever __format_spec::__validate_time_zone(__flags); 405e5d2d3eaSMark de Wever break; 406e5d2d3eaSMark de Wever 407e5d2d3eaSMark de Wever default: 408e5d2d3eaSMark de Wever std::__throw_format_error("The date time type specifier for modifier O is invalid"); 409e5d2d3eaSMark de Wever } 410e5d2d3eaSMark de Wever } 411e5d2d3eaSMark de Wever }; 412e5d2d3eaSMark de Wever 413e5d2d3eaSMark de Wever } // namespace __format_spec 414e5d2d3eaSMark de Wever 415dff62f52SMark de Wever # endif // _LIBCPP_STD_VER >= 20 416e5d2d3eaSMark de Wever 417e5d2d3eaSMark de Wever _LIBCPP_END_NAMESPACE_STD 418e5d2d3eaSMark de Wever 419c6f3b7bcSNikolas Klauser #endif // _LIBCPP_HAS_LOCALIZATION 42087d56c59SLouis Dionne 421e5d2d3eaSMark de Wever #endif // _LIBCPP___CHRONO_PARSER_STD_FORMAT_SPEC_H 422