mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-10 05:10:05 +00:00
Fix fallback to runtime API from compile-time API (#2143)
* fix fallback to the runtime API, add FMT_ENABLE_FALLBACK_TO_RUNTIME_API define, add test * remove `FMT_ENABLE_FALLBACK_TO_RUNTIME_API` * pass format string to format_to() inside format_to_n() in compile-time API instead of compiling it inside format_to_n(), to eliminate code duplication
This commit is contained in:
parent
d8b9254301
commit
684b5b0e40
@ -704,12 +704,7 @@ constexpr auto compile(S format_str) {
|
|||||||
constexpr auto result =
|
constexpr auto result =
|
||||||
detail::compile_format_string<detail::type_list<Args...>, 0, 0>(
|
detail::compile_format_string<detail::type_list<Args...>, 0, 0>(
|
||||||
format_str);
|
format_str);
|
||||||
if constexpr (std::is_same<remove_cvref_t<decltype(result)>,
|
return result;
|
||||||
detail::unknown_format>()) {
|
|
||||||
return detail::compiled_format<S, Args...>(to_string_view(format_str));
|
|
||||||
} else {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -789,7 +784,17 @@ FMT_INLINE std::basic_string<typename S::char_type> format(const S&,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
constexpr auto compiled = detail::compile<Args...>(S());
|
constexpr auto compiled = detail::compile<Args...>(S());
|
||||||
|
#ifdef __cpp_if_constexpr
|
||||||
|
if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>,
|
||||||
|
detail::unknown_format>()) {
|
||||||
|
return format(static_cast<basic_string_view<typename S::char_type>>(S()),
|
||||||
|
std::forward<Args>(args)...);
|
||||||
|
} else {
|
||||||
|
return format(compiled, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
#else
|
||||||
return format(compiled, std::forward<Args>(args)...);
|
return format(compiled, std::forward<Args>(args)...);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIt, typename CompiledFormat, typename... Args,
|
template <typename OutputIt, typename CompiledFormat, typename... Args,
|
||||||
@ -805,9 +810,20 @@ constexpr OutputIt format_to(OutputIt out, const CompiledFormat& cf,
|
|||||||
|
|
||||||
template <typename OutputIt, typename S, typename... Args,
|
template <typename OutputIt, typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||||
FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, const Args&... args) {
|
FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) {
|
||||||
constexpr auto compiled = detail::compile<Args...>(S());
|
constexpr auto compiled = detail::compile<Args...>(S());
|
||||||
return format_to(out, compiled, args...);
|
#ifdef __cpp_if_constexpr
|
||||||
|
if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>,
|
||||||
|
detail::unknown_format>()) {
|
||||||
|
return format_to(out,
|
||||||
|
static_cast<basic_string_view<typename S::char_type>>(S()),
|
||||||
|
std::forward<Args>(args)...);
|
||||||
|
} else {
|
||||||
|
return format_to(out, compiled, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return format_to(out, compiled, std::forward<Args>(args)...);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIt, typename CompiledFormat, typename... Args>
|
template <typename OutputIt, typename CompiledFormat, typename... Args>
|
||||||
@ -827,10 +843,9 @@ auto format_to_n(OutputIt out, size_t n, const CompiledFormat& cf,
|
|||||||
template <typename OutputIt, typename S, typename... Args,
|
template <typename OutputIt, typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||||
format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n, const S&,
|
format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n, const S&,
|
||||||
const Args&... args) {
|
Args&&... args) {
|
||||||
constexpr auto compiled = detail::compile<Args...>(S());
|
auto it = format_to(detail::truncating_iterator<OutputIt>(out, n), S(),
|
||||||
auto it = format_to(detail::truncating_iterator<OutputIt>(out, n), compiled,
|
std::forward<Args>(args)...);
|
||||||
args...);
|
|
||||||
return {it.base(), it.count()};
|
return {it.base(), it.count()};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,6 +229,23 @@ TEST(CompileTest, TextAndArg) {
|
|||||||
EXPECT_EQ("42!", fmt::format(FMT_COMPILE("{}!"), 42));
|
EXPECT_EQ("42!", fmt::format(FMT_COMPILE("{}!"), 42));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(CompileTest, UnknownFormatFallback) {
|
||||||
|
EXPECT_EQ(" 42 ",
|
||||||
|
fmt::format(FMT_COMPILE("{name:^4}"), fmt::arg("name", 42)));
|
||||||
|
|
||||||
|
std::vector<char> v;
|
||||||
|
fmt::format_to(std::back_inserter(v), FMT_COMPILE("{name:^4}"),
|
||||||
|
fmt::arg("name", 42));
|
||||||
|
EXPECT_EQ(" 42 ", fmt::string_view(v.data(), v.size()));
|
||||||
|
|
||||||
|
char buffer[4];
|
||||||
|
auto result = fmt::format_to_n(buffer, 4, FMT_COMPILE("{name:^5}"),
|
||||||
|
fmt::arg("name", 42));
|
||||||
|
EXPECT_EQ(5u, result.size);
|
||||||
|
EXPECT_EQ(buffer + 4, result.out);
|
||||||
|
EXPECT_EQ(" 42 ", fmt::string_view(buffer, 4));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(CompileTest, Empty) { EXPECT_EQ("", fmt::format(FMT_COMPILE(""))); }
|
TEST(CompileTest, Empty) { EXPECT_EQ("", fmt::format(FMT_COMPILE(""))); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user