forked from OSchip/llvm-project
[libc++][chrono] Implements formatter day.
This implements the enabled specializaton template<class charT> struct formatter<chrono::day, charT>; and template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const day& d); Implements: - LWG 3241 chrono-spec grammar ambiguity in §[time.format] Partially implements: - P1361 Integration of chrono with text formatting Reviewed By: #libc, ldionne Differential Revision: https://reviews.llvm.org/D128577
This commit is contained in:
parent
b490c8a662
commit
e5d2d3eafb
|
@ -175,7 +175,7 @@
|
|||
"`3253 <https://wg21.link/LWG3253>`__","``basic_syncbuf::basic_syncbuf()``\ should not be explicit","Belfast","",""
|
||||
"`3245 <https://wg21.link/LWG3245>`__","Unnecessary restriction on ``'%p'``\ parse specifier","Belfast","","","|chrono|"
|
||||
"`3244 <https://wg21.link/LWG3244>`__","Constraints for ``Source``\ in |sect|\ [fs.path.req] insufficiently constrainty","Belfast","",""
|
||||
"`3241 <https://wg21.link/LWG3241>`__","``chrono-spec``\ grammar ambiguity in |sect|\ [time.format]","Belfast","","","|chrono| |format|"
|
||||
"`3241 <https://wg21.link/LWG3241>`__","``chrono-spec``\ grammar ambiguity in |sect|\ [time.format]","Belfast","|Complete|","16.0","|chrono| |format|"
|
||||
"`3257 <https://wg21.link/LWG3257>`__","Missing feature testing macro update from P0858","Belfast","",""
|
||||
"`3256 <https://wg21.link/LWG3256>`__","Feature testing macro for ``constexpr``\ algorithms","Belfast","|Complete|","13.0"
|
||||
"`3273 <https://wg21.link/LWG3273>`__","Specify ``weekday_indexed``\ to range of ``[0, 7]``\ ","Belfast","","","|chrono|"
|
||||
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
@ -114,7 +114,7 @@
|
|||
"`P1207R4 <https://wg21.link/P1207R4>`__","LWG","Movability of Single-pass Iterators","Cologne","|Complete|","15.0"
|
||||
"`P1208R6 <https://wg21.link/P1208R6>`__","LWG","Adopt source_location for C++20","Cologne","",""
|
||||
"`P1355R2 <https://wg21.link/P1355R2>`__","LWG","Exposing a narrow contract for ceil2","Cologne","|Complete|","9.0"
|
||||
"`P1361R2 <https://wg21.link/P1361R2>`__","LWG","Integration of chrono with text formatting","Cologne","",""
|
||||
"`P1361R2 <https://wg21.link/P1361R2>`__","LWG","Integration of chrono with text formatting","Cologne","|In Progress|",""
|
||||
"`P1423R3 <https://wg21.link/P1423R3>`__","LWG","char8_t backward compatibility remediation","Cologne","|Complete|","15.0"
|
||||
"`P1424R1 <https://wg21.link/P1424R1>`__","LWG","'constexpr' feature macro concerns","Cologne","Superseded by `P1902 <https://wg21.link/P1902>`__",""
|
||||
"`P1466R3 <https://wg21.link/P1466R3>`__","LWG","Miscellaneous minor fixes for chrono","Cologne","",""
|
||||
|
|
|
|
@ -204,15 +204,20 @@ set(files
|
|||
__charconv/to_chars_result.h
|
||||
__chrono/calendar.h
|
||||
__chrono/convert_to_timespec.h
|
||||
__chrono/convert_to_tm.h
|
||||
__chrono/day.h
|
||||
__chrono/duration.h
|
||||
__chrono/file_clock.h
|
||||
__chrono/formatter.h
|
||||
__chrono/hh_mm_ss.h
|
||||
__chrono/high_resolution_clock.h
|
||||
__chrono/literals.h
|
||||
__chrono/month.h
|
||||
__chrono/month_weekday.h
|
||||
__chrono/monthday.h
|
||||
__chrono/ostream.h
|
||||
__chrono/parser_std_format_spec.h
|
||||
__chrono/statically_widen.h
|
||||
__chrono/steady_clock.h
|
||||
__chrono/system_clock.h
|
||||
__chrono/time_point.h
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___CHRONO_CONVERT_TO_TM_H
|
||||
#define _LIBCPP___CHRONO_CONVERT_TO_TM_H
|
||||
|
||||
#include <__chrono/day.h>
|
||||
#include <__concepts/same_as.h>
|
||||
#include <__config>
|
||||
#include <ctime>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI tm __convert_to_tm(const _Tp& __value) {
|
||||
tm __result = {};
|
||||
# ifdef __GLIBC__
|
||||
__result.tm_zone = "UTC";
|
||||
# endif
|
||||
|
||||
if constexpr (same_as<_Tp, chrono::day>)
|
||||
__result.tm_mday = static_cast<unsigned>(__value);
|
||||
else
|
||||
static_assert(sizeof(_Tp) == 0, "Add the missing type specialization");
|
||||
|
||||
return __result;
|
||||
}
|
||||
|
||||
#endif //if _LIBCPP_STD_VER > 17
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___CHRONO_CONVERT_TO_TM_H
|
|
@ -0,0 +1,153 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___CHRONO_FORMATTER_H
|
||||
#define _LIBCPP___CHRONO_FORMATTER_H
|
||||
|
||||
#include <__chrono/convert_to_tm.h>
|
||||
#include <__chrono/day.h>
|
||||
#include <__chrono/parser_std_format_spec.h>
|
||||
#include <__config>
|
||||
#include <__format/concepts.h>
|
||||
#include <__format/format_parse_context.h>
|
||||
#include <__format/formatter.h>
|
||||
#include <__format/formatter_output.h>
|
||||
#include <__format/parser_std_format_spec.h>
|
||||
#include <ctime>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
|
||||
|
||||
namespace __formatter {
|
||||
|
||||
/// Formats a time based on a tm struct.
|
||||
///
|
||||
/// This formatter passes the formatting to time_put which uses strftime. When
|
||||
/// the value is outside the valid range it's unspecified what strftime will
|
||||
/// output. For example weekday 8 can print 1 when the day is processed modulo
|
||||
/// 7 since that handles the Sunday for 0-based weekday. It can also print 8 if
|
||||
/// 7 is handled as a special case.
|
||||
///
|
||||
/// The Standard doesn't specify what to do in this case so the result depends
|
||||
/// on the result of the underlying code.
|
||||
///
|
||||
/// \pre When the (abbreviated) weekday or month name are used, the caller
|
||||
/// validates whether the value is valid. So the caller handles that
|
||||
/// requirement of Table 97: Meaning of conversion specifiers
|
||||
/// [tab:time.format.spec].
|
||||
///
|
||||
/// When no chrono-specs are provided it uses the stream formatter.
|
||||
|
||||
template <class _CharT, class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs(
|
||||
const _Tp& __value, basic_stringstream<_CharT>& __sstr, basic_string_view<_CharT> __chrono_specs) {
|
||||
tm __t = std::__convert_to_tm(__value);
|
||||
const auto& __facet = std::use_facet<time_put<_CharT>>(__sstr.getloc());
|
||||
for (auto __it = __chrono_specs.begin(); __it != __chrono_specs.end(); ++__it) {
|
||||
if (*__it == _CharT('%')) {
|
||||
auto __s = __it;
|
||||
++__it;
|
||||
// We only handle the types that can't be directly handled by time_put.
|
||||
// (as an optimization n, t, and % are also handled directly.)
|
||||
switch (*__it) {
|
||||
case _CharT('n'):
|
||||
__sstr << _CharT('\n');
|
||||
break;
|
||||
case _CharT('t'):
|
||||
__sstr << _CharT('\t');
|
||||
break;
|
||||
case _CharT('%'):
|
||||
__sstr << *__it;
|
||||
break;
|
||||
|
||||
case _CharT('O'):
|
||||
++__it;
|
||||
[[fallthrough]];
|
||||
default:
|
||||
__facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
__sstr << *__it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class _CharT, class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI auto
|
||||
__format_chrono(const _Tp& __value,
|
||||
auto& __ctx,
|
||||
__format_spec::__parsed_specifications<_CharT> __specs,
|
||||
basic_string_view<_CharT> __chrono_specs) -> decltype(__ctx.out()) {
|
||||
basic_stringstream<_CharT> __sstr;
|
||||
// [time.format]/2
|
||||
// 2.1 - the "C" locale if the L option is not present in chrono-format-spec, otherwise
|
||||
// 2.2 - the locale passed to the formatting function if any, otherwise
|
||||
// 2.3 - the global locale.
|
||||
// Note that the __ctx's locale() call does 2.2 and 2.3.
|
||||
if (__specs.__chrono_.__locale_specific_form_)
|
||||
__sstr.imbue(__ctx.locale());
|
||||
else
|
||||
__sstr.imbue(locale::classic());
|
||||
|
||||
if (__chrono_specs.empty())
|
||||
__sstr << __value;
|
||||
else
|
||||
__formatter::__format_chrono_using_chrono_specs(__value, __sstr, __chrono_specs);
|
||||
|
||||
// TODO FMT Use the stringstream's view after P0408R7 has been implemented.
|
||||
basic_string<_CharT> __str = __sstr.str();
|
||||
return __formatter::__write_string(basic_string_view<_CharT>{__str}, __ctx.out(), __specs);
|
||||
}
|
||||
|
||||
} // namespace __formatter
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_chrono {
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto __parse(
|
||||
basic_format_parse_context<_CharT>& __parse_ctx, __format_spec::__fields __fields, __format_spec::__flags __flags)
|
||||
-> decltype(__parse_ctx.begin()) {
|
||||
return __parser_.__parse(__parse_ctx, __fields, __flags);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI auto format(const _Tp& __value, auto& __ctx) const -> decltype(__ctx.out()) const {
|
||||
return __formatter::__format_chrono(
|
||||
__value, __ctx, __parser_.__parser_.__get_parsed_chrono_specifications(__ctx), __parser_.__chrono_specs_);
|
||||
}
|
||||
|
||||
__format_spec::__parser_chrono<_CharT> __parser_;
|
||||
};
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::day, _CharT>
|
||||
: public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base = __formatter_chrono<_CharT>;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
|
||||
-> decltype(__parse_ctx.begin()) {
|
||||
return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__day);
|
||||
}
|
||||
};
|
||||
|
||||
#endif //if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___CHRONO_FORMATTER_H
|
|
@ -0,0 +1,49 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___CHRONO_OSTREAM_H
|
||||
#define _LIBCPP___CHRONO_OSTREAM_H
|
||||
|
||||
#include <__chrono/day.h>
|
||||
#include <__chrono/statically_widen.h>
|
||||
#include <__config>
|
||||
#include <format>
|
||||
#include <ostream>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
|
||||
|
||||
namespace chrono {
|
||||
|
||||
template <class _CharT, class _Traits>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>&
|
||||
operator<<(basic_ostream<_CharT, _Traits>& __os, const day& __d) {
|
||||
return __os
|
||||
<< (__d.ok()
|
||||
? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%d}"), __d)
|
||||
// Note this error differs from the wording of the Standard. The
|
||||
// Standard wording doesn't work well on AIX or Windows. There
|
||||
// the formatted day seems to be either modulo 100 or completely
|
||||
// omitted. Judging by the wording this is valid.
|
||||
// TODO FMT Write a paper of file an LWG issue.
|
||||
: std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02} is not a valid day"), static_cast<unsigned>(__d)));
|
||||
}
|
||||
|
||||
} // namespace chrono
|
||||
|
||||
#endif //if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___CHRONO_OSTREAM_H
|
|
@ -0,0 +1,401 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___CHRONO_PARSER_STD_FORMAT_SPEC_H
|
||||
#define _LIBCPP___CHRONO_PARSER_STD_FORMAT_SPEC_H
|
||||
|
||||
#include <__config>
|
||||
#include <__format/concepts.h>
|
||||
#include <__format/format_error.h>
|
||||
#include <__format/format_parse_context.h>
|
||||
#include <__format/formatter_string.h>
|
||||
#include <__format/parser_std_format_spec.h>
|
||||
#include <string_view>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
|
||||
|
||||
namespace __format_spec {
|
||||
|
||||
// By not placing this constant in the formatter class it's not duplicated for char and wchar_t
|
||||
inline constexpr __fields __fields_chrono{.__locale_specific_form_ = true, .__type_ = false};
|
||||
|
||||
/// Flags available or required in a chrono type.
|
||||
///
|
||||
/// The caller of the chrono formatter lists the types it has available and the
|
||||
/// validation tests whether the requested type spec (e.g. %M) is available in
|
||||
/// the formatter.
|
||||
/// When the type in the chrono-format-spec isn't present in the data a
|
||||
/// \ref format_error is thrown.
|
||||
enum class __flags {
|
||||
__second = 0x1,
|
||||
__minute = 0x2,
|
||||
__hour = 0x4,
|
||||
__time = __hour | __minute | __second,
|
||||
|
||||
__day = 0x8,
|
||||
__month = 0x10,
|
||||
__year = 0x20,
|
||||
|
||||
__weekday = 0x40,
|
||||
|
||||
__month_day = __day | __month,
|
||||
__month_weekday = __weekday | __month,
|
||||
__year_month = __month | __year,
|
||||
__date = __day | __month | __year | __weekday,
|
||||
|
||||
__date_time = __date | __time,
|
||||
|
||||
__duration = 0x80 | __time,
|
||||
|
||||
__time_zone = 0x100,
|
||||
|
||||
__clock = __date_time | __time_zone
|
||||
};
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __flags operator&(__flags __lhs, __flags __rhs) {
|
||||
return static_cast<__flags>(static_cast<unsigned>(__lhs) & static_cast<unsigned>(__rhs));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void __validate_second(__flags __flags) {
|
||||
if ((__flags & __flags::__second) != __flags::__second)
|
||||
std::__throw_format_error("The supplied date time doesn't contain a second");
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void __validate_minute(__flags __flags) {
|
||||
if ((__flags & __flags::__minute) != __flags::__minute)
|
||||
std::__throw_format_error("The supplied date time doesn't contain a minute");
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void __validate_hour(__flags __flags) {
|
||||
if ((__flags & __flags::__hour) != __flags::__hour)
|
||||
std::__throw_format_error("The supplied date time doesn't contain an hour");
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void __validate_time(__flags __flags) {
|
||||
if ((__flags & __flags::__time) != __flags::__time)
|
||||
std::__throw_format_error("The supplied date time doesn't contain a time");
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void __validate_day(__flags __flags) {
|
||||
if ((__flags & __flags::__day) != __flags::__day)
|
||||
std::__throw_format_error("The supplied date time doesn't contain a day");
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void __validate_month(__flags __flags) {
|
||||
if ((__flags & __flags::__month) != __flags::__month)
|
||||
std::__throw_format_error("The supplied date time doesn't contain a month");
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void __validate_year(__flags __flags) {
|
||||
if ((__flags & __flags::__year) != __flags::__year)
|
||||
std::__throw_format_error("The supplied date time doesn't contain a year");
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void __validate_date(__flags __flags) {
|
||||
if ((__flags & __flags::__date) != __flags::__date)
|
||||
std::__throw_format_error("The supplied date time doesn't contain a date");
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void __validate_date_or_duration(__flags __flags) {
|
||||
if (((__flags & __flags::__date) != __flags::__date) && ((__flags & __flags::__duration) != __flags::__duration))
|
||||
std::__throw_format_error("The supplied date time doesn't contain a date or duration");
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void __validate_date_time(__flags __flags) {
|
||||
if ((__flags & __flags::__date_time) != __flags::__date_time)
|
||||
std::__throw_format_error("The supplied date time doesn't contain a date and time");
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void __validate_weekday(__flags __flags) {
|
||||
if ((__flags & __flags::__weekday) != __flags::__weekday)
|
||||
std::__throw_format_error("The supplied date time doesn't contain a weekday");
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void __validate_duration(__flags __flags) {
|
||||
if ((__flags & __flags::__duration) != __flags::__duration)
|
||||
std::__throw_format_error("The supplied date time doesn't contain a duration");
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void __validate_time_zone(__flags __flags) {
|
||||
if ((__flags & __flags::__time_zone) != __flags::__time_zone)
|
||||
std::__throw_format_error("The supplied date time doesn't contain a time zone");
|
||||
}
|
||||
|
||||
template <class _CharT>
|
||||
class _LIBCPP_TEMPLATE_VIS __parser_chrono {
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto
|
||||
__parse(basic_format_parse_context<_CharT>& __parse_ctx, __fields __fields, __flags __flags)
|
||||
-> decltype(__parse_ctx.begin()) {
|
||||
const _CharT* __begin = __parser_.__parse(__parse_ctx, __fields);
|
||||
const _CharT* __end = __parse_ctx.end();
|
||||
if (__begin == __end)
|
||||
return __begin;
|
||||
|
||||
const _CharT* __last = __parse_chrono_specs(__begin, __end, __flags);
|
||||
__chrono_specs_ = basic_string_view<_CharT>{__begin, __last};
|
||||
|
||||
return __last;
|
||||
}
|
||||
|
||||
__parser<_CharT> __parser_;
|
||||
basic_string_view<_CharT> __chrono_specs_;
|
||||
|
||||
private:
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
|
||||
__parse_chrono_specs(const _CharT* __begin, const _CharT* __end, __flags __flags) {
|
||||
_LIBCPP_ASSERT(__begin != __end,
|
||||
"When called with an empty input the function will cause "
|
||||
"undefined behavior by evaluating data not in the input");
|
||||
|
||||
if (*__begin != _CharT('%') && *__begin != _CharT('}'))
|
||||
std::__throw_format_error("Expected '%' or '}' in the chrono format-string");
|
||||
|
||||
do {
|
||||
switch (*__begin) {
|
||||
case _CharT('{'):
|
||||
std::__throw_format_error("The chrono-specs contains a '{'");
|
||||
|
||||
case _CharT('}'):
|
||||
return __begin;
|
||||
|
||||
case _CharT('%'):
|
||||
__parse_conversion_spec(__begin, __end, __flags);
|
||||
[[fallthrough]];
|
||||
|
||||
default:
|
||||
// All other literals
|
||||
++__begin;
|
||||
}
|
||||
|
||||
} while (__begin != __end && *__begin != _CharT('}'));
|
||||
|
||||
return __begin;
|
||||
}
|
||||
|
||||
/// \pre *__begin == '%'
|
||||
/// \post __begin points at the end parsed conversion-spec
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void
|
||||
__parse_conversion_spec(const _CharT*& __begin, const _CharT* __end, __flags __flags) {
|
||||
++__begin;
|
||||
if (__begin == __end)
|
||||
std::__throw_format_error("End of input while parsing the modifier chrono conversion-spec");
|
||||
|
||||
switch (*__begin) {
|
||||
case _CharT('n'):
|
||||
case _CharT('t'):
|
||||
case _CharT('%'):
|
||||
break;
|
||||
|
||||
case _CharT('S'):
|
||||
__format_spec::__validate_second(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('M'):
|
||||
__format_spec::__validate_minute(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('p'): // TODO FMT does the formater require an hour or a time?
|
||||
case _CharT('H'):
|
||||
case _CharT('I'):
|
||||
__validate_hour(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('r'):
|
||||
case _CharT('R'):
|
||||
case _CharT('T'):
|
||||
case _CharT('X'):
|
||||
__format_spec::__validate_time(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('d'):
|
||||
case _CharT('e'):
|
||||
__format_spec::__validate_day(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('b'):
|
||||
case _CharT('h'):
|
||||
case _CharT('B'):
|
||||
__parser_.__month_name_ = true;
|
||||
[[fallthrough]];
|
||||
case _CharT('m'):
|
||||
__format_spec::__validate_month(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('y'):
|
||||
case _CharT('C'):
|
||||
case _CharT('Y'):
|
||||
__format_spec::__validate_year(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('j'):
|
||||
__format_spec::__validate_date_or_duration(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('g'):
|
||||
case _CharT('x'):
|
||||
case _CharT('D'):
|
||||
case _CharT('F'):
|
||||
case _CharT('G'):
|
||||
case _CharT('U'):
|
||||
case _CharT('V'):
|
||||
case _CharT('W'):
|
||||
__format_spec::__validate_date(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('c'):
|
||||
__format_spec::__validate_date_time(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('a'):
|
||||
case _CharT('A'):
|
||||
__parser_.__weekday_name_ = true;
|
||||
[[fallthrough]];
|
||||
case _CharT('u'):
|
||||
case _CharT('w'):
|
||||
__format_spec::__validate_weekday(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('q'):
|
||||
case _CharT('Q'):
|
||||
__format_spec::__validate_duration(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('E'):
|
||||
__parse_modifier_E(__begin, __end, __flags);
|
||||
break;
|
||||
|
||||
case _CharT('O'):
|
||||
__parse_modifier_O(__begin, __end, __flags);
|
||||
break;
|
||||
|
||||
case _CharT('z'):
|
||||
case _CharT('Z'):
|
||||
// Currently there's no time zone information. However some clocks have a
|
||||
// hard-coded "time zone", for these clocks the information can be used.
|
||||
// TODO FMT implement time zones.
|
||||
__format_spec::__validate_time_zone(__flags);
|
||||
break;
|
||||
|
||||
default: // unknown type;
|
||||
std::__throw_format_error("The date time type specifier is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
/// \pre *__begin == 'E'
|
||||
/// \post __begin is incremented by one.
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void
|
||||
__parse_modifier_E(const _CharT*& __begin, const _CharT* __end, __flags __flags) {
|
||||
++__begin;
|
||||
if (__begin == __end)
|
||||
std::__throw_format_error("End of input while parsing the modifier E");
|
||||
|
||||
switch (*__begin) {
|
||||
case _CharT('X'):
|
||||
__format_spec::__validate_time(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('y'):
|
||||
case _CharT('C'):
|
||||
case _CharT('Y'):
|
||||
__format_spec::__validate_year(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('x'):
|
||||
__format_spec::__validate_date(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('c'):
|
||||
__format_spec::__validate_date_time(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('z'):
|
||||
// Currently there's no time zone information. However some clocks have a
|
||||
// hard-coded "time zone", for these clocks the information can be used.
|
||||
// TODO FMT implement time zones.
|
||||
__format_spec::__validate_time_zone(__flags);
|
||||
break;
|
||||
|
||||
default:
|
||||
std::__throw_format_error("The date time type specifier for modifier E is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
/// \pre *__begin == 'O'
|
||||
/// \post __begin is incremented by one.
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void
|
||||
__parse_modifier_O(const _CharT*& __begin, const _CharT* __end, __flags __flags) {
|
||||
++__begin;
|
||||
if (__begin == __end)
|
||||
std::__throw_format_error("End of input while parsing the modifier O");
|
||||
|
||||
switch (*__begin) {
|
||||
case _CharT('S'):
|
||||
__format_spec::__validate_second(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('M'):
|
||||
__format_spec::__validate_minute(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('I'):
|
||||
case _CharT('H'):
|
||||
__format_spec::__validate_hour(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('d'):
|
||||
case _CharT('e'):
|
||||
__format_spec::__validate_day(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('m'):
|
||||
__format_spec::__validate_month(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('y'):
|
||||
__format_spec::__validate_year(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('U'):
|
||||
case _CharT('V'):
|
||||
case _CharT('W'):
|
||||
__format_spec::__validate_date(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('u'):
|
||||
case _CharT('w'):
|
||||
__format_spec::__validate_weekday(__flags);
|
||||
break;
|
||||
|
||||
case _CharT('z'):
|
||||
// Currently there's no time zone information. However some clocks have a
|
||||
// hard-coded "time zone", for these clocks the information can be used.
|
||||
// TODO FMT implement time zones.
|
||||
__format_spec::__validate_time_zone(__flags);
|
||||
break;
|
||||
|
||||
default:
|
||||
std::__throw_format_error("The date time type specifier for modifier O is invalid");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace __format_spec
|
||||
|
||||
#endif //_LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___CHRONO_PARSER_STD_FORMAT_SPEC_H
|
|
@ -0,0 +1,52 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___CHRONO_STATICALLY_WIDEN_H
|
||||
#define _LIBCPP___CHRONO_STATICALLY_WIDEN_H
|
||||
|
||||
// Implements the STATICALLY-WIDEN exposition-only function. ([time.general]/2)
|
||||
|
||||
#include <__concepts/same_as.h>
|
||||
#include <__config>
|
||||
#include <__format/concepts.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
|
||||
# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
template <__fmt_char_type _CharT>
|
||||
consteval const _CharT* __statically_widen(const char* __str, const wchar_t* __wstr) {
|
||||
if constexpr (same_as<_CharT, char>)
|
||||
return __str;
|
||||
else
|
||||
return __wstr;
|
||||
}
|
||||
# define _LIBCPP_STATICALLY_WIDEN(_CharT, __str) ::std::__statically_widen<_CharT>(__str, L##__str)
|
||||
# else // _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
|
||||
// Without this indirection the unit test test/libcxx/modules_include.sh.cpp
|
||||
// fails for the CI build "No wide characters". This seems like a bug.
|
||||
// TODO FMT investigate why this is needed.
|
||||
template <__fmt_char_type _CharT>
|
||||
consteval const _CharT* __statically_widen(const char* __str) {
|
||||
return __str;
|
||||
}
|
||||
# define _LIBCPP_STATICALLY_WIDEN(_CharT, __str) ::std::__statically_widen<_CharT>(__str)
|
||||
# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
|
||||
#endif //if _LIBCPP_STD_VER > 17
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___CHRONO_STATICALLY_WIDEN_H
|
|
@ -176,6 +176,7 @@ struct __std {
|
|||
|
||||
struct __chrono {
|
||||
__alignment __alignment_ : 3;
|
||||
bool __locale_specific_form_ : 1;
|
||||
bool __weekday_name_ : 1;
|
||||
bool __month_name_ : 1;
|
||||
};
|
||||
|
@ -288,12 +289,22 @@ public:
|
|||
_LIBCPP_HIDE_FROM_ABI
|
||||
__parsed_specifications<_CharT> __get_parsed_std_specifications(auto& __ctx) const {
|
||||
return __parsed_specifications<_CharT>{
|
||||
.__std_ =
|
||||
__std{.__alignment_ = __alignment_,
|
||||
.__sign_ = __sign_,
|
||||
.__alternate_form_ = __alternate_form_,
|
||||
.__locale_specific_form_ = __locale_specific_form_,
|
||||
.__type_ = __type_},
|
||||
.__std_ = __std{.__alignment_ = __alignment_,
|
||||
.__sign_ = __sign_,
|
||||
.__alternate_form_ = __alternate_form_,
|
||||
.__locale_specific_form_ = __locale_specific_form_,
|
||||
.__type_ = __type_},
|
||||
.__width_{__get_width(__ctx)},
|
||||
.__precision_{__get_precision(__ctx)},
|
||||
.__fill_{__fill_}};
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __parsed_specifications<_CharT> __get_parsed_chrono_specifications(auto& __ctx) const {
|
||||
return __parsed_specifications<_CharT>{
|
||||
.__chrono_ = __chrono{.__alignment_ = __alignment_,
|
||||
.__locale_specific_form_ = __locale_specific_form_,
|
||||
.__weekday_name_ = __weekday_name_,
|
||||
.__month_name_ = __month_name_},
|
||||
.__width_{__get_width(__ctx)},
|
||||
.__precision_{__get_precision(__ctx)},
|
||||
.__fill_{__fill_}};
|
||||
|
|
|
@ -332,6 +332,9 @@ constexpr day operator+(const day& x, const days& y) noexcept;
|
|||
constexpr day operator+(const days& x, const day& y) noexcept;
|
||||
constexpr day operator-(const day& x, const days& y) noexcept;
|
||||
constexpr days operator-(const day& x, const day& y) noexcept;
|
||||
template<class charT, class traits>
|
||||
basic_ostream<charT, traits>&
|
||||
operator<<(basic_ostream<charT, traits>& os, const day& d);
|
||||
|
||||
// 25.8.4, class month // C++20
|
||||
class month;
|
||||
|
@ -613,7 +616,13 @@ bool operator<(const time_zone& x, const time_zone& y) noexcept;
|
|||
bool operator>(const time_zone& x, const time_zone& y) noexcept;
|
||||
bool operator<=(const time_zone& x, const time_zone& y) noexcept;
|
||||
bool operator>=(const time_zone& x, const time_zone& y) noexcept;
|
||||
} // chrono
|
||||
|
||||
namespace std {
|
||||
template<class charT> struct formatter<chrono::day, charT>; // C++20
|
||||
} // namespace std
|
||||
|
||||
namespace chrono {
|
||||
// calendrical constants
|
||||
inline constexpr last_spec last{}; // C++20
|
||||
inline constexpr chrono::weekday Sunday{0}; // C++20
|
||||
|
@ -663,6 +672,7 @@ constexpr chrono::year operator ""y(unsigned lo
|
|||
#include <__assert> // all public C++ headers provide the assertion handler
|
||||
#include <__chrono/calendar.h>
|
||||
#include <__chrono/convert_to_timespec.h>
|
||||
#include <__chrono/convert_to_tm.h>
|
||||
#include <__chrono/day.h>
|
||||
#include <__chrono/duration.h>
|
||||
#include <__chrono/file_clock.h>
|
||||
|
@ -686,6 +696,14 @@ constexpr chrono::year operator ""y(unsigned lo
|
|||
// standard-mandated includes
|
||||
#include <compare>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) && _LIBCPP_STD_VER > 17
|
||||
# include <__chrono/formatter.h>
|
||||
# include <__chrono/ostream.h>
|
||||
# include <__chrono/parser_std_format_spec.h>
|
||||
# include <__chrono/statically_widen.h>
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
|
|
@ -492,29 +492,43 @@ module std [system] {
|
|||
export *
|
||||
|
||||
module __chrono {
|
||||
module calendar { private header "__chrono/calendar.h" }
|
||||
module convert_to_timespec { private header "__chrono/convert_to_timespec.h" }
|
||||
module day { private header "__chrono/day.h" }
|
||||
module duration { private header "__chrono/duration.h" }
|
||||
module file_clock { private header "__chrono/file_clock.h" }
|
||||
module hh_mm_ss { private header "__chrono/hh_mm_ss.h" }
|
||||
module high_resolution_clock {
|
||||
module calendar { private header "__chrono/calendar.h" }
|
||||
module convert_to_timespec { private header "__chrono/convert_to_timespec.h" }
|
||||
module convert_to_tm { private header "__chrono/convert_to_tm.h" }
|
||||
module day { private header "__chrono/day.h" }
|
||||
module duration { private header "__chrono/duration.h" }
|
||||
module file_clock { private header "__chrono/file_clock.h" }
|
||||
module formatter {
|
||||
@requires_LIBCXX_ENABLE_LOCALIZATION@
|
||||
private header "__chrono/formatter.h"
|
||||
}
|
||||
module hh_mm_ss { private header "__chrono/hh_mm_ss.h" }
|
||||
module high_resolution_clock {
|
||||
private header "__chrono/high_resolution_clock.h"
|
||||
export steady_clock
|
||||
export system_clock
|
||||
}
|
||||
module literals { private header "__chrono/literals.h" }
|
||||
module month { private header "__chrono/month.h" }
|
||||
module month_weekday { private header "__chrono/month_weekday.h" }
|
||||
module monthday { private header "__chrono/monthday.h" }
|
||||
module steady_clock { private header "__chrono/steady_clock.h" }
|
||||
module system_clock { private header "__chrono/system_clock.h" }
|
||||
module time_point { private header "__chrono/time_point.h" }
|
||||
module weekday { private header "__chrono/weekday.h" }
|
||||
module year { private header "__chrono/year.h" }
|
||||
module year_month { private header "__chrono/year_month.h" }
|
||||
module year_month_day { private header "__chrono/year_month_day.h" }
|
||||
module year_month_weekday { private header "__chrono/year_month_weekday.h" }
|
||||
module literals { private header "__chrono/literals.h" }
|
||||
module month { private header "__chrono/month.h" }
|
||||
module month_weekday { private header "__chrono/month_weekday.h" }
|
||||
module monthday { private header "__chrono/monthday.h" }
|
||||
module ostream {
|
||||
@requires_LIBCXX_ENABLE_LOCALIZATION@
|
||||
private header "__chrono/ostream.h"
|
||||
}
|
||||
module parser_std_format_spec {
|
||||
@requires_LIBCXX_ENABLE_LOCALIZATION@
|
||||
private header "__chrono/parser_std_format_spec.h"
|
||||
}
|
||||
module statically_widen { private header "__chrono/statically_widen.h" }
|
||||
module steady_clock { private header "__chrono/steady_clock.h" }
|
||||
module system_clock { private header "__chrono/system_clock.h" }
|
||||
module time_point { private header "__chrono/time_point.h" }
|
||||
module weekday { private header "__chrono/weekday.h" }
|
||||
module year { private header "__chrono/year.h" }
|
||||
module year_month { private header "__chrono/year_month.h" }
|
||||
module year_month_day { private header "__chrono/year_month_day.h" }
|
||||
module year_month_weekday { private header "__chrono/year_month_weekday.h" }
|
||||
}
|
||||
}
|
||||
module codecvt {
|
||||
|
|
|
@ -238,15 +238,20 @@ END-SCRIPT
|
|||
#include <__charconv/to_chars_result.h> // expected-error@*:* {{use of private header from outside its module: '__charconv/to_chars_result.h'}}
|
||||
#include <__chrono/calendar.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/calendar.h'}}
|
||||
#include <__chrono/convert_to_timespec.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/convert_to_timespec.h'}}
|
||||
#include <__chrono/convert_to_tm.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/convert_to_tm.h'}}
|
||||
#include <__chrono/day.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/day.h'}}
|
||||
#include <__chrono/duration.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/duration.h'}}
|
||||
#include <__chrono/file_clock.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/file_clock.h'}}
|
||||
#include <__chrono/formatter.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/formatter.h'}}
|
||||
#include <__chrono/hh_mm_ss.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/hh_mm_ss.h'}}
|
||||
#include <__chrono/high_resolution_clock.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/high_resolution_clock.h'}}
|
||||
#include <__chrono/literals.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/literals.h'}}
|
||||
#include <__chrono/month.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/month.h'}}
|
||||
#include <__chrono/month_weekday.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/month_weekday.h'}}
|
||||
#include <__chrono/monthday.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/monthday.h'}}
|
||||
#include <__chrono/ostream.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/ostream.h'}}
|
||||
#include <__chrono/parser_std_format_spec.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/parser_std_format_spec.h'}}
|
||||
#include <__chrono/statically_widen.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/statically_widen.h'}}
|
||||
#include <__chrono/steady_clock.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/steady_clock.h'}}
|
||||
#include <__chrono/system_clock.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/system_clock.h'}}
|
||||
#include <__chrono/time_point.h> // expected-error@*:* {{use of private header from outside its module: '__chrono/time_point.h'}}
|
||||
|
|
|
@ -1,10 +1,51 @@
|
|||
algorithm
|
||||
array
|
||||
atomic
|
||||
bit
|
||||
bitset
|
||||
cctype
|
||||
cerrno
|
||||
charconv
|
||||
climits
|
||||
cmath
|
||||
compare
|
||||
concepts
|
||||
cstdarg
|
||||
cstddef
|
||||
cstdint
|
||||
cstdio
|
||||
cstdlib
|
||||
cstring
|
||||
ctime
|
||||
cwchar
|
||||
cwctype
|
||||
exception
|
||||
format
|
||||
functional
|
||||
initializer_list
|
||||
ios
|
||||
iosfwd
|
||||
istream
|
||||
iterator
|
||||
limits
|
||||
locale
|
||||
memory
|
||||
mutex
|
||||
new
|
||||
optional
|
||||
ostream
|
||||
ratio
|
||||
sstream
|
||||
stdexcept
|
||||
streambuf
|
||||
string
|
||||
string_view
|
||||
system_error
|
||||
tuple
|
||||
type_traits
|
||||
typeinfo
|
||||
unordered_map
|
||||
utility
|
||||
variant
|
||||
vector
|
||||
version
|
||||
|
|
|
@ -1,10 +1,44 @@
|
|||
array
|
||||
atomic
|
||||
bit
|
||||
bitset
|
||||
cctype
|
||||
cerrno
|
||||
charconv
|
||||
climits
|
||||
cmath
|
||||
compare
|
||||
concepts
|
||||
cstdarg
|
||||
cstddef
|
||||
cstdint
|
||||
cstdio
|
||||
cstdlib
|
||||
cstring
|
||||
ctime
|
||||
cwchar
|
||||
cwctype
|
||||
exception
|
||||
format
|
||||
initializer_list
|
||||
ios
|
||||
iosfwd
|
||||
istream
|
||||
limits
|
||||
locale
|
||||
memory
|
||||
mutex
|
||||
new
|
||||
optional
|
||||
ostream
|
||||
ratio
|
||||
sstream
|
||||
stdexcept
|
||||
streambuf
|
||||
string
|
||||
string_view
|
||||
system_error
|
||||
tuple
|
||||
type_traits
|
||||
typeinfo
|
||||
version
|
||||
|
|
|
@ -122,6 +122,16 @@ void test_P0645() {
|
|||
// enabled.
|
||||
template <class CharT>
|
||||
void test_P1361() {
|
||||
// The chrono formatters require localization support.
|
||||
// [time.format]/7
|
||||
// If the chrono-specs is omitted, the chrono object is formatted as if by
|
||||
// streaming it to std::ostringstream os with the formatting
|
||||
// locale imbued and copying os.str() through the output iterator of the
|
||||
// context with additional padding and adjustments as specified by the format
|
||||
// specifiers.
|
||||
// In libc++ std:::ostringstream requires localization support.
|
||||
#ifndef TEST_HAS_NO_LOCALIZATION
|
||||
|
||||
assert_is_not_formattable<std::chrono::microseconds, CharT>();
|
||||
|
||||
assert_is_not_formattable<std::chrono::sys_time<std::chrono::microseconds>, CharT>();
|
||||
|
@ -131,7 +141,7 @@ void test_P1361() {
|
|||
assert_is_not_formattable<std::chrono::file_time<std::chrono::microseconds>, CharT>();
|
||||
assert_is_not_formattable<std::chrono::local_time<std::chrono::microseconds>, CharT>();
|
||||
|
||||
assert_is_not_formattable<std::chrono::day, CharT>();
|
||||
assert_is_formattable<std::chrono::day, CharT>();
|
||||
assert_is_not_formattable<std::chrono::month, CharT>();
|
||||
assert_is_not_formattable<std::chrono::year, CharT>();
|
||||
|
||||
|
@ -156,6 +166,8 @@ void test_P1361() {
|
|||
//assert_is_formattable<std::chrono::local_info, CharT>();
|
||||
|
||||
//assert_is_formattable<std::chrono::zoned_time, CharT>();
|
||||
|
||||
#endif // TEST_HAS_NO_LOCALIZATION
|
||||
}
|
||||
|
||||
// Tests for P1636 Formatters for library types
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: libcpp-has-no-localization
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// TODO FMT Investigate Windows issues.
|
||||
// UNSUPPORTED msvc, target={{.+}}-windows-gnu
|
||||
|
||||
// REQUIRES: locale.fr_FR.UTF-8
|
||||
// REQUIRES: locale.ja_JP.UTF-8
|
||||
|
||||
// <chrono>
|
||||
// class day;
|
||||
|
||||
// template<class charT, class traits>
|
||||
// basic_ostream<charT, traits>&
|
||||
// operator<<(basic_ostream<charT, traits>& os, const day& d);
|
||||
|
||||
#include <chrono>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
|
||||
#include "make_string.h"
|
||||
#include "platform_support.h" // locale name macros
|
||||
#include "test_macros.h"
|
||||
|
||||
#define SV(S) MAKE_STRING_VIEW(CharT, S)
|
||||
|
||||
template <class CharT>
|
||||
static std::basic_string<CharT> stream_c_locale(std::chrono::day day) {
|
||||
std::basic_stringstream<CharT> sstr;
|
||||
sstr << day;
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static std::basic_string<CharT> stream_fr_FR_locale(std::chrono::day day) {
|
||||
std::basic_stringstream<CharT> sstr;
|
||||
const std::locale locale(LOCALE_fr_FR_UTF_8);
|
||||
sstr.imbue(locale);
|
||||
sstr << day;
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static std::basic_string<CharT> stream_ja_JP_locale(std::chrono::day day) {
|
||||
std::basic_stringstream<CharT> sstr;
|
||||
const std::locale locale(LOCALE_ja_JP_UTF_8);
|
||||
sstr.imbue(locale);
|
||||
sstr << day;
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
assert(stream_c_locale<CharT>(0d) == SV("00 is not a valid day"));
|
||||
assert(stream_c_locale<CharT>(1d) == SV("01"));
|
||||
assert(stream_c_locale<CharT>(31d) == SV("31"));
|
||||
assert(stream_c_locale<CharT>(255d) == SV("255 is not a valid day"));
|
||||
|
||||
assert(stream_fr_FR_locale<CharT>(0d) == SV("00 is not a valid day"));
|
||||
assert(stream_fr_FR_locale<CharT>(1d) == SV("01"));
|
||||
assert(stream_fr_FR_locale<CharT>(31d) == SV("31"));
|
||||
assert(stream_fr_FR_locale<CharT>(255d) == SV("255 is not a valid day"));
|
||||
|
||||
assert(stream_ja_JP_locale<CharT>(0d) == SV("00 is not a valid day"));
|
||||
assert(stream_ja_JP_locale<CharT>(1d) == SV("01"));
|
||||
assert(stream_ja_JP_locale<CharT>(31d) == SV("31"));
|
||||
assert(stream_ja_JP_locale<CharT>(255d) == SV("255 is not a valid day"));
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
test<char>();
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
test<wchar_t>();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: libcpp-has-no-localization
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// TODO FMT Investigate Windows issues.
|
||||
// UNSUPPORTED: msvc, target={{.+}}-windows-gnu
|
||||
|
||||
// REQUIRES: locale.fr_FR.UTF-8
|
||||
// REQUIRES: locale.ja_JP.UTF-8
|
||||
|
||||
// <chrono>
|
||||
|
||||
// template<class charT> struct formatter<chrono::day, charT>;
|
||||
|
||||
#include <chrono>
|
||||
#include <format>
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <locale>
|
||||
#include <iostream>
|
||||
#include <type_traits>
|
||||
|
||||
#include "formatter_tests.h"
|
||||
#include "make_string.h"
|
||||
#include "platform_support.h" // locale name macros
|
||||
#include "string_literal.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class CharT>
|
||||
static void test_no_chrono_specs() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
// Valid day
|
||||
check.template operator()<"{}">(SV("01"), 1d);
|
||||
check.template operator()<"{:*^4}">(SV("*01*"), 1d);
|
||||
check.template operator()<"{:*>3}">(SV("*01"), 1d);
|
||||
|
||||
// Invalid day
|
||||
check.template operator()<"{}">(SV("00 is not a valid day"), 0d);
|
||||
check.template operator()<"{:*^23}">(SV("*00 is not a valid day*"), 0d);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test_valid_values() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
constexpr string_literal fmt{"{:%%d='%d'%t%%Od='%Od'%t%%e='%e'%t%%Oe='%Oe'%n}"};
|
||||
constexpr string_literal lfmt{"{:L%%d='%d'%t%%Od='%Od'%t%%e='%e'%t%%Oe='%Oe'%n}"};
|
||||
|
||||
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||
|
||||
// Non localized output using C-locale
|
||||
check.template operator()<fmt>(SV("%d='00'\t%Od='00'\t%e=' 0'\t%Oe=' 0'\n"), 0d);
|
||||
check.template operator()<fmt>(SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"), 1d);
|
||||
check.template operator()<fmt>(SV("%d='31'\t%Od='31'\t%e='31'\t%Oe='31'\n"), 31d);
|
||||
#if defined(_AIX)
|
||||
check.template operator()<fmt>(SV("%d='55'\t%Od='55'\t%e='55'\t%Oe='55'\n"), 255d);
|
||||
#else
|
||||
check.template operator()<fmt>(SV("%d='255'\t%Od='255'\t%e='255'\t%Oe='255'\n"), 255d);
|
||||
#endif
|
||||
|
||||
// Use the global locale (fr_FR)
|
||||
check.template operator()<lfmt>(SV("%d='00'\t%Od='00'\t%e=' 0'\t%Oe=' 0'\n"), 0d);
|
||||
check.template operator()<lfmt>(SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"), 1d);
|
||||
check.template operator()<lfmt>(SV("%d='31'\t%Od='31'\t%e='31'\t%Oe='31'\n"), 31d);
|
||||
#if defined(_AIX)
|
||||
check.template operator()<lfmt>(SV("%d='55'\t%Od='55'\t%e='55'\t%Oe='55'\n"), 255d);
|
||||
#else
|
||||
check.template operator()<lfmt>(SV("%d='255'\t%Od='255'\t%e='255'\t%Oe='255'\n"), 255d);
|
||||
#endif
|
||||
|
||||
// Use supplied locale (ja_JP). This locale has a different alternate on some platforms.
|
||||
#if defined(__APPLE__) || defined(_AIX)
|
||||
lcheck.template operator()<lfmt>(loc, SV("%d='00'\t%Od='00'\t%e=' 0'\t%Oe=' 0'\n"), 0d);
|
||||
lcheck.template operator()<lfmt>(loc, SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"), 1d);
|
||||
lcheck.template operator()<lfmt>(loc, SV("%d='31'\t%Od='31'\t%e='31'\t%Oe='31'\n"), 31d);
|
||||
# if defined(_AIX)
|
||||
check.template operator()<fmt>(SV("%d='55'\t%Od='55'\t%e='55'\t%Oe='55'\n"), 255d);
|
||||
# else
|
||||
check.template operator()<fmt>(SV("%d='255'\t%Od='255'\t%e='255'\t%Oe='255'\n"), 255d);
|
||||
# endif
|
||||
#else // defined(__APPLE__) || defined(_AIX)
|
||||
lcheck.template operator()<lfmt>(loc, SV("%d='00'\t%Od='〇'\t%e=' 0'\t%Oe='〇'\n"), 0d);
|
||||
lcheck.template operator()<lfmt>(loc, SV("%d='01'\t%Od='一'\t%e=' 1'\t%Oe='一'\n"), 1d);
|
||||
lcheck.template operator()<lfmt>(loc, SV("%d='31'\t%Od='三十一'\t%e='31'\t%Oe='三十一'\n"), 31d);
|
||||
lcheck.template operator()<lfmt>(loc, SV("%d='255'\t%Od='255'\t%e='255'\t%Oe='255'\n"), 255d);
|
||||
#endif // defined(__APPLE__) || defined(_AIX)
|
||||
|
||||
std::locale::global(std::locale::classic());
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
test_no_chrono_specs<CharT>();
|
||||
test_valid_values<CharT>();
|
||||
check_invalid_types<CharT>({SV("d"), SV("e"), SV("Od"), SV("Oe")}, 0d);
|
||||
|
||||
check_exception("Expected '%' or '}' in the chrono format-string", SV("{:A"), 0d);
|
||||
check_exception("The chrono-specs contains a '{'", SV("{:%%{"), 0d);
|
||||
check_exception("End of input while parsing the modifier chrono conversion-spec", SV("{:%"), 0d);
|
||||
check_exception("End of input while parsing the modifier E", SV("{:%E"), 0d);
|
||||
check_exception("End of input while parsing the modifier O", SV("{:%O"), 0d);
|
||||
|
||||
// Precision not allowed
|
||||
check_exception("Expected '%' or '}' in the chrono format-string", SV("{:.3}"), 0d);
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test<char>();
|
||||
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
test<wchar_t>();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,269 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef TEST_STD_TIME_TIME_SYN_FORMATTER_TESTS_H
|
||||
#define TEST_STD_TIME_TIME_SYN_FORMATTER_TESTS_H
|
||||
|
||||
#include "make_string.h"
|
||||
#include "string_literal.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#define STR(S) MAKE_STRING(CharT, S)
|
||||
#define SV(S) MAKE_STRING_VIEW(CharT, S)
|
||||
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
template <class CharT>
|
||||
using format_context = std::conditional_t<std::same_as<CharT, char>, std::format_context, std::wformat_context>;
|
||||
#else
|
||||
template <class CharT>
|
||||
using format_context = std::format_context;
|
||||
#endif
|
||||
|
||||
inline constexpr auto check = []<string_literal fmt, class CharT, class... Args>(
|
||||
std::basic_string_view<CharT> expected, const Args&... args) constexpr {
|
||||
std::basic_string<CharT> out = std::format(fmt.template sv<CharT>(), args...);
|
||||
if constexpr (std::same_as<CharT, char>)
|
||||
if (out != expected)
|
||||
std::cerr << "\nFormat string " << fmt.template sv<CharT>() << "\nExpected output " << expected
|
||||
<< "\nActual output " << out << '\n';
|
||||
assert(out == expected);
|
||||
};
|
||||
|
||||
inline constexpr auto lcheck = []<string_literal fmt, class CharT, class... Args>(
|
||||
const std::locale& loc, std::basic_string_view<CharT> expected, const Args&... args) constexpr {
|
||||
std::basic_string<CharT> out = std::format(loc, fmt.template sv<CharT>(), args...);
|
||||
if constexpr (std::same_as<CharT, char>)
|
||||
if (out != expected)
|
||||
std::cerr << "\nFormat string " << fmt.template sv<CharT>() << "\nExpected output " << expected
|
||||
<< "\nActual output " << out << '\n';
|
||||
assert(out == expected);
|
||||
};
|
||||
|
||||
inline constexpr auto check_exception =
|
||||
[]<class CharT, class... Args>(
|
||||
[[maybe_unused]] std::string_view what,
|
||||
[[maybe_unused]] std::basic_string_view<CharT> fmt,
|
||||
[[maybe_unused]] const Args&... args) {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
try {
|
||||
TEST_IGNORE_NODISCARD std::vformat(fmt, std::make_format_args<format_context<CharT>>(args...));
|
||||
if constexpr (std::same_as<CharT, char>)
|
||||
std::cerr << "\nFormat string " << fmt << "\nDidn't throw an exception.\n";
|
||||
assert(false);
|
||||
} catch (const std::format_error& e) {
|
||||
# if defined(_LIBCPP_VERSION)
|
||||
if constexpr (std::same_as<CharT, char>)
|
||||
if (e.what() != what)
|
||||
std::cerr << "\nFormat string " << fmt << "\nExpected exception " << what << "\nActual exception "
|
||||
<< e.what() << '\n';
|
||||
assert(e.what() == what);
|
||||
# endif
|
||||
return;
|
||||
}
|
||||
assert(false);
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class CharT, class T>
|
||||
void check_invalid_type(const std::set<std::basic_string_view<CharT>>& valid_types,
|
||||
std::string_view what,
|
||||
std::basic_string<CharT> type,
|
||||
const T& arg) {
|
||||
std::basic_string<CharT> fmt{STR("{:%") + type + STR("}")};
|
||||
|
||||
if (valid_types.contains(std::basic_string_view<CharT>{type})) {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
TEST_IGNORE_NODISCARD std::vformat(
|
||||
std::basic_string_view<CharT>{fmt}, std::make_format_args<format_context<CharT>>(arg));
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
} catch (const std::format_error& e) {
|
||||
# if defined(_LIBCPP_VERSION)
|
||||
if constexpr (std::same_as<CharT, char>)
|
||||
std::cerr << "\nFormat string " << fmt << "\nUnexpected exception " << e.what() << '\n';
|
||||
# endif
|
||||
assert(false);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
check_exception(what, std::basic_string_view<CharT>{fmt}, arg);
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT, class T>
|
||||
void check_invalid_types(const std::set<std::basic_string_view<CharT>>& valid_types, const T& arg) {
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a weekday", STR("a"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a weekday", STR("A"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a month", STR("b"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a month", STR("B"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a date and time", STR("c"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a year", STR("C"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a day", STR("d"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a date", STR("D"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a day", STR("e"), arg);
|
||||
// E - the modifier is checked separately
|
||||
check_invalid_type(valid_types, "The date time type specifier is invalid", STR("f"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a date", STR("F"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a date", STR("g"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a date", STR("G"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a month", STR("h"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain an hour", STR("H"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier is invalid", STR("i"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain an hour", STR("I"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a date or duration", STR("j"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier is invalid", STR("J"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier is invalid", STR("k"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier is invalid", STR("K"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier is invalid", STR("l"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier is invalid", STR("L"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a month", STR("m"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a minute", STR("M"), arg);
|
||||
// n - valid
|
||||
check_invalid_type(valid_types, "The date time type specifier is invalid", STR("N"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier is invalid", STR("o"), arg);
|
||||
// O - the modifier is checked separately
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain an hour", STR("p"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier is invalid", STR("P"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a duration", STR("q"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a duration", STR("Q"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a time", STR("r"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a time", STR("R"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier is invalid", STR("s"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a second", STR("S"), arg);
|
||||
// t - valid
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a time", STR("T"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a weekday", STR("u"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a date", STR("U"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier is invalid", STR("v"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a date", STR("V"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a weekday", STR("w"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a date", STR("W"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a date", STR("x"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a time", STR("X"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a year", STR("y"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a year", STR("y"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a time zone", STR("z"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a time zone", STR("Z"), arg);
|
||||
|
||||
// *** E modifier
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Ea"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EA"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Eb"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EB"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a date and time", STR("Ec"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a year", STR("EC"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Ed"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("ED"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Ee"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EE"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Ef"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EF"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Eg"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EG"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Eh"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EH"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Ei"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EI"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Ej"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EJ"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Ek"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EK"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("El"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EL"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Em"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EM"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("En"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EN"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Eo"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EO"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Ep"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EP"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Eq"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EQ"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Er"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("ER"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Es"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("ES"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Et"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("ET"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Eu"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EU"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Ev"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EV"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("Ew"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EW"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a date", STR("Ex"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a time", STR("EX"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a year", STR("Ey"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a year", STR("EY"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a time zone", STR("Ez"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("EZ"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid", STR("E%"), arg);
|
||||
|
||||
// *** O modifier
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Oa"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OA"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Ob"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OB"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Oc"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OC"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a day", STR("Od"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OD"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a day", STR("Oe"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OE"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Of"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OF"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Og"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OG"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Oh"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain an hour", STR("OH"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Oi"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain an hour", STR("OI"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Oj"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OJ"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Ok"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OK"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Ol"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OL"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a month", STR("Om"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a minute", STR("OM"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("On"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("ON"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Oo"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OO"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Op"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OP"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Oq"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OQ"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Or"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OR"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Os"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a second", STR("OS"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Ot"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OT"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a weekday", STR("Ou"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a date", STR("OU"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Ov"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a date", STR("OV"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a weekday", STR("Ow"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a date", STR("OW"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("Ox"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OX"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a year", STR("Oy"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OY"), arg);
|
||||
check_invalid_type(valid_types, "The supplied date time doesn't contain a time zone", STR("Oz"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("OZ"), arg);
|
||||
check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid", STR("O%"), arg);
|
||||
}
|
||||
|
||||
#endif // TEST_STD_TIME_TIME_SYN_FORMATTER_TESTS_H
|
|
@ -164,6 +164,16 @@ void test_P0645() {
|
|||
// enabled.
|
||||
template <class CharT>
|
||||
void test_P1361() {
|
||||
// The chrono formatters require localization support.
|
||||
// [time.format]/7
|
||||
// If the chrono-specs is omitted, the chrono object is formatted as if by
|
||||
// streaming it to std::ostringstream os with the formatting
|
||||
// locale imbued and copying os.str() through the output iterator of the
|
||||
// context with additional padding and adjustments as specified by the format
|
||||
// specifiers.
|
||||
// In libc++ std:::ostringstream requires localization support.
|
||||
#ifndef TEST_HAS_NO_LOCALIZATION
|
||||
|
||||
assert_formatter_is_disabled<std::chrono::microseconds, CharT>();
|
||||
|
||||
assert_formatter_is_disabled<std::chrono::sys_time<std::chrono::microseconds>, CharT>();
|
||||
|
@ -173,7 +183,7 @@ void test_P1361() {
|
|||
assert_formatter_is_disabled<std::chrono::file_time<std::chrono::microseconds>, CharT>();
|
||||
assert_formatter_is_disabled<std::chrono::local_time<std::chrono::microseconds>, CharT>();
|
||||
|
||||
assert_formatter_is_disabled<std::chrono::day, CharT>();
|
||||
assert_formatter_is_enabled<std::chrono::day, CharT>();
|
||||
assert_formatter_is_disabled<std::chrono::month, CharT>();
|
||||
assert_formatter_is_disabled<std::chrono::year, CharT>();
|
||||
|
||||
|
@ -198,6 +208,8 @@ void test_P1361() {
|
|||
//assert_formatter_is_enabled<std::chrono::local_info, CharT>();
|
||||
|
||||
//assert_formatter_is_enabled<std::chrono::zoned_time, CharT>();
|
||||
|
||||
#endif // TEST_HAS_NO_LOCALIZATION
|
||||
}
|
||||
|
||||
// Tests for P1636 Formatters for library types
|
||||
|
|
|
@ -187,10 +187,12 @@ check-generated-output)
|
|||
# Depends on LC_COLLATE set at the top of this script.
|
||||
! grep -rn '[^ -~]' libcxx/include libcxx/src libcxx/test libcxx/benchmarks \
|
||||
--exclude '*.dat' \
|
||||
--exclude 'std_format_spec_string_unicode.bench.cpp' \
|
||||
--exclude 'format_tests.h' \
|
||||
--exclude 'formatter.day.pass.cpp' \
|
||||
--exclude 'grep.pass.cpp' \
|
||||
--exclude 'locale-specific_form.pass.cpp' \
|
||||
--exclude 'format_tests.h' || false
|
||||
--exclude 'std_format_spec_string_unicode.bench.cpp' \
|
||||
|| false
|
||||
|
||||
# Reject code with trailing whitespace
|
||||
! grep -rn '[[:blank:]]$' libcxx/include libcxx/src libcxx/test libcxx/benchmarks || false
|
||||
|
|
Loading…
Reference in New Issue