Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:25

0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0007 //
0008 //===----------------------------------------------------------------------===//
0009 
0010 #ifndef _LIBCPP___CXX03___CHRONO_PARSER_STD_FORMAT_SPEC_H
0011 #define _LIBCPP___CXX03___CHRONO_PARSER_STD_FORMAT_SPEC_H
0012 
0013 #include <__cxx03/__config>
0014 #include <__cxx03/__format/concepts.h>
0015 #include <__cxx03/__format/format_error.h>
0016 #include <__cxx03/__format/format_parse_context.h>
0017 #include <__cxx03/__format/formatter_string.h>
0018 #include <__cxx03/__format/parser_std_format_spec.h>
0019 #include <__cxx03/string_view>
0020 
0021 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0022 #  pragma GCC system_header
0023 #endif
0024 
0025 _LIBCPP_BEGIN_NAMESPACE_STD
0026 
0027 #if _LIBCPP_STD_VER >= 20
0028 
0029 namespace __format_spec {
0030 
0031 // By not placing this constant in the formatter class it's not duplicated for char and wchar_t
0032 inline constexpr __fields __fields_chrono_fractional{
0033     .__precision_ = true, .__locale_specific_form_ = true, .__type_ = false};
0034 inline constexpr __fields __fields_chrono{.__locale_specific_form_ = true, .__type_ = false};
0035 
0036 /// Flags available or required in a chrono type.
0037 ///
0038 /// The caller of the chrono formatter lists the types it has available and the
0039 /// validation tests whether the requested type spec (e.g. %M) is available in
0040 /// the formatter.
0041 /// When the type in the chrono-format-spec isn't present in the data a
0042 /// \ref format_error is thrown.
0043 enum class __flags {
0044   __second = 0x1,
0045   __minute = 0x2,
0046   __hour   = 0x4,
0047   __time   = __hour | __minute | __second,
0048 
0049   __day   = 0x8,
0050   __month = 0x10,
0051   __year  = 0x20,
0052 
0053   __weekday = 0x40,
0054 
0055   __month_day     = __day | __month,
0056   __month_weekday = __weekday | __month,
0057   __year_month    = __month | __year,
0058   __date          = __day | __month | __year | __weekday,
0059 
0060   __date_time = __date | __time,
0061 
0062   __duration = 0x80 | __time,
0063 
0064   __time_zone = 0x100,
0065 
0066   __clock = __date_time | __time_zone
0067 };
0068 
0069 _LIBCPP_HIDE_FROM_ABI constexpr __flags operator&(__flags __lhs, __flags __rhs) {
0070   return static_cast<__flags>(static_cast<unsigned>(__lhs) & static_cast<unsigned>(__rhs));
0071 }
0072 
0073 _LIBCPP_HIDE_FROM_ABI constexpr void __validate_second(__flags __flags) {
0074   if ((__flags & __flags::__second) != __flags::__second)
0075     std::__throw_format_error("The supplied date time doesn't contain a second");
0076 }
0077 
0078 _LIBCPP_HIDE_FROM_ABI constexpr void __validate_minute(__flags __flags) {
0079   if ((__flags & __flags::__minute) != __flags::__minute)
0080     std::__throw_format_error("The supplied date time doesn't contain a minute");
0081 }
0082 
0083 _LIBCPP_HIDE_FROM_ABI constexpr void __validate_hour(__flags __flags) {
0084   if ((__flags & __flags::__hour) != __flags::__hour)
0085     std::__throw_format_error("The supplied date time doesn't contain an hour");
0086 }
0087 
0088 _LIBCPP_HIDE_FROM_ABI constexpr void __validate_time(__flags __flags) {
0089   if ((__flags & __flags::__time) != __flags::__time)
0090     std::__throw_format_error("The supplied date time doesn't contain a time");
0091 }
0092 
0093 _LIBCPP_HIDE_FROM_ABI constexpr void __validate_day(__flags __flags) {
0094   if ((__flags & __flags::__day) != __flags::__day)
0095     std::__throw_format_error("The supplied date time doesn't contain a day");
0096 }
0097 
0098 _LIBCPP_HIDE_FROM_ABI constexpr void __validate_month(__flags __flags) {
0099   if ((__flags & __flags::__month) != __flags::__month)
0100     std::__throw_format_error("The supplied date time doesn't contain a month");
0101 }
0102 
0103 _LIBCPP_HIDE_FROM_ABI constexpr void __validate_year(__flags __flags) {
0104   if ((__flags & __flags::__year) != __flags::__year)
0105     std::__throw_format_error("The supplied date time doesn't contain a year");
0106 }
0107 
0108 _LIBCPP_HIDE_FROM_ABI constexpr void __validate_date(__flags __flags) {
0109   if ((__flags & __flags::__date) != __flags::__date)
0110     std::__throw_format_error("The supplied date time doesn't contain a date");
0111 }
0112 
0113 _LIBCPP_HIDE_FROM_ABI constexpr void __validate_date_or_duration(__flags __flags) {
0114   if (((__flags & __flags::__date) != __flags::__date) && ((__flags & __flags::__duration) != __flags::__duration))
0115     std::__throw_format_error("The supplied date time doesn't contain a date or duration");
0116 }
0117 
0118 _LIBCPP_HIDE_FROM_ABI constexpr void __validate_date_time(__flags __flags) {
0119   if ((__flags & __flags::__date_time) != __flags::__date_time)
0120     std::__throw_format_error("The supplied date time doesn't contain a date and time");
0121 }
0122 
0123 _LIBCPP_HIDE_FROM_ABI constexpr void __validate_weekday(__flags __flags) {
0124   if ((__flags & __flags::__weekday) != __flags::__weekday)
0125     std::__throw_format_error("The supplied date time doesn't contain a weekday");
0126 }
0127 
0128 _LIBCPP_HIDE_FROM_ABI constexpr void __validate_duration(__flags __flags) {
0129   if ((__flags & __flags::__duration) != __flags::__duration)
0130     std::__throw_format_error("The supplied date time doesn't contain a duration");
0131 }
0132 
0133 _LIBCPP_HIDE_FROM_ABI constexpr void __validate_time_zone(__flags __flags) {
0134   if ((__flags & __flags::__time_zone) != __flags::__time_zone)
0135     std::__throw_format_error("The supplied date time doesn't contain a time zone");
0136 }
0137 
0138 template <class _CharT>
0139 class _LIBCPP_TEMPLATE_VIS __parser_chrono {
0140   using _ConstIterator = typename basic_format_parse_context<_CharT>::const_iterator;
0141 
0142 public:
0143   template <class _ParseContext>
0144   _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator
0145   __parse(_ParseContext& __ctx, __fields __fields, __flags __flags) {
0146     _ConstIterator __begin = __parser_.__parse(__ctx, __fields);
0147     _ConstIterator __end   = __ctx.end();
0148     if (__begin == __end)
0149       return __begin;
0150 
0151     _ConstIterator __last = __parse_chrono_specs(__begin, __end, __flags);
0152     __chrono_specs_       = basic_string_view<_CharT>{__begin, __last};
0153 
0154     return __last;
0155   }
0156 
0157   __parser<_CharT> __parser_;
0158   basic_string_view<_CharT> __chrono_specs_;
0159 
0160 private:
0161   _LIBCPP_HIDE_FROM_ABI constexpr _ConstIterator
0162   __parse_chrono_specs(_ConstIterator __begin, _ConstIterator __end, __flags __flags) {
0163     _LIBCPP_ASSERT_INTERNAL(__begin != __end,
0164                             "When called with an empty input the function will cause "
0165                             "undefined behavior by evaluating data not in the input");
0166 
0167     if (*__begin != _CharT('%') && *__begin != _CharT('}'))
0168       std::__throw_format_error("The format specifier expects a '%' or a '}'");
0169 
0170     do {
0171       switch (*__begin) {
0172       case _CharT('{'):
0173         std::__throw_format_error("The chrono specifiers contain a '{'");
0174 
0175       case _CharT('}'):
0176         return __begin;
0177 
0178       case _CharT('%'):
0179         __parse_conversion_spec(__begin, __end, __flags);
0180         [[fallthrough]];
0181 
0182       default:
0183         // All other literals
0184         ++__begin;
0185       }
0186 
0187     } while (__begin != __end && *__begin != _CharT('}'));
0188 
0189     return __begin;
0190   }
0191 
0192   /// \pre *__begin == '%'
0193   /// \post __begin points at the end parsed conversion-spec
0194   _LIBCPP_HIDE_FROM_ABI constexpr void
0195   __parse_conversion_spec(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) {
0196     ++__begin;
0197     if (__begin == __end)
0198       std::__throw_format_error("End of input while parsing a conversion specifier");
0199 
0200     switch (*__begin) {
0201     case _CharT('n'):
0202     case _CharT('t'):
0203     case _CharT('%'):
0204       break;
0205 
0206     case _CharT('S'):
0207       __format_spec::__validate_second(__flags);
0208       break;
0209 
0210     case _CharT('M'):
0211       __format_spec::__validate_minute(__flags);
0212       break;
0213 
0214     case _CharT('p'): // TODO FMT does the formater require an hour or a time?
0215     case _CharT('H'):
0216     case _CharT('I'):
0217       __parser_.__hour_ = true;
0218       __validate_hour(__flags);
0219       break;
0220 
0221     case _CharT('r'):
0222     case _CharT('R'):
0223     case _CharT('T'):
0224     case _CharT('X'):
0225       __parser_.__hour_ = true;
0226       __format_spec::__validate_time(__flags);
0227       break;
0228 
0229     case _CharT('d'):
0230     case _CharT('e'):
0231       __format_spec::__validate_day(__flags);
0232       break;
0233 
0234     case _CharT('b'):
0235     case _CharT('h'):
0236     case _CharT('B'):
0237       __parser_.__month_name_ = true;
0238       [[fallthrough]];
0239     case _CharT('m'):
0240       __format_spec::__validate_month(__flags);
0241       break;
0242 
0243     case _CharT('y'):
0244     case _CharT('C'):
0245     case _CharT('Y'):
0246       __format_spec::__validate_year(__flags);
0247       break;
0248 
0249     case _CharT('j'):
0250       __parser_.__day_of_year_ = true;
0251       __format_spec::__validate_date_or_duration(__flags);
0252       break;
0253 
0254     case _CharT('g'):
0255     case _CharT('G'):
0256     case _CharT('U'):
0257     case _CharT('V'):
0258     case _CharT('W'):
0259       __parser_.__week_of_year_ = true;
0260       [[fallthrough]];
0261     case _CharT('x'):
0262     case _CharT('D'):
0263     case _CharT('F'):
0264       __format_spec::__validate_date(__flags);
0265       break;
0266 
0267     case _CharT('c'):
0268       __format_spec::__validate_date_time(__flags);
0269       break;
0270 
0271     case _CharT('a'):
0272     case _CharT('A'):
0273       __parser_.__weekday_name_ = true;
0274       [[fallthrough]];
0275     case _CharT('u'):
0276     case _CharT('w'):
0277       __parser_.__weekday_ = true;
0278       __validate_weekday(__flags);
0279       __format_spec::__validate_weekday(__flags);
0280       break;
0281 
0282     case _CharT('q'):
0283     case _CharT('Q'):
0284       __format_spec::__validate_duration(__flags);
0285       break;
0286 
0287     case _CharT('E'):
0288       __parse_modifier_E(__begin, __end, __flags);
0289       break;
0290 
0291     case _CharT('O'):
0292       __parse_modifier_O(__begin, __end, __flags);
0293       break;
0294 
0295     case _CharT('z'):
0296     case _CharT('Z'):
0297       // Currently there's no time zone information. However some clocks have a
0298       // hard-coded "time zone", for these clocks the information can be used.
0299       // TODO FMT implement time zones.
0300       __format_spec::__validate_time_zone(__flags);
0301       break;
0302 
0303     default: // unknown type;
0304       std::__throw_format_error("The date time type specifier is invalid");
0305     }
0306   }
0307 
0308   /// \pre *__begin == 'E'
0309   /// \post __begin is incremented by one.
0310   _LIBCPP_HIDE_FROM_ABI constexpr void
0311   __parse_modifier_E(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) {
0312     ++__begin;
0313     if (__begin == __end)
0314       std::__throw_format_error("End of input while parsing the modifier E");
0315 
0316     switch (*__begin) {
0317     case _CharT('X'):
0318       __parser_.__hour_ = true;
0319       __format_spec::__validate_time(__flags);
0320       break;
0321 
0322     case _CharT('y'):
0323     case _CharT('C'):
0324     case _CharT('Y'):
0325       __format_spec::__validate_year(__flags);
0326       break;
0327 
0328     case _CharT('x'):
0329       __format_spec::__validate_date(__flags);
0330       break;
0331 
0332     case _CharT('c'):
0333       __format_spec::__validate_date_time(__flags);
0334       break;
0335 
0336     case _CharT('z'):
0337       // Currently there's no time zone information. However some clocks have a
0338       // hard-coded "time zone", for these clocks the information can be used.
0339       // TODO FMT implement time zones.
0340       __format_spec::__validate_time_zone(__flags);
0341       break;
0342 
0343     default:
0344       std::__throw_format_error("The date time type specifier for modifier E is invalid");
0345     }
0346   }
0347 
0348   /// \pre *__begin == 'O'
0349   /// \post __begin is incremented by one.
0350   _LIBCPP_HIDE_FROM_ABI constexpr void
0351   __parse_modifier_O(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) {
0352     ++__begin;
0353     if (__begin == __end)
0354       std::__throw_format_error("End of input while parsing the modifier O");
0355 
0356     switch (*__begin) {
0357     case _CharT('S'):
0358       __format_spec::__validate_second(__flags);
0359       break;
0360 
0361     case _CharT('M'):
0362       __format_spec::__validate_minute(__flags);
0363       break;
0364 
0365     case _CharT('I'):
0366     case _CharT('H'):
0367       __parser_.__hour_ = true;
0368       __format_spec::__validate_hour(__flags);
0369       break;
0370 
0371     case _CharT('d'):
0372     case _CharT('e'):
0373       __format_spec::__validate_day(__flags);
0374       break;
0375 
0376     case _CharT('m'):
0377       __format_spec::__validate_month(__flags);
0378       break;
0379 
0380     case _CharT('y'):
0381       __format_spec::__validate_year(__flags);
0382       break;
0383 
0384     case _CharT('U'):
0385     case _CharT('V'):
0386     case _CharT('W'):
0387       __parser_.__week_of_year_ = true;
0388       __format_spec::__validate_date(__flags);
0389       break;
0390 
0391     case _CharT('u'):
0392     case _CharT('w'):
0393       __parser_.__weekday_ = true;
0394       __format_spec::__validate_weekday(__flags);
0395       break;
0396 
0397     case _CharT('z'):
0398       // Currently there's no time zone information. However some clocks have a
0399       // hard-coded "time zone", for these clocks the information can be used.
0400       // TODO FMT implement time zones.
0401       __format_spec::__validate_time_zone(__flags);
0402       break;
0403 
0404     default:
0405       std::__throw_format_error("The date time type specifier for modifier O is invalid");
0406     }
0407   }
0408 };
0409 
0410 } // namespace __format_spec
0411 
0412 #endif //_LIBCPP_STD_VER >= 20
0413 
0414 _LIBCPP_END_NAMESPACE_STD
0415 
0416 #endif // _LIBCPP___CXX03___CHRONO_PARSER_STD_FORMAT_SPEC_H