Add native and generic representation for filesystem::path format spec (#3729)

This commit is contained in:
js324 2023-11-29 17:49:36 -05:00 committed by GitHub
parent 5cfd28d476
commit b87ea22e29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 4 deletions

View File

@ -114,6 +114,7 @@ template <typename Char> struct formatter<std::filesystem::path, Char> {
format_specs<Char> specs_; format_specs<Char> specs_;
detail::arg_ref<Char> width_ref_; detail::arg_ref<Char> width_ref_;
bool debug_ = false; bool debug_ = false;
char path_type_ = 'n';
public: public:
FMT_CONSTEXPR void set_debug_format(bool set = true) { debug_ = set; } FMT_CONSTEXPR void set_debug_format(bool set = true) { debug_ = set; }
@ -130,20 +131,30 @@ template <typename Char> struct formatter<std::filesystem::path, Char> {
debug_ = true; debug_ = true;
++it; ++it;
} }
if (it != end && (*it == 'g' || *it == 'n')) {
path_type_ = *it++;
}
return it; return it;
} }
template <typename FormatContext> template <typename FormatContext>
auto format(const std::filesystem::path& p, FormatContext& ctx) const { auto format(const std::filesystem::path& p, FormatContext& ctx) const {
auto specs = specs_; auto specs = specs_;
auto path_type = path_type_;
# ifdef _WIN32
auto path_string = path_type == 'n' ? p.native() : p.generic_wstring();
# else
auto path_string = path_type == 'n' ? p.native() : p.generic_string();
# endif
detail::handle_dynamic_spec<detail::width_checker>(specs.width, width_ref_, detail::handle_dynamic_spec<detail::width_checker>(specs.width, width_ref_,
ctx); ctx);
if (!debug_) { if (!debug_) {
auto s = detail::get_path_string<Char>(p, p.native()); auto s = detail::get_path_string<Char>(p, path_string);
return detail::write(ctx.out(), basic_string_view<Char>(s), specs); return detail::write(ctx.out(), basic_string_view<Char>(s), specs);
} }
auto quoted = basic_memory_buffer<Char>(); auto quoted = basic_memory_buffer<Char>();
detail::write_escaped_path(quoted, p, p.native()); detail::write_escaped_path(quoted, p, path_string);
return detail::write(ctx.out(), return detail::write(ctx.out(),
basic_string_view<Char>(quoted.data(), quoted.size()), basic_string_view<Char>(quoted.data(), quoted.size()),
specs); specs);

View File

@ -25,15 +25,20 @@ TEST(std_test, path) {
EXPECT_EQ(fmt::format("{}", path("foo\"bar")), "foo\"bar"); EXPECT_EQ(fmt::format("{}", path("foo\"bar")), "foo\"bar");
EXPECT_EQ(fmt::format("{:?}", path("foo\"bar")), "\"foo\\\"bar\""); EXPECT_EQ(fmt::format("{:?}", path("foo\"bar")), "\"foo\\\"bar\"");
EXPECT_EQ(fmt::format("{:n}", path("/usr/bin")), "/usr/bin");
EXPECT_EQ(fmt::format("{:g}", path("/usr/bin")), "/usr/bin");
# ifdef _WIN32
EXPECT_EQ(fmt::format("{:n}", path("C:\\foo")), "C:\\foo");
EXPECT_EQ(fmt::format("{:g}", path("C:\\foo")), "C:/foo");
# ifdef _WIN32
EXPECT_EQ(fmt::format("{}", path( EXPECT_EQ(fmt::format("{}", path(
L"\x0428\x0447\x0443\x0447\x044B\x043D\x0448" L"\x0428\x0447\x0443\x0447\x044B\x043D\x0448"
L"\x0447\x044B\x043D\x0430")), L"\x0447\x044B\x043D\x0430")),
"Шчучыншчына"); "Шчучыншчына");
EXPECT_EQ(fmt::format("{}", path(L"\xd800")), "<EFBFBD>"); EXPECT_EQ(fmt::format("{}", path(L"\xd800")), "<EFBFBD>");
EXPECT_EQ(fmt::format("{:?}", path(L"\xd800")), "\"\\ud800\""); EXPECT_EQ(fmt::format("{:?}", path(L"\xd800")), "\"\\ud800\"");
# endif # endif
} }
// Test ambiguity problem described in #2954. // Test ambiguity problem described in #2954.