mirror of
https://github.com/fmtlib/fmt.git
synced 2025-07-30 02:37:36 +02:00
More wchar_t-specific API to wchar.h
This commit is contained in:
@ -629,8 +629,6 @@ void iterator_buffer<OutputIt, T, Traits>::flush() {
|
|||||||
|
|
||||||
FMT_MODULE_EXPORT_BEGIN
|
FMT_MODULE_EXPORT_BEGIN
|
||||||
|
|
||||||
using wstring_view = basic_string_view<wchar_t>;
|
|
||||||
|
|
||||||
template <> struct is_char<wchar_t> : std::true_type {};
|
template <> struct is_char<wchar_t> : std::true_type {};
|
||||||
template <> struct is_char<detail::char8_type> : std::true_type {};
|
template <> struct is_char<detail::char8_type> : std::true_type {};
|
||||||
template <> struct is_char<char16_t> : std::true_type {};
|
template <> struct is_char<char16_t> : std::true_type {};
|
||||||
@ -1129,7 +1127,7 @@ class utf8_to_utf16 {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
FMT_API explicit utf8_to_utf16(string_view s);
|
FMT_API explicit utf8_to_utf16(string_view s);
|
||||||
operator wstring_view() const { return {&buffer_[0], size()}; }
|
operator basic_string_view<wchar_t>() const { return {&buffer_[0], size()}; }
|
||||||
size_t size() const { return buffer_.size() - 1; }
|
size_t size() const { return buffer_.size() - 1; }
|
||||||
const wchar_t* c_str() const { return &buffer_[0]; }
|
const wchar_t* c_str() const { return &buffer_[0]; }
|
||||||
std::wstring str() const { return {&buffer_[0], size()}; }
|
std::wstring str() const { return {&buffer_[0], size()}; }
|
||||||
@ -2489,11 +2487,6 @@ arg_join<It, Sentinel, char> join(It begin, Sentinel end, string_view sep) {
|
|||||||
return {begin, end, sep};
|
return {begin, end, sep};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename It, typename Sentinel>
|
|
||||||
arg_join<It, Sentinel, wchar_t> join(It begin, Sentinel end, wstring_view sep) {
|
|
||||||
return {begin, end, sep};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
Returns an object that formats `range` with elements separated by `sep`.
|
Returns an object that formats `range` with elements separated by `sep`.
|
||||||
@ -2516,12 +2509,6 @@ arg_join<detail::iterator_t<Range>, detail::sentinel_t<Range>, char> join(
|
|||||||
return join(std::begin(range), std::end(range), sep);
|
return join(std::begin(range), std::end(range), sep);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Range>
|
|
||||||
arg_join<detail::iterator_t<Range>, detail::sentinel_t<Range>, wchar_t> join(
|
|
||||||
Range&& range, wstring_view sep) {
|
|
||||||
return join(std::begin(range), std::end(range), sep);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
Converts *value* to ``std::string`` using the default format for type *T*.
|
Converts *value* to ``std::string`` using the default format for type *T*.
|
||||||
@ -2550,13 +2537,6 @@ inline std::string to_string(T value) {
|
|||||||
return std::string(begin, detail::write<char>(begin, value));
|
return std::string(begin, detail::write<char>(begin, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Converts *value* to ``std::wstring`` using the default format for type *T*.
|
|
||||||
*/
|
|
||||||
template <typename T> inline std::wstring to_wstring(const T& value) {
|
|
||||||
return format(FMT_STRING(L"{}"), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char, size_t SIZE>
|
template <typename Char, size_t SIZE>
|
||||||
std::basic_string<Char> to_string(const basic_memory_buffer<Char, SIZE>& buf) {
|
std::basic_string<Char> to_string(const basic_memory_buffer<Char, SIZE>& buf) {
|
||||||
auto size = buf.size();
|
auto size = buf.size();
|
||||||
@ -2873,9 +2853,6 @@ operator""_a() {
|
|||||||
constexpr detail::udl_arg<char> operator"" _a(const char* s, size_t) {
|
constexpr detail::udl_arg<char> operator"" _a(const char* s, size_t) {
|
||||||
return {s};
|
return {s};
|
||||||
}
|
}
|
||||||
constexpr detail::udl_arg<wchar_t> operator"" _a(const wchar_t* s, size_t) {
|
|
||||||
return {s};
|
|
||||||
}
|
|
||||||
# endif
|
# endif
|
||||||
} // namespace literals
|
} // namespace literals
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ class utf16_to_utf8 {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
utf16_to_utf8() {}
|
utf16_to_utf8() {}
|
||||||
FMT_API explicit utf16_to_utf8(wstring_view s);
|
FMT_API explicit utf16_to_utf8(basic_string_view<wchar_t> s);
|
||||||
operator string_view() const { return string_view(&buffer_[0], size()); }
|
operator string_view() const { return string_view(&buffer_[0], size()); }
|
||||||
size_t size() const { return buffer_.size() - 1; }
|
size_t size() const { return buffer_.size() - 1; }
|
||||||
const char* c_str() const { return &buffer_[0]; }
|
const char* c_str() const { return &buffer_[0]; }
|
||||||
@ -157,7 +157,7 @@ class utf16_to_utf8 {
|
|||||||
// Performs conversion returning a system error code instead of
|
// Performs conversion returning a system error code instead of
|
||||||
// throwing exception on conversion error. This method may still throw
|
// throwing exception on conversion error. This method may still throw
|
||||||
// in case of memory allocation error.
|
// in case of memory allocation error.
|
||||||
FMT_API int convert(wstring_view s);
|
FMT_API int convert(basic_string_view<wchar_t> s);
|
||||||
};
|
};
|
||||||
|
|
||||||
FMT_API void format_windows_error(buffer<char>& out, int error_code,
|
FMT_API void format_windows_error(buffer<char>& out, int error_code,
|
||||||
|
@ -435,8 +435,8 @@ FMT_CONSTEXPR tuple_arg_join<char, T...> join(const std::tuple<T...>& tuple,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
FMT_CONSTEXPR tuple_arg_join<wchar_t, T...> join(const std::tuple<T...>& tuple,
|
FMT_CONSTEXPR tuple_arg_join<wchar_t, T...> join(
|
||||||
wstring_view sep) {
|
const std::tuple<T...>& tuple, basic_string_view<wchar_t> sep) {
|
||||||
return {tuple, sep};
|
return {tuple, sep};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,12 +457,6 @@ arg_join<const T*, const T*, char> join(std::initializer_list<T> list,
|
|||||||
return join(std::begin(list), std::end(list), sep);
|
return join(std::begin(list), std::end(list), sep);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
arg_join<const T*, const T*, wchar_t> join(std::initializer_list<T> list,
|
|
||||||
wstring_view sep) {
|
|
||||||
return join(std::begin(list), std::end(list), sep);
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_MODULE_EXPORT_END
|
FMT_MODULE_EXPORT_END
|
||||||
FMT_END_NAMESPACE
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
FMT_BEGIN_NAMESPACE
|
FMT_BEGIN_NAMESPACE
|
||||||
FMT_MODULE_EXPORT_BEGIN
|
FMT_MODULE_EXPORT_BEGIN
|
||||||
|
|
||||||
|
using wstring_view = basic_string_view<wchar_t>;
|
||||||
using wformat_parse_context = basic_format_parse_context<wchar_t>;
|
using wformat_parse_context = basic_format_parse_context<wchar_t>;
|
||||||
using wformat_context = buffer_context<wchar_t>;
|
using wformat_context = buffer_context<wchar_t>;
|
||||||
using wformat_args = basic_format_args<wformat_context>;
|
using wformat_args = basic_format_args<wformat_context>;
|
||||||
@ -38,8 +39,31 @@ constexpr auto operator"" _format(const wchar_t* s, size_t n)
|
|||||||
-> detail::udl_formatter<wchar_t> {
|
-> detail::udl_formatter<wchar_t> {
|
||||||
return {{s, n}};
|
return {{s, n}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
||||||
|
constexpr detail::udl_arg<wchar_t> operator"" _a(const wchar_t* s, size_t) {
|
||||||
|
return {s};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
} // namespace literals
|
} // namespace literals
|
||||||
|
|
||||||
|
template <typename It, typename Sentinel>
|
||||||
|
arg_join<It, Sentinel, wchar_t> join(It begin, Sentinel end, wstring_view sep) {
|
||||||
|
return {begin, end, sep};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Range>
|
||||||
|
arg_join<detail::iterator_t<Range>, detail::sentinel_t<Range>, wchar_t> join(
|
||||||
|
Range&& range, wstring_view sep) {
|
||||||
|
return join(std::begin(range), std::end(range), sep);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
arg_join<const T*, const T*, wchar_t> join(std::initializer_list<T> list,
|
||||||
|
wstring_view sep) {
|
||||||
|
return join(std::begin(list), std::end(list), sep);
|
||||||
|
}
|
||||||
|
|
||||||
inline void vprint(std::FILE* f, wstring_view fmt, wformat_args args) {
|
inline void vprint(std::FILE* f, wstring_view fmt, wformat_args args) {
|
||||||
wmemory_buffer buffer;
|
wmemory_buffer buffer;
|
||||||
detail::vformat_to(buffer, fmt, args);
|
detail::vformat_to(buffer, fmt, args);
|
||||||
@ -61,6 +85,13 @@ template <typename... T> void print(wformat_string<T...> fmt, T&&... args) {
|
|||||||
return vprint(wstring_view(fmt), make_wformat_args(args...));
|
return vprint(wstring_view(fmt), make_wformat_args(args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Converts *value* to ``std::wstring`` using the default format for type *T*.
|
||||||
|
*/
|
||||||
|
template <typename T> inline std::wstring to_wstring(const T& value) {
|
||||||
|
return format(FMT_STRING(L"{}"), value);
|
||||||
|
}
|
||||||
|
|
||||||
FMT_MODULE_EXPORT_END
|
FMT_MODULE_EXPORT_END
|
||||||
FMT_END_NAMESPACE
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
|
@ -72,14 +72,14 @@ inline std::size_t convert_rwcount(std::size_t count) { return count; }
|
|||||||
FMT_BEGIN_NAMESPACE
|
FMT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
detail::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
|
detail::utf16_to_utf8::utf16_to_utf8(basic_string_view<wchar_t> s) {
|
||||||
if (int error_code = convert(s)) {
|
if (int error_code = convert(s)) {
|
||||||
FMT_THROW(windows_error(error_code,
|
FMT_THROW(windows_error(error_code,
|
||||||
"cannot convert string from UTF-16 to UTF-8"));
|
"cannot convert string from UTF-16 to UTF-8"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int detail::utf16_to_utf8::convert(wstring_view s) {
|
int detail::utf16_to_utf8::convert(basic_string_view<wchar_t> s) {
|
||||||
if (s.size() > INT_MAX) return ERROR_INVALID_PARAMETER;
|
if (s.size() > INT_MAX) return ERROR_INVALID_PARAMETER;
|
||||||
int s_size = static_cast<int>(s.size());
|
int s_size = static_cast<int>(s.size());
|
||||||
if (s_size == 0) {
|
if (s_size == 0) {
|
||||||
@ -129,8 +129,8 @@ class system_message {
|
|||||||
}
|
}
|
||||||
~system_message() { LocalFree(message_); }
|
~system_message() { LocalFree(message_); }
|
||||||
explicit operator bool() const FMT_NOEXCEPT { return result_ != 0; }
|
explicit operator bool() const FMT_NOEXCEPT { return result_ != 0; }
|
||||||
operator wstring_view() const FMT_NOEXCEPT {
|
operator basic_string_view<wchar_t>() const FMT_NOEXCEPT {
|
||||||
return wstring_view(message_, result_);
|
return basic_string_view<wchar_t>(message_, result_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -22,10 +22,6 @@
|
|||||||
|
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
#if defined(FMT_COMPILE_TIME_CHECKS) && FMT_COMPILE_TIME_CHECKS
|
|
||||||
# include "fmt/format.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using fmt::string_view;
|
using fmt::string_view;
|
||||||
using fmt::detail::buffer;
|
using fmt::detail::buffer;
|
||||||
|
|
||||||
@ -453,11 +449,11 @@ TEST(arg_test, wstring_arg) {
|
|||||||
wchar_t* str = str_data;
|
wchar_t* str = str_data;
|
||||||
const wchar_t* cstr = str;
|
const wchar_t* cstr = str;
|
||||||
|
|
||||||
auto sv = fmt::wstring_view(str);
|
auto sv = fmt::basic_string_view<wchar_t>(str);
|
||||||
CHECK_ARG(wchar_t, cstr, str);
|
CHECK_ARG(wchar_t, cstr, str);
|
||||||
CHECK_ARG(wchar_t, cstr, cstr);
|
CHECK_ARG(wchar_t, cstr, cstr);
|
||||||
CHECK_ARG(wchar_t, sv, std::wstring(str));
|
CHECK_ARG(wchar_t, sv, std::wstring(str));
|
||||||
CHECK_ARG(wchar_t, sv, fmt::wstring_view(str));
|
CHECK_ARG(wchar_t, sv, fmt::basic_string_view<wchar_t>(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(arg_test, pointer_arg) {
|
TEST(arg_test, pointer_arg) {
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "fmt/locale.h"
|
#include "fmt/locale.h"
|
||||||
#include "fmt/ostream.h"
|
#include "fmt/ostream.h"
|
||||||
#include "fmt/ranges.h"
|
#include "fmt/ranges.h"
|
||||||
|
#include "fmt/wchar.h"
|
||||||
|
|
||||||
// Exercise the API to verify that everything we expect to can compile.
|
// Exercise the API to verify that everything we expect to can compile.
|
||||||
void test_format_api() {
|
void test_format_api() {
|
||||||
|
@ -1437,18 +1437,6 @@ TEST(format_test, format_explicitly_convertible_to_std_string_view) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// std::is_constructible is broken in MSVC until version 2015.
|
|
||||||
#if !FMT_MSC_VER || FMT_MSC_VER >= 1900
|
|
||||||
struct explicitly_convertible_to_wstring_view {
|
|
||||||
explicit operator fmt::wstring_view() const { return L"foo"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST(format_test, format_explicitly_convertible_to_wstring_view) {
|
|
||||||
EXPECT_EQ(L"foo",
|
|
||||||
fmt::format(L"{}", explicitly_convertible_to_wstring_view()));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace fake_qt {
|
namespace fake_qt {
|
||||||
class QString {
|
class QString {
|
||||||
public:
|
public:
|
||||||
@ -1640,7 +1628,6 @@ TEST(format_test, join) {
|
|||||||
EXPECT_EQ("(+01.20, +03.40)",
|
EXPECT_EQ("(+01.20, +03.40)",
|
||||||
fmt::format("({:+06.2f})", join(v2.begin(), v2.end(), ", ")));
|
fmt::format("({:+06.2f})", join(v2.begin(), v2.end(), ", ")));
|
||||||
|
|
||||||
EXPECT_EQ(L"(1, 2, 3)", fmt::format(L"({})", join(v1, v1 + 3, L", ")));
|
|
||||||
EXPECT_EQ("1, 2, 3", fmt::format("{0:{1}}", join(v1, v1 + 3, ", "), 1));
|
EXPECT_EQ("1, 2, 3", fmt::format("{0:{1}}", join(v1, v1 + 3, ", "), 1));
|
||||||
|
|
||||||
EXPECT_EQ(fmt::format("{}, {}", v3[0], v3[1]),
|
EXPECT_EQ(fmt::format("{}, {}", v3[0], v3[1]),
|
||||||
@ -1770,13 +1757,6 @@ TEST(format_test, named_arg_udl) {
|
|||||||
fmt::format("{first}{second}{first}{third}", fmt::arg("first", "abra"),
|
fmt::format("{first}{second}{first}{third}", fmt::arg("first", "abra"),
|
||||||
fmt::arg("second", "cad"), fmt::arg("third", 99)),
|
fmt::arg("second", "cad"), fmt::arg("third", 99)),
|
||||||
udl_a);
|
udl_a);
|
||||||
auto udl_a_w =
|
|
||||||
fmt::format(L"{first}{second}{first}{third}", L"first"_a = L"abra",
|
|
||||||
L"second"_a = L"cad", L"third"_a = 99);
|
|
||||||
EXPECT_EQ(
|
|
||||||
fmt::format(L"{first}{second}{first}{third}", fmt::arg(L"first", L"abra"),
|
|
||||||
fmt::arg(L"second", L"cad"), fmt::arg(L"third", 99)),
|
|
||||||
udl_a_w);
|
|
||||||
}
|
}
|
||||||
#endif // FMT_USE_USER_DEFINED_LITERALS
|
#endif // FMT_USE_USER_DEFINED_LITERALS
|
||||||
|
|
||||||
@ -1869,8 +1849,6 @@ TEST(format_test, to_string) {
|
|||||||
EXPECT_EQ("0", fmt::to_string(test_value));
|
EXPECT_EQ("0", fmt::to_string(test_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(format_test, to_wstring) { EXPECT_EQ(L"42", fmt::to_wstring(42)); }
|
|
||||||
|
|
||||||
TEST(format_test, output_iterators) {
|
TEST(format_test, output_iterators) {
|
||||||
std::list<char> out;
|
std::list<char> out;
|
||||||
fmt::format_to(std::back_inserter(out), "{}", 42);
|
fmt::format_to(std::back_inserter(out), "{}", 42);
|
||||||
@ -1966,26 +1944,6 @@ TEST(format_test, format_to_n) {
|
|||||||
EXPECT_EQ("***x", fmt::string_view(buffer, 4));
|
EXPECT_EQ("***x", fmt::string_view(buffer, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(format_test, wide_format_to_n) {
|
|
||||||
wchar_t buffer[4];
|
|
||||||
buffer[3] = L'x';
|
|
||||||
auto result = fmt::format_to_n(buffer, 3, L"{}", 12345);
|
|
||||||
EXPECT_EQ(5u, result.size);
|
|
||||||
EXPECT_EQ(buffer + 3, result.out);
|
|
||||||
EXPECT_EQ(L"123x", fmt::wstring_view(buffer, 4));
|
|
||||||
buffer[0] = L'x';
|
|
||||||
buffer[1] = L'x';
|
|
||||||
buffer[2] = L'x';
|
|
||||||
result = fmt::format_to_n(buffer, 3, L"{}", L'A');
|
|
||||||
EXPECT_EQ(1u, result.size);
|
|
||||||
EXPECT_EQ(buffer + 1, result.out);
|
|
||||||
EXPECT_EQ(L"Axxx", fmt::wstring_view(buffer, 4));
|
|
||||||
result = fmt::format_to_n(buffer, 3, L"{}{} ", L'B', L'C');
|
|
||||||
EXPECT_EQ(3u, result.size);
|
|
||||||
EXPECT_EQ(buffer + 3, result.out);
|
|
||||||
EXPECT_EQ(L"BC x", fmt::wstring_view(buffer, 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct test_output_iterator {
|
struct test_output_iterator {
|
||||||
char* data;
|
char* data;
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
using fmt::buffered_file;
|
using fmt::buffered_file;
|
||||||
using testing::HasSubstr;
|
using testing::HasSubstr;
|
||||||
|
using wstring_view = fmt::basic_string_view<wchar_t>;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
@ -62,9 +63,9 @@ TEST(util_test, utf16_to_utf8_error) {
|
|||||||
|
|
||||||
TEST(util_test, utf16_to_utf8_convert) {
|
TEST(util_test, utf16_to_utf8_convert) {
|
||||||
fmt::detail::utf16_to_utf8 u;
|
fmt::detail::utf16_to_utf8 u;
|
||||||
EXPECT_EQ(ERROR_INVALID_PARAMETER, u.convert(fmt::wstring_view(0, 1)));
|
EXPECT_EQ(ERROR_INVALID_PARAMETER, u.convert(wstring_view(0, 1)));
|
||||||
EXPECT_EQ(ERROR_INVALID_PARAMETER,
|
EXPECT_EQ(ERROR_INVALID_PARAMETER,
|
||||||
u.convert(fmt::wstring_view(L"foo", INT_MAX + 1u)));
|
u.convert(wstring_view(L"foo", INT_MAX + 1u)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(os_test, format_std_error_code) {
|
TEST(os_test, format_std_error_code) {
|
||||||
@ -98,8 +99,7 @@ TEST(os_test, format_windows_error) {
|
|||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
0, ERROR_FILE_EXISTS, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
0, ERROR_FILE_EXISTS, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
reinterpret_cast<LPWSTR>(&message), 0, 0);
|
reinterpret_cast<LPWSTR>(&message), 0, 0);
|
||||||
fmt::detail::utf16_to_utf8 utf8_message(
|
fmt::detail::utf16_to_utf8 utf8_message(wstring_view(message, result - 2));
|
||||||
fmt::wstring_view(message, result - 2));
|
|
||||||
LocalFree(message);
|
LocalFree(message);
|
||||||
fmt::memory_buffer actual_message;
|
fmt::memory_buffer actual_message;
|
||||||
fmt::detail::format_windows_error(actual_message, ERROR_FILE_EXISTS, "test");
|
fmt::detail::format_windows_error(actual_message, ERROR_FILE_EXISTS, "test");
|
||||||
@ -124,8 +124,7 @@ TEST(os_test, format_long_windows_error) {
|
|||||||
LocalFree(message);
|
LocalFree(message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fmt::detail::utf16_to_utf8 utf8_message(
|
fmt::detail::utf16_to_utf8 utf8_message(wstring_view(message, result - 2));
|
||||||
fmt::wstring_view(message, result - 2));
|
|
||||||
LocalFree(message);
|
LocalFree(message);
|
||||||
fmt::memory_buffer actual_message;
|
fmt::memory_buffer actual_message;
|
||||||
fmt::detail::format_windows_error(actual_message, provisioning_not_allowed,
|
fmt::detail::format_windows_error(actual_message, provisioning_not_allowed,
|
||||||
|
@ -29,7 +29,7 @@ static std::string make_positional(fmt::string_view format) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::wstring make_positional(fmt::wstring_view format) {
|
static std::wstring make_positional(fmt::basic_string_view<wchar_t> format) {
|
||||||
std::wstring s(format.data(), format.size());
|
std::wstring s(format.data(), format.size());
|
||||||
s.replace(s.find(L'%'), 1, L"%1$");
|
s.replace(s.find(L'%'), 1, L"%1$");
|
||||||
return s;
|
return s;
|
||||||
@ -42,7 +42,8 @@ std::string test_sprintf(fmt::string_view format, const Args&... args) {
|
|||||||
return fmt::sprintf(format, args...);
|
return fmt::sprintf(format, args...);
|
||||||
}
|
}
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
std::wstring test_sprintf(fmt::wstring_view format, const Args&... args) {
|
std::wstring test_sprintf(fmt::basic_string_view<wchar_t> format,
|
||||||
|
const Args&... args) {
|
||||||
return fmt::sprintf(format, args...);
|
return fmt::sprintf(format, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,19 @@
|
|||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
TEST(format_test, vformat_to) {
|
// std::is_constructible is broken in MSVC until version 2015.
|
||||||
|
#if !FMT_MSC_VER || FMT_MSC_VER >= 1900
|
||||||
|
struct explicitly_convertible_to_wstring_view {
|
||||||
|
explicit operator fmt::wstring_view() const { return L"foo"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(wchar_test, format_explicitly_convertible_to_wstring_view) {
|
||||||
|
EXPECT_EQ(L"foo",
|
||||||
|
fmt::format(L"{}", explicitly_convertible_to_wstring_view()));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TEST(wchar_test, vformat_to) {
|
||||||
using wcontext = fmt::wformat_context;
|
using wcontext = fmt::wformat_context;
|
||||||
fmt::basic_format_arg<wcontext> warg = fmt::detail::make_arg<wcontext>(42);
|
fmt::basic_format_arg<wcontext> warg = fmt::detail::make_arg<wcontext>(42);
|
||||||
auto wargs = fmt::basic_format_args<wcontext>(&warg, 1);
|
auto wargs = fmt::basic_format_args<wcontext>(&warg, 1);
|
||||||
@ -21,14 +33,52 @@ TEST(format_test, vformat_to) {
|
|||||||
EXPECT_EQ(L"42", w);
|
EXPECT_EQ(L"42", w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(format_test, wide_format_to_n) {
|
||||||
|
wchar_t buffer[4];
|
||||||
|
buffer[3] = L'x';
|
||||||
|
auto result = fmt::format_to_n(buffer, 3, L"{}", 12345);
|
||||||
|
EXPECT_EQ(5u, result.size);
|
||||||
|
EXPECT_EQ(buffer + 3, result.out);
|
||||||
|
EXPECT_EQ(L"123x", fmt::wstring_view(buffer, 4));
|
||||||
|
buffer[0] = L'x';
|
||||||
|
buffer[1] = L'x';
|
||||||
|
buffer[2] = L'x';
|
||||||
|
result = fmt::format_to_n(buffer, 3, L"{}", L'A');
|
||||||
|
EXPECT_EQ(1u, result.size);
|
||||||
|
EXPECT_EQ(buffer + 1, result.out);
|
||||||
|
EXPECT_EQ(L"Axxx", fmt::wstring_view(buffer, 4));
|
||||||
|
result = fmt::format_to_n(buffer, 3, L"{}{} ", L'B', L'C');
|
||||||
|
EXPECT_EQ(3u, result.size);
|
||||||
|
EXPECT_EQ(buffer + 3, result.out);
|
||||||
|
EXPECT_EQ(L"BC x", fmt::wstring_view(buffer, 4));
|
||||||
|
}
|
||||||
|
|
||||||
#if FMT_USE_USER_DEFINED_LITERALS
|
#if FMT_USE_USER_DEFINED_LITERALS
|
||||||
TEST(format_test, format_udl) {
|
TEST(wchar_test, format_udl) {
|
||||||
using namespace fmt::literals;
|
using namespace fmt::literals;
|
||||||
EXPECT_EQ(L"{}c{}"_format(L"ab", 1), fmt::format(L"{}c{}", L"ab", 1));
|
EXPECT_EQ(L"{}c{}"_format(L"ab", 1), fmt::format(L"{}c{}", L"ab", 1));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
TEST(wchar_test, named_arg_udl) {
|
||||||
|
using namespace fmt::literals;
|
||||||
|
auto udl_a =
|
||||||
|
fmt::format(L"{first}{second}{first}{third}", L"first"_a = L"abra",
|
||||||
|
L"second"_a = L"cad", L"third"_a = 99);
|
||||||
|
EXPECT_EQ(
|
||||||
|
fmt::format(L"{first}{second}{first}{third}", fmt::arg(L"first", L"abra"),
|
||||||
|
fmt::arg(L"second", L"cad"), fmt::arg(L"third", 99)),
|
||||||
|
udl_a);
|
||||||
|
}
|
||||||
|
#endif // FMT_USE_USER_DEFINED_LITERALS
|
||||||
|
|
||||||
TEST(wchar_test, print) {
|
TEST(wchar_test, print) {
|
||||||
// Check that the wide print overload compiles.
|
// Check that the wide print overload compiles.
|
||||||
if (fmt::detail::const_check(false)) fmt::print(L"test");
|
if (fmt::detail::const_check(false)) fmt::print(L"test");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(wchar_test, join) {
|
||||||
|
int v[3] = {1, 2, 3};
|
||||||
|
EXPECT_EQ(fmt::format(L"({})", fmt::join(v, v + 3, L", ")), L"(1, 2, 3)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(wchar_test, to_wstring) { EXPECT_EQ(L"42", fmt::to_wstring(42)); }
|
||||||
|
Reference in New Issue
Block a user