Implement compile-time checks by default
This commit is contained in:
parent
befd7d4a2f
commit
bcc20b29df
4
.github/workflows/linux.yml
vendored
4
.github/workflows/linux.yml
vendored
@ -17,6 +17,9 @@ jobs:
|
||||
std: 14
|
||||
- cxx: g++-10
|
||||
std: 17
|
||||
- cxx: g++-10
|
||||
std: 20
|
||||
cxxflags: -DFMT_COMPILE_TIME_CHECKS=1
|
||||
- cxx: clang++-9
|
||||
std: 11
|
||||
- cxx: clang++-9
|
||||
@ -36,6 +39,7 @@ jobs:
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
env:
|
||||
CXX: ${{matrix.cxx}}
|
||||
CXXFLAGS: ${{matrix.cxxflags}}
|
||||
run: |
|
||||
cmake -DCMAKE_BUILD_TYPE=${{matrix.build_type}} ${{matrix.fuzz}} \
|
||||
-DCMAKE_CXX_STANDARD=${{matrix.std}} -DFMT_DOC=OFF \
|
||||
|
@ -404,20 +404,20 @@ struct formatter<std::chrono::time_point<std::chrono::system_clock>, Char>
|
||||
};
|
||||
|
||||
template <typename Char> struct formatter<std::tm, Char> {
|
||||
template <typename ParseContext>
|
||||
auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
|
||||
auto it = ctx.begin();
|
||||
if (it != ctx.end() && *it == ':') ++it;
|
||||
auto end = it;
|
||||
while (end != ctx.end() && *end != '}') ++end;
|
||||
tm_format.reserve(detail::to_unsigned(end - it + 1));
|
||||
tm_format.append(it, end);
|
||||
tm_format.push_back('\0');
|
||||
specs = {it, detail::to_unsigned(end - it)};
|
||||
return end;
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const std::tm& tm, FormatContext& ctx) -> decltype(ctx.out()) {
|
||||
basic_memory_buffer<Char> tm_format;
|
||||
tm_format.append(specs.begin(), specs.end());
|
||||
tm_format.push_back('\0');
|
||||
basic_memory_buffer<Char> buf;
|
||||
size_t start = buf.size();
|
||||
for (;;) {
|
||||
@ -440,7 +440,7 @@ template <typename Char> struct formatter<std::tm, Char> {
|
||||
return std::copy(buf.begin(), buf.end(), ctx.out());
|
||||
}
|
||||
|
||||
basic_memory_buffer<Char> tm_format;
|
||||
basic_string_view<Char> specs;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
@ -638,28 +638,29 @@ FMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin,
|
||||
struct chrono_format_checker {
|
||||
FMT_NORETURN void report_no_date() { FMT_THROW(format_error("no date")); }
|
||||
|
||||
template <typename Char> void on_text(const Char*, const Char*) {}
|
||||
template <typename Char>
|
||||
FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
|
||||
FMT_NORETURN void on_abbr_weekday() { report_no_date(); }
|
||||
FMT_NORETURN void on_full_weekday() { report_no_date(); }
|
||||
FMT_NORETURN void on_dec0_weekday(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_dec1_weekday(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_abbr_month() { report_no_date(); }
|
||||
FMT_NORETURN void on_full_month() { report_no_date(); }
|
||||
void on_24_hour(numeric_system) {}
|
||||
void on_12_hour(numeric_system) {}
|
||||
void on_minute(numeric_system) {}
|
||||
void on_second(numeric_system) {}
|
||||
FMT_CONSTEXPR void on_24_hour(numeric_system) {}
|
||||
FMT_CONSTEXPR void on_12_hour(numeric_system) {}
|
||||
FMT_CONSTEXPR void on_minute(numeric_system) {}
|
||||
FMT_CONSTEXPR void on_second(numeric_system) {}
|
||||
FMT_NORETURN void on_datetime(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_loc_date(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_loc_time(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_us_date() { report_no_date(); }
|
||||
FMT_NORETURN void on_iso_date() { report_no_date(); }
|
||||
void on_12_hour_time() {}
|
||||
void on_24_hour_time() {}
|
||||
void on_iso_time() {}
|
||||
void on_am_pm() {}
|
||||
void on_duration_value() {}
|
||||
void on_duration_unit() {}
|
||||
FMT_CONSTEXPR void on_12_hour_time() {}
|
||||
FMT_CONSTEXPR void on_24_hour_time() {}
|
||||
FMT_CONSTEXPR void on_iso_time() {}
|
||||
FMT_CONSTEXPR void on_am_pm() {}
|
||||
FMT_CONSTEXPR void on_duration_value() {}
|
||||
FMT_CONSTEXPR void on_duration_unit() {}
|
||||
FMT_NORETURN void on_utc_offset() { report_no_date(); }
|
||||
FMT_NORETURN void on_tz_name() { report_no_date(); }
|
||||
};
|
||||
@ -1033,11 +1034,11 @@ template <typename Rep, typename Period, typename Char>
|
||||
struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
private:
|
||||
basic_format_specs<Char> specs;
|
||||
int precision;
|
||||
int precision = -1;
|
||||
using arg_ref_type = detail::arg_ref<Char>;
|
||||
arg_ref_type width_ref;
|
||||
arg_ref_type precision_ref;
|
||||
mutable basic_string_view<Char> format_str;
|
||||
basic_string_view<Char> format_str;
|
||||
using duration = std::chrono::duration<Rep, Period>;
|
||||
|
||||
struct spec_handler {
|
||||
@ -1060,17 +1061,21 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
}
|
||||
|
||||
void on_error(const char* msg) { FMT_THROW(format_error(msg)); }
|
||||
void on_fill(basic_string_view<Char> fill) { f.specs.fill = fill; }
|
||||
void on_align(align_t align) { f.specs.align = align; }
|
||||
void on_width(int width) { f.specs.width = width; }
|
||||
void on_precision(int _precision) { f.precision = _precision; }
|
||||
void end_precision() {}
|
||||
FMT_CONSTEXPR void on_fill(basic_string_view<Char> fill) {
|
||||
f.specs.fill = fill;
|
||||
}
|
||||
FMT_CONSTEXPR void on_align(align_t align) { f.specs.align = align; }
|
||||
FMT_CONSTEXPR void on_width(int width) { f.specs.width = width; }
|
||||
FMT_CONSTEXPR void on_precision(int _precision) {
|
||||
f.precision = _precision;
|
||||
}
|
||||
FMT_CONSTEXPR void end_precision() {}
|
||||
|
||||
template <typename Id> void on_dynamic_width(Id arg_id) {
|
||||
template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {
|
||||
f.width_ref = make_arg_ref(arg_id);
|
||||
}
|
||||
|
||||
template <typename Id> void on_dynamic_precision(Id arg_id) {
|
||||
template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {
|
||||
f.precision_ref = make_arg_ref(arg_id);
|
||||
}
|
||||
};
|
||||
@ -1100,8 +1105,6 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
}
|
||||
|
||||
public:
|
||||
formatter() : precision(-1) {}
|
||||
|
||||
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
|
||||
-> decltype(ctx.begin()) {
|
||||
auto range = do_parse(ctx);
|
||||
|
@ -249,6 +249,10 @@
|
||||
# pragma execution_character_set("utf-8")
|
||||
#endif
|
||||
|
||||
#ifndef FMT_COMPILE_TIME_CHECKS
|
||||
# define FMT_COMPILE_TIME_CHECKS 0
|
||||
#endif
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
// Implementations of enable_if_t and other metafunctions for older systems.
|
||||
@ -1864,7 +1868,9 @@ FMT_INLINE std::basic_string<Char> vformat(
|
||||
*/
|
||||
// Pass char_t as a default template parameter instead of using
|
||||
// std::basic_string<char_t<S>> to reduce the symbol size.
|
||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||
template <typename S, typename... Args, typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(!FMT_COMPILE_TIME_CHECKS ||
|
||||
!std::is_same<Char, char>::value)>
|
||||
FMT_INLINE std::basic_string<Char> format(const S& format_str, Args&&... args) {
|
||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
||||
return detail::vformat(to_string_view(format_str), vargs);
|
||||
|
@ -2652,7 +2652,8 @@ struct stringifier {
|
||||
} // namespace detail
|
||||
|
||||
template <> struct formatter<detail::bigint> {
|
||||
format_parse_context::iterator parse(format_parse_context& ctx) {
|
||||
FMT_CONSTEXPR format_parse_context::iterator parse(
|
||||
format_parse_context& ctx) {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
|
@ -3065,7 +3065,7 @@ FMT_CONSTEXPR const typename ParseContext::char_type* parse_format_specs(
|
||||
using mapped_type =
|
||||
conditional_t<detail::mapped_type_constant<T, context>::value !=
|
||||
type::custom_type,
|
||||
decltype(arg_mapper<context>().map(std::declval<T>())), T>;
|
||||
decltype(arg_mapper<context>().map(std::declval<const T&>())), T>;
|
||||
auto f = conditional_t<has_formatter<mapped_type, context>::value,
|
||||
formatter<mapped_type, char_type>,
|
||||
detail::fallback_formatter<T, char_type>>();
|
||||
@ -3561,7 +3561,7 @@ template <typename Char = char> class dynamic_formatter {
|
||||
|
||||
public:
|
||||
template <typename ParseContext>
|
||||
auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
format_str_ = ctx.begin();
|
||||
// Checks are deferred to formatting time when the argument type is known.
|
||||
detail::dynamic_specs_handler<ParseContext> handler(specs_, ctx);
|
||||
@ -3864,6 +3864,30 @@ make_format_to_n_args(const Args&... args) {
|
||||
return format_arg_store<buffer_context<Char>, Args...>(args...);
|
||||
}
|
||||
|
||||
#if FMT_COMPILE_TIME_CHECKS
|
||||
template <typename... Args> struct format_string {
|
||||
string_view str;
|
||||
|
||||
template <size_t N> consteval format_string(const char (&s)[N]) : str(s) {
|
||||
if constexpr (detail::count_named_args<Args...>() == 0) {
|
||||
using checker = detail::format_string_checker<char, detail::error_handler,
|
||||
remove_cvref_t<Args>...>;
|
||||
detail::parse_format_string<true>(string_view(s, N), checker(s, {}));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T,
|
||||
FMT_ENABLE_IF(std::is_constructible_v<string_view, const T&>)>
|
||||
format_string(const T& s) : str(s) {}
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
FMT_INLINE std::string format(
|
||||
format_string<std::type_identity_t<Args>...> format_str, Args&&... args) {
|
||||
return detail::vformat(format_str.str, make_format_args(args...));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Char, enable_if_t<(!std::is_same<Char, char>::value), int>>
|
||||
std::basic_string<Char> detail::vformat(
|
||||
basic_string_view<Char> format_str,
|
||||
|
@ -36,20 +36,18 @@ struct formatting_range : formatting_base<Char> {
|
||||
static FMT_CONSTEXPR_DECL const size_t range_length_limit =
|
||||
FMT_RANGE_OUTPUT_LENGTH_LIMIT; // output only up to N items from the
|
||||
// range.
|
||||
Char prefix;
|
||||
Char delimiter;
|
||||
Char postfix;
|
||||
formatting_range() : prefix('{'), delimiter(','), postfix('}') {}
|
||||
Char prefix = '{';
|
||||
Char delimiter = ',';
|
||||
Char postfix = '}';
|
||||
static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
|
||||
static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
|
||||
};
|
||||
|
||||
template <typename Char, typename Enable = void>
|
||||
struct formatting_tuple : formatting_base<Char> {
|
||||
Char prefix;
|
||||
Char delimiter;
|
||||
Char postfix;
|
||||
formatting_tuple() : prefix('('), delimiter(','), postfix(')') {}
|
||||
Char prefix = '(';
|
||||
Char delimiter = ',';
|
||||
Char postfix = ')';
|
||||
static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
|
||||
static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
|
||||
};
|
||||
|
@ -148,7 +148,7 @@ endif ()
|
||||
|
||||
message(STATUS "FMT_PEDANTIC: ${FMT_PEDANTIC}")
|
||||
|
||||
if (FMT_PEDANTIC)
|
||||
if (FMT_PEDANTIC AND CXX_STANDARD LESS 20)
|
||||
# MSVC fails to compile GMock when C++17 is enabled.
|
||||
if (FMT_HAS_VARIANT AND NOT MSVC)
|
||||
add_fmt_test(std-format-test)
|
||||
|
@ -96,12 +96,14 @@ TEST(TimeTest, GMTime) {
|
||||
}
|
||||
|
||||
TEST(TimeTest, TimePoint) {
|
||||
std::chrono::system_clock::time_point point = std::chrono::system_clock::now();
|
||||
std::chrono::system_clock::time_point point =
|
||||
std::chrono::system_clock::now();
|
||||
|
||||
std::time_t t = std::chrono::system_clock::to_time_t(point);
|
||||
std::tm tm = *std::localtime(&t);
|
||||
char strftime_output[256];
|
||||
std::strftime(strftime_output, sizeof(strftime_output), "It is %Y-%m-%d %H:%M:%S", &tm);
|
||||
std::strftime(strftime_output, sizeof(strftime_output),
|
||||
"It is %Y-%m-%d %H:%M:%S", &tm);
|
||||
|
||||
EXPECT_EQ(strftime_output, fmt::format("It is {:%Y-%m-%d %H:%M:%S}", point));
|
||||
}
|
||||
@ -246,25 +248,25 @@ TEST(ChronoTest, FormatSpecs) {
|
||||
|
||||
TEST(ChronoTest, InvalidSpecs) {
|
||||
auto sec = std::chrono::seconds(0);
|
||||
EXPECT_THROW_MSG(fmt::format("{:%a}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format("{:%A}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format("{:%c}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format("{:%x}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format("{:%Ex}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format("{:%X}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format("{:%EX}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format("{:%D}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format("{:%F}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format("{:%Ec}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format("{:%w}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format("{:%u}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format("{:%b}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format("{:%B}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format("{:%z}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format("{:%Z}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format("{:%Eq}", sec), fmt::format_error,
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%a}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%A}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%c}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%x}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%Ex}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%X}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%EX}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%D}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%F}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%Ec}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%w}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%u}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%b}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%B}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%z}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%Z}", sec), fmt::format_error, "no date");
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%Eq}", sec), fmt::format_error,
|
||||
"invalid format");
|
||||
EXPECT_THROW_MSG(fmt::format("{:%Oq}", sec), fmt::format_error,
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:%Oq}", sec), fmt::format_error,
|
||||
"invalid format");
|
||||
}
|
||||
|
||||
@ -307,7 +309,7 @@ TEST(ChronoTest, FormatDefaultFP) {
|
||||
}
|
||||
|
||||
TEST(ChronoTest, FormatPrecision) {
|
||||
EXPECT_THROW_MSG(fmt::format("{:.2}", std::chrono::seconds(42)),
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:.2}", std::chrono::seconds(42)),
|
||||
fmt::format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_EQ("1.2ms", fmt::format("{:.1}", dms(1.234)));
|
||||
@ -334,7 +336,7 @@ TEST(ChronoTest, FormatSimpleQq) {
|
||||
}
|
||||
|
||||
TEST(ChronoTest, FormatPrecisionQq) {
|
||||
EXPECT_THROW_MSG(fmt::format("{:.2%Q %q}", std::chrono::seconds(42)),
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:.2%Q %q}", std::chrono::seconds(42)),
|
||||
fmt::format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_EQ("1.2 ms", fmt::format("{:.1%Q %q}", dms(1.234)));
|
||||
@ -351,12 +353,12 @@ TEST(ChronoTest, FormatFullSpecsQq) {
|
||||
}
|
||||
|
||||
TEST(ChronoTest, InvalidWidthId) {
|
||||
EXPECT_THROW(fmt::format("{:{o}", std::chrono::seconds(0)),
|
||||
EXPECT_THROW(fmt::format(+"{:{o}", std::chrono::seconds(0)),
|
||||
fmt::format_error);
|
||||
}
|
||||
|
||||
TEST(ChronoTest, InvalidColons) {
|
||||
EXPECT_THROW(fmt::format("{0}=:{0::", std::chrono::seconds(0)),
|
||||
EXPECT_THROW(fmt::format(+"{0}=:{0::", std::chrono::seconds(0)),
|
||||
fmt::format_error);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,9 @@
|
||||
#endif
|
||||
|
||||
#include "fmt/args.h"
|
||||
#if defined(FMT_COMPILE_TIME_CHECKS) && FMT_COMPILE_TIME_CHECKS
|
||||
# include "fmt/format.h"
|
||||
#endif
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
@ -633,7 +636,7 @@ template <> struct formatter<convertible_to_int> {
|
||||
};
|
||||
|
||||
template <> struct formatter<convertible_to_c_string> {
|
||||
auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
|
||||
FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
}
|
||||
auto format(convertible_to_c_string, format_context& ctx)
|
||||
@ -696,18 +699,10 @@ TYPED_TEST(IsStringTest, IsString) {
|
||||
}
|
||||
|
||||
TEST(CoreTest, Format) {
|
||||
// This should work without including fmt/format.h.
|
||||
#ifdef FMT_FORMAT_H_
|
||||
# error fmt/format.h must not be included in the core test
|
||||
#endif
|
||||
EXPECT_EQ(fmt::format("{}", 42), "42");
|
||||
}
|
||||
|
||||
TEST(CoreTest, FormatTo) {
|
||||
// This should work without including fmt/format.h.
|
||||
#ifdef FMT_FORMAT_H_
|
||||
# error fmt/format.h must not be included in the core test
|
||||
#endif
|
||||
std::string s;
|
||||
fmt::format_to(std::back_inserter(s), "{}", 42);
|
||||
EXPECT_EQ(s, "42");
|
||||
|
@ -521,9 +521,10 @@ TEST(FormatterTest, Escape) {
|
||||
}
|
||||
|
||||
TEST(FormatterTest, UnmatchedBraces) {
|
||||
EXPECT_THROW_MSG(format("{"), format_error, "invalid format string");
|
||||
EXPECT_THROW_MSG(format("}"), format_error, "unmatched '}' in format string");
|
||||
EXPECT_THROW_MSG(format("{0{}"), format_error, "invalid format string");
|
||||
EXPECT_THROW_MSG(format(+"{"), format_error, "invalid format string");
|
||||
EXPECT_THROW_MSG(format(+"}"), format_error,
|
||||
"unmatched '}' in format string");
|
||||
EXPECT_THROW_MSG(format(+"{0{}"), format_error, "invalid format string");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, NoArgs) { EXPECT_EQ("test", format("test")); }
|
||||
@ -539,22 +540,22 @@ TEST(FormatterTest, ArgsInDifferentPositions) {
|
||||
}
|
||||
|
||||
TEST(FormatterTest, ArgErrors) {
|
||||
EXPECT_THROW_MSG(format("{"), format_error, "invalid format string");
|
||||
EXPECT_THROW_MSG(format("{?}"), format_error, "invalid format string");
|
||||
EXPECT_THROW_MSG(format("{0"), format_error, "invalid format string");
|
||||
EXPECT_THROW_MSG(format("{0}"), format_error, "argument not found");
|
||||
EXPECT_THROW_MSG(format("{00}", 42), format_error, "invalid format string");
|
||||
EXPECT_THROW_MSG(format(+"{"), format_error, "invalid format string");
|
||||
EXPECT_THROW_MSG(format(+"{?}"), format_error, "invalid format string");
|
||||
EXPECT_THROW_MSG(format(+"{0"), format_error, "invalid format string");
|
||||
EXPECT_THROW_MSG(format(+"{0}"), format_error, "argument not found");
|
||||
EXPECT_THROW_MSG(format(+"{00}", 42), format_error, "invalid format string");
|
||||
|
||||
char format_str[BUFFER_SIZE];
|
||||
safe_sprintf(format_str, "{%u", INT_MAX);
|
||||
EXPECT_THROW_MSG(format(format_str), format_error, "invalid format string");
|
||||
EXPECT_THROW_MSG(format(+format_str), format_error, "invalid format string");
|
||||
safe_sprintf(format_str, "{%u}", INT_MAX);
|
||||
EXPECT_THROW_MSG(format(format_str), format_error, "argument not found");
|
||||
EXPECT_THROW_MSG(format(+format_str), format_error, "argument not found");
|
||||
|
||||
safe_sprintf(format_str, "{%u", INT_MAX + 1u);
|
||||
EXPECT_THROW_MSG(format(format_str), format_error, "number is too big");
|
||||
EXPECT_THROW_MSG(format(+format_str), format_error, "number is too big");
|
||||
safe_sprintf(format_str, "{%u}", INT_MAX + 1u);
|
||||
EXPECT_THROW_MSG(format(format_str), format_error, "number is too big");
|
||||
EXPECT_THROW_MSG(format(+format_str), format_error, "number is too big");
|
||||
}
|
||||
|
||||
template <int N> struct TestFormat {
|
||||
@ -595,22 +596,22 @@ TEST(FormatterTest, NamedArg) {
|
||||
fmt::arg("i", 0), fmt::arg("j", 0), fmt::arg("k", 0),
|
||||
fmt::arg("l", 0), fmt::arg("m", 0), fmt::arg("n", 0),
|
||||
fmt::arg("o", 0), fmt::arg("p", 0)));
|
||||
EXPECT_THROW_MSG(format("{a}"), format_error, "argument not found");
|
||||
EXPECT_THROW_MSG(format("{a}", 42), format_error, "argument not found");
|
||||
EXPECT_THROW_MSG(format(+"{a}"), format_error, "argument not found");
|
||||
EXPECT_THROW_MSG(format(+"{a}", 42), format_error, "argument not found");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, AutoArgIndex) {
|
||||
EXPECT_EQ("abc", format("{}{}{}", 'a', 'b', 'c'));
|
||||
EXPECT_THROW_MSG(format("{0}{}", 'a', 'b'), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0}{}", 'a', 'b'), format_error,
|
||||
"cannot switch from manual to automatic argument indexing");
|
||||
EXPECT_THROW_MSG(format("{}{0}", 'a', 'b'), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{}{0}", 'a', 'b'), format_error,
|
||||
"cannot switch from automatic to manual argument indexing");
|
||||
EXPECT_EQ("1.2", format("{:.{}}", 1.2345, 2));
|
||||
EXPECT_THROW_MSG(format("{0}:.{}", 1.2345, 2), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0}:.{}", 1.2345, 2), format_error,
|
||||
"cannot switch from manual to automatic argument indexing");
|
||||
EXPECT_THROW_MSG(format("{:.{0}}", 1.2345, 2), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{:.{0}}", 1.2345, 2), format_error,
|
||||
"cannot switch from automatic to manual argument indexing");
|
||||
EXPECT_THROW_MSG(format("{}"), format_error, "argument not found");
|
||||
EXPECT_THROW_MSG(format(+"{}"), format_error, "argument not found");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, EmptySpecs) { EXPECT_EQ("42", format("{0:}", 42)); }
|
||||
@ -671,9 +672,9 @@ TEST(FormatterTest, CenterAlign) {
|
||||
}
|
||||
|
||||
TEST(FormatterTest, Fill) {
|
||||
EXPECT_THROW_MSG(format("{0:{<5}", 'c'), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:{<5}", 'c'), format_error,
|
||||
"invalid fill character '{'");
|
||||
EXPECT_THROW_MSG(format("{0:{<5}}", 'c'), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:{<5}}", 'c'), format_error,
|
||||
"invalid fill character '{'");
|
||||
EXPECT_EQ("**42", format("{0:*>4}", 42));
|
||||
EXPECT_EQ("**-42", format("{0:*>5}", -42));
|
||||
@ -690,7 +691,7 @@ TEST(FormatterTest, Fill) {
|
||||
EXPECT_EQ("foo=", format("{:}=", "foo"));
|
||||
EXPECT_EQ(std::string("\0\0\0*", 4), format(string_view("{:\0>4}", 6), '*'));
|
||||
EXPECT_EQ("жж42", format("{0:ж>4}", 42));
|
||||
EXPECT_THROW_MSG(format("{:\x80\x80\x80\x80\x80>}", 0), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{:\x80\x80\x80\x80\x80>}", 0), format_error,
|
||||
"missing '}' in format string");
|
||||
}
|
||||
|
||||
@ -698,72 +699,72 @@ TEST(FormatterTest, PlusSign) {
|
||||
EXPECT_EQ("+42", format("{0:+}", 42));
|
||||
EXPECT_EQ("-42", format("{0:+}", -42));
|
||||
EXPECT_EQ("+42", format("{0:+}", 42));
|
||||
EXPECT_THROW_MSG(format("{0:+}", 42u), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:+}", 42u), format_error,
|
||||
"format specifier requires signed argument");
|
||||
EXPECT_EQ("+42", format("{0:+}", 42l));
|
||||
EXPECT_THROW_MSG(format("{0:+}", 42ul), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:+}", 42ul), format_error,
|
||||
"format specifier requires signed argument");
|
||||
EXPECT_EQ("+42", format("{0:+}", 42ll));
|
||||
EXPECT_THROW_MSG(format("{0:+}", 42ull), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:+}", 42ull), format_error,
|
||||
"format specifier requires signed argument");
|
||||
EXPECT_EQ("+42", format("{0:+}", 42.0));
|
||||
EXPECT_EQ("+42", format("{0:+}", 42.0l));
|
||||
EXPECT_THROW_MSG(format("{0:+", 'c'), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:+", 'c'), format_error,
|
||||
"missing '}' in format string");
|
||||
EXPECT_THROW_MSG(format("{0:+}", 'c'), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:+}", 'c'), format_error,
|
||||
"invalid format specifier for char");
|
||||
EXPECT_THROW_MSG(format("{0:+}", "abc"), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:+}", reinterpret_cast<void*>(0x42)), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:+}", "abc"), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format(+"{0:+}", reinterpret_cast<void*>(0x42)),
|
||||
format_error, "format specifier requires numeric argument");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, MinusSign) {
|
||||
EXPECT_EQ("42", format("{0:-}", 42));
|
||||
EXPECT_EQ("-42", format("{0:-}", -42));
|
||||
EXPECT_EQ("42", format("{0:-}", 42));
|
||||
EXPECT_THROW_MSG(format("{0:-}", 42u), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:-}", 42u), format_error,
|
||||
"format specifier requires signed argument");
|
||||
EXPECT_EQ("42", format("{0:-}", 42l));
|
||||
EXPECT_THROW_MSG(format("{0:-}", 42ul), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:-}", 42ul), format_error,
|
||||
"format specifier requires signed argument");
|
||||
EXPECT_EQ("42", format("{0:-}", 42ll));
|
||||
EXPECT_THROW_MSG(format("{0:-}", 42ull), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:-}", 42ull), format_error,
|
||||
"format specifier requires signed argument");
|
||||
EXPECT_EQ("42", format("{0:-}", 42.0));
|
||||
EXPECT_EQ("42", format("{0:-}", 42.0l));
|
||||
EXPECT_THROW_MSG(format("{0:-", 'c'), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:-", 'c'), format_error,
|
||||
"missing '}' in format string");
|
||||
EXPECT_THROW_MSG(format("{0:-}", 'c'), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:-}", 'c'), format_error,
|
||||
"invalid format specifier for char");
|
||||
EXPECT_THROW_MSG(format("{0:-}", "abc"), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:-}", reinterpret_cast<void*>(0x42)), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:-}", "abc"), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format(+"{0:-}", reinterpret_cast<void*>(0x42)),
|
||||
format_error, "format specifier requires numeric argument");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, SpaceSign) {
|
||||
EXPECT_EQ(" 42", format("{0: }", 42));
|
||||
EXPECT_EQ("-42", format("{0: }", -42));
|
||||
EXPECT_EQ(" 42", format("{0: }", 42));
|
||||
EXPECT_THROW_MSG(format("{0: }", 42u), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0: }", 42u), format_error,
|
||||
"format specifier requires signed argument");
|
||||
EXPECT_EQ(" 42", format("{0: }", 42l));
|
||||
EXPECT_THROW_MSG(format("{0: }", 42ul), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0: }", 42ul), format_error,
|
||||
"format specifier requires signed argument");
|
||||
EXPECT_EQ(" 42", format("{0: }", 42ll));
|
||||
EXPECT_THROW_MSG(format("{0: }", 42ull), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0: }", 42ull), format_error,
|
||||
"format specifier requires signed argument");
|
||||
EXPECT_EQ(" 42", format("{0: }", 42.0));
|
||||
EXPECT_EQ(" 42", format("{0: }", 42.0l));
|
||||
EXPECT_THROW_MSG(format("{0: ", 'c'), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0: ", 'c'), format_error,
|
||||
"missing '}' in format string");
|
||||
EXPECT_THROW_MSG(format("{0: }", 'c'), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0: }", 'c'), format_error,
|
||||
"invalid format specifier for char");
|
||||
EXPECT_THROW_MSG(format("{0: }", "abc"), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0: }", reinterpret_cast<void*>(0x42)), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0: }", "abc"), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format(+"{0: }", reinterpret_cast<void*>(0x42)),
|
||||
format_error, "format specifier requires numeric argument");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, SignNotTruncated) {
|
||||
@ -812,14 +813,14 @@ TEST(FormatterTest, HashFlag) {
|
||||
EXPECT_EQ("0.", format("{:#.0f}", 0.01));
|
||||
EXPECT_EQ("0.50", format("{:#.2g}", 0.5));
|
||||
EXPECT_EQ("0.", format("{:#.0f}", 0.5));
|
||||
EXPECT_THROW_MSG(format("{0:#", 'c'), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:#", 'c'), format_error,
|
||||
"missing '}' in format string");
|
||||
EXPECT_THROW_MSG(format("{0:#}", 'c'), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:#}", 'c'), format_error,
|
||||
"invalid format specifier for char");
|
||||
EXPECT_THROW_MSG(format("{0:#}", "abc"), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:#}", reinterpret_cast<void*>(0x42)), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:#}", "abc"), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format(+"{0:#}", reinterpret_cast<void*>(0x42)),
|
||||
format_error, "format specifier requires numeric argument");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, ZeroFlag) {
|
||||
@ -832,13 +833,13 @@ TEST(FormatterTest, ZeroFlag) {
|
||||
EXPECT_EQ("00042", format("{0:05}", 42ull));
|
||||
EXPECT_EQ("-000042", format("{0:07}", -42.0));
|
||||
EXPECT_EQ("-000042", format("{0:07}", -42.0l));
|
||||
EXPECT_THROW_MSG(format("{0:0", 'c'), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:0", 'c'), format_error,
|
||||
"missing '}' in format string");
|
||||
EXPECT_THROW_MSG(format("{0:05}", 'c'), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:05}", 'c'), format_error,
|
||||
"invalid format specifier for char");
|
||||
EXPECT_THROW_MSG(format("{0:05}", "abc"), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:05}", "abc"), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:05}", reinterpret_cast<void*>(0x42)),
|
||||
EXPECT_THROW_MSG(format(+"{0:05}", reinterpret_cast<void*>(0x42)),
|
||||
format_error, "format specifier requires numeric argument");
|
||||
}
|
||||
|
||||
@ -846,16 +847,16 @@ TEST(FormatterTest, Width) {
|
||||
char format_str[BUFFER_SIZE];
|
||||
safe_sprintf(format_str, "{0:%u", UINT_MAX);
|
||||
increment(format_str + 3);
|
||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||
EXPECT_THROW_MSG(format(+format_str, 0), format_error, "number is too big");
|
||||
size_t size = std::strlen(format_str);
|
||||
format_str[size] = '}';
|
||||
format_str[size + 1] = 0;
|
||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||
EXPECT_THROW_MSG(format(+format_str, 0), format_error, "number is too big");
|
||||
|
||||
safe_sprintf(format_str, "{0:%u", INT_MAX + 1u);
|
||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||
EXPECT_THROW_MSG(format(+format_str, 0), format_error, "number is too big");
|
||||
safe_sprintf(format_str, "{0:%u}", INT_MAX + 1u);
|
||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||
EXPECT_THROW_MSG(format(+format_str, 0), format_error, "number is too big");
|
||||
EXPECT_EQ(" -42", format("{0:4}", -42));
|
||||
EXPECT_EQ(" 42", format("{0:5}", 42u));
|
||||
EXPECT_EQ(" -42", format("{0:6}", -42l));
|
||||
@ -876,39 +877,40 @@ TEST(FormatterTest, RuntimeWidth) {
|
||||
char format_str[BUFFER_SIZE];
|
||||
safe_sprintf(format_str, "{0:{%u", UINT_MAX);
|
||||
increment(format_str + 4);
|
||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||
EXPECT_THROW_MSG(format(+format_str, 0), format_error, "number is too big");
|
||||
size_t size = std::strlen(format_str);
|
||||
format_str[size] = '}';
|
||||
format_str[size + 1] = 0;
|
||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||
EXPECT_THROW_MSG(format(+format_str, 0), format_error, "number is too big");
|
||||
format_str[size + 1] = '}';
|
||||
format_str[size + 2] = 0;
|
||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||
EXPECT_THROW_MSG(format(+format_str, 0), format_error, "number is too big");
|
||||
|
||||
EXPECT_THROW_MSG(format("{0:{", 0), format_error, "invalid format string");
|
||||
EXPECT_THROW_MSG(format("{0:{}", 0), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:{", 0), format_error, "invalid format string");
|
||||
EXPECT_THROW_MSG(format(+"{0:{}", 0), format_error,
|
||||
"cannot switch from manual to automatic argument indexing");
|
||||
EXPECT_THROW_MSG(format("{0:{?}}", 0), format_error, "invalid format string");
|
||||
EXPECT_THROW_MSG(format("{0:{1}}", 0), format_error, "argument not found");
|
||||
EXPECT_THROW_MSG(format(+"{0:{?}}", 0), format_error,
|
||||
"invalid format string");
|
||||
EXPECT_THROW_MSG(format(+"{0:{1}}", 0), format_error, "argument not found");
|
||||
|
||||
EXPECT_THROW_MSG(format("{0:{0:}}", 0), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:{0:}}", 0), format_error,
|
||||
"invalid format string");
|
||||
|
||||
EXPECT_THROW_MSG(format("{0:{1}}", 0, -1), format_error, "negative width");
|
||||
EXPECT_THROW_MSG(format("{0:{1}}", 0, (INT_MAX + 1u)), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:{1}}", 0, -1), format_error, "negative width");
|
||||
EXPECT_THROW_MSG(format(+"{0:{1}}", 0, (INT_MAX + 1u)), format_error,
|
||||
"number is too big");
|
||||
EXPECT_THROW_MSG(format("{0:{1}}", 0, -1l), format_error, "negative width");
|
||||
EXPECT_THROW_MSG(format(+"{0:{1}}", 0, -1l), format_error, "negative width");
|
||||
if (const_check(sizeof(long) > sizeof(int))) {
|
||||
long value = INT_MAX;
|
||||
EXPECT_THROW_MSG(format("{0:{1}}", 0, (value + 1)), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:{1}}", 0, (value + 1)), format_error,
|
||||
"number is too big");
|
||||
}
|
||||
EXPECT_THROW_MSG(format("{0:{1}}", 0, (INT_MAX + 1ul)), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:{1}}", 0, (INT_MAX + 1ul)), format_error,
|
||||
"number is too big");
|
||||
|
||||
EXPECT_THROW_MSG(format("{0:{1}}", 0, '0'), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:{1}}", 0, '0'), format_error,
|
||||
"width is not integer");
|
||||
EXPECT_THROW_MSG(format("{0:{1}}", 0, 0.0), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:{1}}", 0, 0.0), format_error,
|
||||
"width is not integer");
|
||||
|
||||
EXPECT_EQ(" -42", format("{0:{1}}", -42, 4));
|
||||
@ -929,49 +931,49 @@ TEST(FormatterTest, Precision) {
|
||||
char format_str[BUFFER_SIZE];
|
||||
safe_sprintf(format_str, "{0:.%u", UINT_MAX);
|
||||
increment(format_str + 4);
|
||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||
EXPECT_THROW_MSG(format(+format_str, 0), format_error, "number is too big");
|
||||
size_t size = std::strlen(format_str);
|
||||
format_str[size] = '}';
|
||||
format_str[size + 1] = 0;
|
||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||
EXPECT_THROW_MSG(format(+format_str, 0), format_error, "number is too big");
|
||||
|
||||
safe_sprintf(format_str, "{0:.%u", INT_MAX + 1u);
|
||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||
EXPECT_THROW_MSG(format(+format_str, 0), format_error, "number is too big");
|
||||
safe_sprintf(format_str, "{0:.%u}", INT_MAX + 1u);
|
||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||
EXPECT_THROW_MSG(format(+format_str, 0), format_error, "number is too big");
|
||||
|
||||
EXPECT_THROW_MSG(format("{0:.", 0), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.", 0), format_error,
|
||||
"missing precision specifier");
|
||||
EXPECT_THROW_MSG(format("{0:.}", 0), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.}", 0), format_error,
|
||||
"missing precision specifier");
|
||||
|
||||
EXPECT_THROW_MSG(format("{0:.2", 0), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.2", 0), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.2}", 42), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.2}", 42), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.2f}", 42), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.2f}", 42), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.2}", 42u), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.2}", 42u), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.2f}", 42u), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.2f}", 42u), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.2}", 42l), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.2}", 42l), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.2f}", 42l), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.2f}", 42l), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.2}", 42ul), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.2}", 42ul), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.2f}", 42ul), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.2f}", 42ul), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.2}", 42ll), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.2}", 42ll), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.2f}", 42ll), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.2f}", 42ll), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.2}", 42ull), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.2}", 42ull), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.2f}", 42ull), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.2f}", 42ull), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:3.0}", 'x'), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:3.0}", 'x'), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_EQ("1.2", format("{0:.2}", 1.2345));
|
||||
EXPECT_EQ("1.2", format("{0:.2}", 1.2345l));
|
||||
@ -1008,13 +1010,13 @@ TEST(FormatterTest, Precision) {
|
||||
EXPECT_EQ("1e+01", format("{:.0e}", 9.5));
|
||||
EXPECT_EQ("1.0e-34", fmt::format("{:.1e}", 1e-34));
|
||||
|
||||
EXPECT_THROW_MSG(format("{0:.2}", reinterpret_cast<void*>(0xcafe)),
|
||||
EXPECT_THROW_MSG(format(+"{0:.2}", reinterpret_cast<void*>(0xcafe)),
|
||||
format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.2f}", reinterpret_cast<void*>(0xcafe)),
|
||||
EXPECT_THROW_MSG(format(+"{0:.2f}", reinterpret_cast<void*>(0xcafe)),
|
||||
format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{:.{}e}", 42.0, fmt::detail::max_value<int>()),
|
||||
EXPECT_THROW_MSG(format(+"{:.{}e}", 42.0, fmt::detail::max_value<int>()),
|
||||
format_error, "number is too big");
|
||||
|
||||
EXPECT_EQ("st", format("{0:.2}", "str"));
|
||||
@ -1024,79 +1026,79 @@ TEST(FormatterTest, RuntimePrecision) {
|
||||
char format_str[BUFFER_SIZE];
|
||||
safe_sprintf(format_str, "{0:.{%u", UINT_MAX);
|
||||
increment(format_str + 5);
|
||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||
EXPECT_THROW_MSG(format(+format_str, 0), format_error, "number is too big");
|
||||
size_t size = std::strlen(format_str);
|
||||
format_str[size] = '}';
|
||||
format_str[size + 1] = 0;
|
||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||
EXPECT_THROW_MSG(format(+format_str, 0), format_error, "number is too big");
|
||||
format_str[size + 1] = '}';
|
||||
format_str[size + 2] = 0;
|
||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||
EXPECT_THROW_MSG(format(+format_str, 0), format_error, "number is too big");
|
||||
|
||||
EXPECT_THROW_MSG(format("{0:.{", 0), format_error, "invalid format string");
|
||||
EXPECT_THROW_MSG(format("{0:.{}", 0), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{", 0), format_error, "invalid format string");
|
||||
EXPECT_THROW_MSG(format(+"{0:.{}", 0), format_error,
|
||||
"cannot switch from manual to automatic argument indexing");
|
||||
EXPECT_THROW_MSG(format("{0:.{?}}", 0), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{?}}", 0), format_error,
|
||||
"invalid format string");
|
||||
EXPECT_THROW_MSG(format("{0:.{1}", 0, 0), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}", 0, 0), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.{1}}", 0), format_error, "argument not found");
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}}", 0), format_error, "argument not found");
|
||||
|
||||
EXPECT_THROW_MSG(format("{0:.{0:}}", 0), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{0:}}", 0), format_error,
|
||||
"invalid format string");
|
||||
|
||||
EXPECT_THROW_MSG(format("{0:.{1}}", 0, -1), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}}", 0, -1), format_error,
|
||||
"negative precision");
|
||||
EXPECT_THROW_MSG(format("{0:.{1}}", 0, (INT_MAX + 1u)), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}}", 0, (INT_MAX + 1u)), format_error,
|
||||
"number is too big");
|
||||
EXPECT_THROW_MSG(format("{0:.{1}}", 0, -1l), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}}", 0, -1l), format_error,
|
||||
"negative precision");
|
||||
if (const_check(sizeof(long) > sizeof(int))) {
|
||||
long value = INT_MAX;
|
||||
EXPECT_THROW_MSG(format("{0:.{1}}", 0, (value + 1)), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}}", 0, (value + 1)), format_error,
|
||||
"number is too big");
|
||||
}
|
||||
EXPECT_THROW_MSG(format("{0:.{1}}", 0, (INT_MAX + 1ul)), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}}", 0, (INT_MAX + 1ul)), format_error,
|
||||
"number is too big");
|
||||
|
||||
EXPECT_THROW_MSG(format("{0:.{1}}", 0, '0'), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}}", 0, '0'), format_error,
|
||||
"precision is not integer");
|
||||
EXPECT_THROW_MSG(format("{0:.{1}}", 0, 0.0), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}}", 0, 0.0), format_error,
|
||||
"precision is not integer");
|
||||
|
||||
EXPECT_THROW_MSG(format("{0:.{1}}", 42, 2), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}}", 42, 2), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.{1}f}", 42, 2), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}f}", 42, 2), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.{1}}", 42u, 2), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}}", 42u, 2), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.{1}f}", 42u, 2), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}f}", 42u, 2), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.{1}}", 42l, 2), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}}", 42l, 2), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.{1}f}", 42l, 2), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}f}", 42l, 2), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.{1}}", 42ul, 2), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}}", 42ul, 2), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.{1}f}", 42ul, 2), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}f}", 42ul, 2), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.{1}}", 42ll, 2), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}}", 42ll, 2), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.{1}f}", 42ll, 2), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}f}", 42ll, 2), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.{1}}", 42ull, 2), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}}", 42ull, 2), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.{1}f}", 42ull, 2), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}f}", 42ull, 2), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:3.{1}}", 'x', 0), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:3.{1}}", 'x', 0), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_EQ("1.2", format("{0:.{1}}", 1.2345, 2));
|
||||
EXPECT_EQ("1.2", format("{1:.{0}}", 2, 1.2345l));
|
||||
|
||||
EXPECT_THROW_MSG(format("{0:.{1}}", reinterpret_cast<void*>(0xcafe), 2),
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}}", reinterpret_cast<void*>(0xcafe), 2),
|
||||
format_error,
|
||||
"precision not allowed for this argument type");
|
||||
EXPECT_THROW_MSG(format("{0:.{1}f}", reinterpret_cast<void*>(0xcafe), 2),
|
||||
EXPECT_THROW_MSG(format(+"{0:.{1}f}", reinterpret_cast<void*>(0xcafe), 2),
|
||||
format_error,
|
||||
"precision not allowed for this argument type");
|
||||
|
||||
@ -1112,7 +1114,7 @@ void check_unknown_types(const T& value, const char* types, const char*) {
|
||||
if (std::strchr(types, c) || std::strchr(special, c) || !c) continue;
|
||||
safe_sprintf(format_str, "{0:10%c}", c);
|
||||
const char* message = "invalid type specifier";
|
||||
EXPECT_THROW_MSG(format(format_str, value), format_error, message)
|
||||
EXPECT_THROW_MSG(format(+format_str, value), format_error, message)
|
||||
<< format_str << " " << message;
|
||||
}
|
||||
}
|
||||
@ -1133,7 +1135,7 @@ TEST(FormatterTest, FormatShort) {
|
||||
}
|
||||
|
||||
TEST(FormatterTest, FormatInt) {
|
||||
EXPECT_THROW_MSG(format("{0:v", 42), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:v", 42), format_error,
|
||||
"missing '}' in format string");
|
||||
check_unknown_types(42, "bBdoxXnLc", "integer");
|
||||
EXPECT_EQ("x", format("{:c}", static_cast<int>('x')));
|
||||
@ -1437,7 +1439,7 @@ TEST(FormatterTest, FormatCString) {
|
||||
EXPECT_EQ("test", format("{0:s}", "test"));
|
||||
char nonconst[] = "nonconst";
|
||||
EXPECT_EQ("nonconst", format("{0}", nonconst));
|
||||
EXPECT_THROW_MSG(format("{0}", static_cast<const char*>(nullptr)),
|
||||
EXPECT_THROW_MSG(format(+"{0}", static_cast<const char*>(nullptr)),
|
||||
format_error, "string pointer is null");
|
||||
}
|
||||
|
||||
@ -1570,7 +1572,7 @@ FMT_END_NAMESPACE
|
||||
|
||||
TEST(FormatterTest, FormatCustom) {
|
||||
Date date(2012, 12, 9);
|
||||
EXPECT_THROW_MSG(fmt::format("{:s}", date), format_error,
|
||||
EXPECT_THROW_MSG(fmt::format(+"{:s}", date), format_error,
|
||||
"unknown format specifier");
|
||||
}
|
||||
|
||||
@ -1669,7 +1671,7 @@ TEST(FormatterTest, Examples) {
|
||||
format("int: {0:d}; hex: {0:#x}; oct: {0:#o}", 42));
|
||||
|
||||
EXPECT_EQ("The answer is 42", format("The answer is {}", 42));
|
||||
EXPECT_THROW_MSG(format("The answer is {:d}", "forty-two"), format_error,
|
||||
EXPECT_THROW_MSG(format(+"The answer is {:d}", "forty-two"), format_error,
|
||||
"invalid type specifier");
|
||||
|
||||
EXPECT_EQ(L"Cyrillic letter \x42e", format(L"Cyrillic letter {}", L'\x42e'));
|
||||
@ -1931,25 +1933,25 @@ TEST(FormatTest, DynamicFormatter) {
|
||||
EXPECT_EQ("42", format("{:d}", num));
|
||||
EXPECT_EQ("foo", format("{:s}", str));
|
||||
EXPECT_EQ(" 42 foo ", format("{:{}} {:{}}", num, 3, str, 4));
|
||||
EXPECT_THROW_MSG(format("{0:{}}", num), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:{}}", num), format_error,
|
||||
"cannot switch from manual to automatic argument indexing");
|
||||
EXPECT_THROW_MSG(format("{:{0}}", num), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{:{0}}", num), format_error,
|
||||
"cannot switch from automatic to manual argument indexing");
|
||||
#if FMT_DEPRECATED_NUMERIC_ALIGN
|
||||
EXPECT_THROW_MSG(format("{:=}", str), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{:=}", str), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
#endif
|
||||
EXPECT_THROW_MSG(format("{:+}", str), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{:+}", str), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{:-}", str), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{:-}", str), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{: }", str), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{: }", str), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{:#}", str), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{:#}", str), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{:0}", str), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{:0}", str), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{:.2}", num), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{:.2}", num), format_error,
|
||||
"precision not allowed for this argument type");
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ template <class charT> struct formatter<std::complex<double>, charT> {
|
||||
detail::dynamic_format_specs<char> specs_;
|
||||
|
||||
public:
|
||||
typename basic_format_parse_context<charT>::iterator parse(
|
||||
FMT_CONSTEXPR typename basic_format_parse_context<charT>::iterator parse(
|
||||
basic_format_parse_context<charT>& ctx) {
|
||||
using handler_type =
|
||||
detail::dynamic_specs_handler<basic_format_parse_context<charT>>;
|
||||
|
@ -97,20 +97,20 @@ TEST(OStreamTest, FormatSpecs) {
|
||||
EXPECT_EQ("def ", format("{0:<5}", TestString("def")));
|
||||
EXPECT_EQ(" def", format("{0:>5}", TestString("def")));
|
||||
#if FMT_DEPRECATED_NUMERIC_ALIGN
|
||||
EXPECT_THROW_MSG(format("{0:=5}", TestString("def")), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:=5}", TestString("def")), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
#endif
|
||||
EXPECT_EQ(" def ", format("{0:^5}", TestString("def")));
|
||||
EXPECT_EQ("def**", format("{0:*<5}", TestString("def")));
|
||||
EXPECT_THROW_MSG(format("{0:+}", TestString()), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:+}", TestString()), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:-}", TestString()), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:-}", TestString()), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0: }", TestString()), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0: }", TestString()), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:#}", TestString()), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:#}", TestString()), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:05}", TestString()), format_error,
|
||||
EXPECT_THROW_MSG(format(+"{0:05}", TestString()), format_error,
|
||||
"format specifier requires numeric argument");
|
||||
EXPECT_EQ("test ", format("{0:13}", TestString("test")));
|
||||
EXPECT_EQ("test ", format("{0:{1}}", TestString("test"), 13));
|
||||
|
Loading…
Reference in New Issue
Block a user