mirror of
https://github.com/fmtlib/fmt.git
synced 2024-12-24 03:17:53 +00:00
Provide more overloads for the wide string flavour
Signed-off-by: Daniela Engert <dani@ngrt.de>
This commit is contained in:
parent
ca31ca13f1
commit
2570f1afdc
@ -1098,7 +1098,11 @@ struct format_args: basic_format_args<format_context> {
|
||||
format_args(Args && ... arg)
|
||||
: basic_format_args<format_context>(std::forward<Args>(arg)...) {}
|
||||
};
|
||||
typedef basic_format_args<wformat_context> wformat_args;
|
||||
struct wformat_args : basic_format_args<wformat_context> {
|
||||
template <typename ...Args>
|
||||
wformat_args(Args && ... arg)
|
||||
: basic_format_args<wformat_context>(std::forward<Args>(arg)...) {}
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
template <typename Char>
|
||||
@ -1154,6 +1158,7 @@ void arg(S, internal::named_arg<T, Char>) FMT_DELETED;
|
||||
enum color { black, red, green, yellow, blue, magenta, cyan, white };
|
||||
|
||||
FMT_API void vprint_colored(color c, string_view format, format_args args);
|
||||
FMT_API void vprint_colored(color c, wstring_view format, wformat_args args);
|
||||
|
||||
/**
|
||||
Formats a string and prints it to stdout using ANSI escape sequences to
|
||||
@ -1167,6 +1172,12 @@ inline void print_colored(color c, string_view format_str,
|
||||
vprint_colored(c, format_str, make_format_args(args...));
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline void print_colored(color c, wstring_view format_str,
|
||||
const Args & ... args) {
|
||||
vprint_colored(c, format_str, make_format_args<wformat_context>(args...));
|
||||
}
|
||||
|
||||
format_context::iterator vformat_to(
|
||||
internal::buffer &buf, string_view format_str, format_args args);
|
||||
wformat_context::iterator vformat_to(
|
||||
@ -1193,6 +1204,17 @@ typename std::enable_if<
|
||||
return std::back_inserter(container);
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
typename std::enable_if<
|
||||
is_contiguous<Container>::value, std::back_insert_iterator<Container>>::type
|
||||
vformat_to(std::back_insert_iterator<Container> out,
|
||||
wstring_view format_str, wformat_args args) {
|
||||
auto& container = internal::get_container(out);
|
||||
internal::container_buffer<Container> buf(container);
|
||||
vformat_to(buf, format_str, args);
|
||||
return std::back_inserter(container);
|
||||
}
|
||||
|
||||
std::string vformat(string_view format_str, format_args args);
|
||||
std::wstring vformat(wstring_view format_str, wformat_args args);
|
||||
|
||||
@ -1221,6 +1243,7 @@ inline std::wstring format(wstring_view format_str, const Args & ... args) {
|
||||
}
|
||||
|
||||
FMT_API void vprint(std::FILE *f, string_view format_str, format_args args);
|
||||
FMT_API void vprint(std::FILE *f, wstring_view format_str, wformat_args args);
|
||||
|
||||
/**
|
||||
\rst
|
||||
@ -1236,8 +1259,14 @@ inline void print(std::FILE *f, string_view format_str, const Args & ... args) {
|
||||
format_arg_store<format_context, Args...> as(args...);
|
||||
vprint(f, format_str, as);
|
||||
}
|
||||
template <typename... Args>
|
||||
inline void print(std::FILE *f, wstring_view format_str, const Args & ... args) {
|
||||
format_arg_store<wformat_context, Args...> as(args...);
|
||||
vprint(f, format_str, as);
|
||||
}
|
||||
|
||||
FMT_API void vprint(string_view format_str, format_args args);
|
||||
FMT_API void vprint(wstring_view format_str, wformat_args args);
|
||||
|
||||
/**
|
||||
\rst
|
||||
@ -1253,6 +1282,12 @@ inline void print(string_view format_str, const Args & ... args) {
|
||||
format_arg_store<format_context, Args...> as(args...);
|
||||
vprint(format_str, as);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline void print(wstring_view format_str, const Args & ... args) {
|
||||
format_arg_store<wformat_context, Args...> as(args...);
|
||||
vprint(format_str, as);
|
||||
}
|
||||
} // namespace fmt
|
||||
|
||||
#endif // FMT_CORE_H_
|
||||
|
@ -96,6 +96,7 @@ inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
|
||||
#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
|
||||
|
||||
const char RESET_COLOR[] = "\x1b[0m";
|
||||
const wchar_t WRESET_COLOR[] = L"\x1b[0m";
|
||||
|
||||
typedef void (*FormatFunc)(internal::buffer &, int, string_view);
|
||||
|
||||
@ -489,10 +490,20 @@ FMT_FUNC void vprint(std::FILE *f, string_view format_str, format_args args) {
|
||||
std::fwrite(buffer.data(), 1, buffer.size(), f);
|
||||
}
|
||||
|
||||
FMT_FUNC void vprint(std::FILE *f, wstring_view format_str, wformat_args args) {
|
||||
wmemory_buffer buffer;
|
||||
vformat_to(buffer, format_str, args);
|
||||
std::fwrite(buffer.data(), sizeof(wchar_t), buffer.size(), f);
|
||||
}
|
||||
|
||||
FMT_FUNC void vprint(string_view format_str, format_args args) {
|
||||
vprint(stdout, format_str, args);
|
||||
}
|
||||
|
||||
FMT_FUNC void vprint(wstring_view format_str, wformat_args args) {
|
||||
vprint(stdout, format_str, args);
|
||||
}
|
||||
|
||||
FMT_FUNC void vprint_colored(color c, string_view format, format_args args) {
|
||||
char escape[] = "\x1b[30m";
|
||||
escape[3] = static_cast<char>('0' + c);
|
||||
@ -501,6 +512,14 @@ FMT_FUNC void vprint_colored(color c, string_view format, format_args args) {
|
||||
std::fputs(RESET_COLOR, stdout);
|
||||
}
|
||||
|
||||
FMT_FUNC void vprint_colored(color c, wstring_view format, wformat_args args) {
|
||||
wchar_t escape[] = L"\x1b[30m";
|
||||
escape[3] = static_cast<wchar_t>('0' + c);
|
||||
std::fputws(escape, stdout);
|
||||
vprint(format, args);
|
||||
std::fputws(WRESET_COLOR, stdout);
|
||||
}
|
||||
|
||||
FMT_FUNC locale locale_provider::locale() { return fmt::locale(); }
|
||||
|
||||
} // namespace fmt
|
||||
|
@ -3419,7 +3419,15 @@ inline typename std::enable_if<
|
||||
is_contiguous<Container>::value, std::back_insert_iterator<Container>>::type
|
||||
format_to(std::back_insert_iterator<Container> out,
|
||||
string_view format_str, const Args & ... args) {
|
||||
return vformat_to(out, format_str, make_format_args(args...));
|
||||
return vformat_to(out, format_str, make_format_args<format_context>(args...));
|
||||
}
|
||||
|
||||
template <typename Container, typename... Args>
|
||||
inline typename std::enable_if<
|
||||
is_contiguous<Container>::value, std::back_insert_iterator<Container>>::type
|
||||
format_to(std::back_insert_iterator<Container> out,
|
||||
wstring_view format_str, const Args & ... args) {
|
||||
return vformat_to(out, format_str, make_format_args<wformat_context>(args...));
|
||||
}
|
||||
|
||||
template <typename OutputIt>
|
||||
|
@ -121,12 +121,14 @@ struct formatter<T, Char,
|
||||
}
|
||||
};
|
||||
|
||||
inline void vprint(std::ostream &os, string_view format_str, format_args args) {
|
||||
memory_buffer buffer;
|
||||
template <typename Char>
|
||||
inline void vprint(std::basic_ostream<Char> &os,
|
||||
basic_string_view<Char> format_str,
|
||||
basic_format_args<typename buffer_context<Char>::type> args) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
vformat_to(buffer, format_str, args);
|
||||
internal::write(os, buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Prints formatted data to the stream *os*.
|
||||
@ -139,8 +141,15 @@ inline void vprint(std::ostream &os, string_view format_str, format_args args) {
|
||||
template <typename... Args>
|
||||
inline void print(std::ostream &os, string_view format_str,
|
||||
const Args & ... args) {
|
||||
vprint(os, format_str, make_format_args(args...));
|
||||
vprint(os, format_str, make_format_args<format_context>(args...));
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline void print(std::wostream &os, wstring_view format_str,
|
||||
const Args & ... args) {
|
||||
vprint(os, format_str, make_format_args<wformat_context>(args...));
|
||||
}
|
||||
|
||||
} // namespace fmt
|
||||
|
||||
#endif // FMT_OSTREAM_H_
|
||||
|
@ -151,7 +151,8 @@ class char_converter: public function<void> {
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_integral<T>::value>::type
|
||||
operator()(T value) {
|
||||
arg_ = internal::make_arg<Context>(static_cast<char>(value));
|
||||
typedef typename Context::char_type Char;
|
||||
arg_ = internal::make_arg<Context>(static_cast<Char>(value));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -223,11 +224,16 @@ class printf_arg_formatter:
|
||||
|
||||
context_type &context_;
|
||||
|
||||
void write_null_pointer() {
|
||||
void write_null_pointer(char) {
|
||||
this->spec().type_ = 0;
|
||||
this->write("(nil)");
|
||||
}
|
||||
|
||||
void write_null_pointer(wchar_t) {
|
||||
this->spec().type_ = 0;
|
||||
this->write(L"(nil)");
|
||||
}
|
||||
|
||||
public:
|
||||
typedef typename base::format_specs format_specs;
|
||||
|
||||
@ -270,18 +276,29 @@ class printf_arg_formatter:
|
||||
if (value)
|
||||
base::operator()(value);
|
||||
else if (this->spec().type_ == 'p')
|
||||
write_null_pointer();
|
||||
write_null_pointer(char_type());
|
||||
else
|
||||
this->write("(null)");
|
||||
return this->out();
|
||||
}
|
||||
|
||||
/** Formats a null-terminated wide C string. */
|
||||
iterator operator()(const wchar_t *value) {
|
||||
if (value)
|
||||
base::operator()(value);
|
||||
else if (this->spec().type_ == 'p')
|
||||
write_null_pointer(char_type());
|
||||
else
|
||||
this->write(L"(null)");
|
||||
return this->out();
|
||||
}
|
||||
|
||||
/** Formats a pointer. */
|
||||
iterator operator()(const void *value) {
|
||||
if (value)
|
||||
return base::operator()(value);
|
||||
this->spec().type_ = 0;
|
||||
write_null_pointer();
|
||||
write_null_pointer(char_type());
|
||||
return this->out();
|
||||
}
|
||||
|
||||
@ -518,7 +535,7 @@ void basic_printf_context<OutputIt, Char, AF>::format() {
|
||||
spec.type_ = 'd';
|
||||
break;
|
||||
case 'c':
|
||||
// TODO: handle wchar_t
|
||||
// TODO: handle wchar_t better?
|
||||
visit(internal::char_converter<basic_printf_context>(arg), arg);
|
||||
break;
|
||||
}
|
||||
@ -551,6 +568,7 @@ inline format_arg_store<printf_context<internal::buffer>::type, Args...>
|
||||
args...);
|
||||
}
|
||||
typedef basic_format_args<printf_context<internal::buffer>::type> printf_args;
|
||||
typedef basic_format_args<printf_context<internal::wbuffer>::type> wprintf_args;
|
||||
|
||||
inline std::string vsprintf(string_view format, printf_args args) {
|
||||
memory_buffer buffer;
|
||||
@ -573,9 +591,7 @@ inline std::string sprintf(string_view format_str, const Args & ... args) {
|
||||
make_format_args<typename printf_context<internal::buffer>::type>(args...));
|
||||
}
|
||||
|
||||
inline std::wstring vsprintf(
|
||||
wstring_view format,
|
||||
basic_format_args<printf_context<internal::wbuffer>::type> args) {
|
||||
inline std::wstring vsprintf(wstring_view format, wprintf_args args) {
|
||||
wmemory_buffer buffer;
|
||||
printf(buffer, format, args);
|
||||
return to_string(buffer);
|
||||
@ -583,17 +599,19 @@ inline std::wstring vsprintf(
|
||||
|
||||
template <typename... Args>
|
||||
inline std::wstring sprintf(wstring_view format_str, const Args & ... args) {
|
||||
auto vargs = make_format_args<
|
||||
typename printf_context<internal::wbuffer>::type>(args...);
|
||||
return vsprintf(format_str, vargs);
|
||||
return vsprintf(format_str,
|
||||
make_format_args<typename printf_context<internal::wbuffer>::type>(args...));
|
||||
}
|
||||
|
||||
inline int vfprintf(std::FILE *f, string_view format, printf_args args) {
|
||||
memory_buffer buffer;
|
||||
template <typename Char>
|
||||
inline int vfprintf(std::FILE *f, basic_string_view<Char> format,
|
||||
basic_format_args<typename printf_context<
|
||||
internal::basic_buffer<Char>>::type> args) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
printf(buffer, format, args);
|
||||
std::size_t size = buffer.size();
|
||||
return std::fwrite(
|
||||
buffer.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
|
||||
buffer.data(), sizeof(Char), size, f) < size ? -1 : static_cast<int>(size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -612,10 +630,21 @@ inline int fprintf(std::FILE *f, string_view format_str, const Args & ... args)
|
||||
return vfprintf(f, format_str, vargs);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline int fprintf(std::FILE *f, wstring_view format_str,
|
||||
const Args & ... args) {
|
||||
return vfprintf(f, format_str,
|
||||
make_format_args<typename printf_context<internal::wbuffer>::type>(args...));
|
||||
}
|
||||
|
||||
inline int vprintf(string_view format, printf_args args) {
|
||||
return vfprintf(stdout, format, args);
|
||||
}
|
||||
|
||||
inline int vprintf(wstring_view format, wprintf_args args) {
|
||||
return vfprintf(stdout, format, args);
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Prints formatted data to ``stdout``.
|
||||
@ -631,6 +660,12 @@ inline int printf(string_view format_str, const Args & ... args) {
|
||||
make_format_args<typename printf_context<internal::buffer>::type>(args...));
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline int printf(wstring_view format_str, const Args & ... args) {
|
||||
return vprintf(format_str,
|
||||
make_format_args<typename printf_context<internal::wbuffer>::type>(args...));
|
||||
}
|
||||
|
||||
inline int vfprintf(std::ostream &os, string_view format_str,
|
||||
printf_args args) {
|
||||
memory_buffer buffer;
|
||||
@ -639,6 +674,14 @@ inline int vfprintf(std::ostream &os, string_view format_str,
|
||||
return static_cast<int>(buffer.size());
|
||||
}
|
||||
|
||||
inline int vfprintf(std::wostream &os, wstring_view format_str,
|
||||
wprintf_args args) {
|
||||
wmemory_buffer buffer;
|
||||
printf(buffer, format_str, args);
|
||||
internal::write(os, buffer);
|
||||
return static_cast<int>(buffer.size());
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Prints formatted data to the stream *os*.
|
||||
@ -655,6 +698,14 @@ inline int fprintf(std::ostream &os, string_view format_str,
|
||||
typename printf_context<internal::buffer>::type>(args...);
|
||||
return vfprintf(os, format_str, vargs);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline int fprintf(std::wostream &os, wstring_view format_str,
|
||||
const Args & ... args) {
|
||||
auto vargs = make_format_args<
|
||||
typename printf_context<internal::buffer>::type>(args...);
|
||||
return vfprintf(os, format_str, vargs);
|
||||
}
|
||||
} // namespace fmt
|
||||
|
||||
#endif // FMT_PRINTF_H_
|
||||
|
@ -34,7 +34,8 @@ template FMT_API wchar_t internal::thousands_sep(locale_provider *lp);
|
||||
|
||||
template void basic_fixed_buffer<wchar_t>::grow(std::size_t);
|
||||
|
||||
template void internal::arg_map<wformat_context>::init(const wformat_args &args);
|
||||
template void internal::arg_map<wformat_context>::init(
|
||||
const basic_format_args<wformat_context> &args);
|
||||
|
||||
template FMT_API int internal::char_traits<wchar_t>::format_float(
|
||||
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
||||
|
@ -30,12 +30,19 @@ std::ostream &operator<<(std::ostream &os, TestEnum) {
|
||||
return os << "TestEnum";
|
||||
}
|
||||
|
||||
std::wostream &operator<<(std::wostream &os, TestEnum) {
|
||||
return os << L"TestEnum";
|
||||
}
|
||||
|
||||
enum TestEnum2 {A};
|
||||
|
||||
TEST(OStreamTest, Enum) {
|
||||
EXPECT_FALSE((fmt::internal::convert_to_int<TestEnum, char>::value));
|
||||
EXPECT_EQ("TestEnum", fmt::format("{}", TestEnum()));
|
||||
EXPECT_EQ("0", fmt::format("{}", A));
|
||||
EXPECT_FALSE((fmt::internal::convert_to_int<TestEnum, wchar_t>::value));
|
||||
EXPECT_EQ(L"TestEnum", fmt::format(L"{}", TestEnum()));
|
||||
EXPECT_EQ(L"0", fmt::format(L"{}", A));
|
||||
}
|
||||
|
||||
typedef fmt::back_insert_range<fmt::internal::buffer> range;
|
||||
@ -100,6 +107,9 @@ TEST(OStreamTest, Print) {
|
||||
std::ostringstream os;
|
||||
fmt::print(os, "Don't {}!", "panic");
|
||||
EXPECT_EQ("Don't panic!", os.str());
|
||||
std::wostringstream wos;
|
||||
fmt::print(wos, L"Don't {}!", L"panic");
|
||||
EXPECT_EQ(L"Don't panic!", wos.str());
|
||||
}
|
||||
|
||||
TEST(OStreamTest, WriteToOStream) {
|
||||
|
@ -26,6 +26,12 @@ std::string make_positional(fmt::string_view format) {
|
||||
return s;
|
||||
}
|
||||
|
||||
std::wstring make_positional(fmt::wstring_view format) {
|
||||
std::wstring s(format.data(), format.size());
|
||||
s.replace(s.find(L'%'), 1, L"%1$");
|
||||
return s;
|
||||
}
|
||||
|
||||
#define EXPECT_PRINTF(expected_output, format, arg) \
|
||||
EXPECT_EQ(expected_output, fmt::sprintf(format, arg)) \
|
||||
<< "format: " << format; \
|
||||
@ -33,6 +39,7 @@ std::string make_positional(fmt::string_view format) {
|
||||
|
||||
TEST(PrintfTest, NoArgs) {
|
||||
EXPECT_EQ("test", fmt::sprintf("test"));
|
||||
EXPECT_EQ(L"test", fmt::sprintf(L"test"));
|
||||
}
|
||||
|
||||
TEST(PrintfTest, Escape) {
|
||||
@ -41,6 +48,11 @@ TEST(PrintfTest, Escape) {
|
||||
EXPECT_EQ("% after", fmt::sprintf("%% after"));
|
||||
EXPECT_EQ("before % after", fmt::sprintf("before %% after"));
|
||||
EXPECT_EQ("%s", fmt::sprintf("%%s"));
|
||||
EXPECT_EQ(L"%", fmt::sprintf(L"%%"));
|
||||
EXPECT_EQ(L"before %", fmt::sprintf(L"before %%"));
|
||||
EXPECT_EQ(L"% after", fmt::sprintf(L"%% after"));
|
||||
EXPECT_EQ(L"before % after", fmt::sprintf(L"before %% after"));
|
||||
EXPECT_EQ(L"%s", fmt::sprintf(L"%%s"));
|
||||
}
|
||||
|
||||
TEST(PrintfTest, PositionalArgs) {
|
||||
@ -408,7 +420,8 @@ TEST(PrintfTest, Char) {
|
||||
int max = std::numeric_limits<int>::max();
|
||||
EXPECT_PRINTF(fmt::format("{}", static_cast<char>(max)), "%c", max);
|
||||
//EXPECT_PRINTF("x", "%lc", L'x');
|
||||
// TODO: test wchar_t
|
||||
EXPECT_PRINTF(L"x", L"%c", L'x');
|
||||
EXPECT_PRINTF(fmt::format(L"{}", static_cast<wchar_t>(max)), L"%c", max);
|
||||
}
|
||||
|
||||
TEST(PrintfTest, String) {
|
||||
@ -416,7 +429,10 @@ TEST(PrintfTest, String) {
|
||||
const char *null_str = 0;
|
||||
EXPECT_PRINTF("(null)", "%s", null_str);
|
||||
EXPECT_PRINTF(" (null)", "%10s", null_str);
|
||||
// TODO: wide string
|
||||
EXPECT_PRINTF(L"abc", L"%s", L"abc");
|
||||
const wchar_t *null_wstr = 0;
|
||||
EXPECT_PRINTF(L"(null)", L"%s", null_wstr);
|
||||
EXPECT_PRINTF(L" (null)", L"%10s", null_wstr);
|
||||
}
|
||||
|
||||
TEST(PrintfTest, Pointer) {
|
||||
@ -430,6 +446,16 @@ TEST(PrintfTest, Pointer) {
|
||||
EXPECT_PRINTF(fmt::format("{:p}", s), "%p", s);
|
||||
const char *null_str = 0;
|
||||
EXPECT_PRINTF("(nil)", "%p", null_str);
|
||||
|
||||
p = &n;
|
||||
EXPECT_PRINTF(fmt::format(L"{}", p), L"%p", p);
|
||||
p = 0;
|
||||
EXPECT_PRINTF(L"(nil)", L"%p", p);
|
||||
EXPECT_PRINTF(L" (nil)", L"%10p", p);
|
||||
const wchar_t *w = L"test";
|
||||
EXPECT_PRINTF(fmt::format(L"{:p}", w), L"%p", w);
|
||||
const wchar_t *null_wstr = 0;
|
||||
EXPECT_PRINTF(L"(nil)", L"%p", null_wstr);
|
||||
}
|
||||
|
||||
TEST(PrintfTest, Location) {
|
||||
|
Loading…
Reference in New Issue
Block a user