mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-25 19:50:05 +00:00
More wchar_t-specific API to wchar.h
This commit is contained in:
parent
6326c18906
commit
34b8acaef7
@ -629,8 +629,6 @@ void iterator_buffer<OutputIt, T, Traits>::flush() {
|
||||
|
||||
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<detail::char8_type> : std::true_type {};
|
||||
template <> struct is_char<char16_t> : std::true_type {};
|
||||
@ -1129,7 +1127,7 @@ class utf8_to_utf16 {
|
||||
|
||||
public:
|
||||
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; }
|
||||
const wchar_t* c_str() const { return &buffer_[0]; }
|
||||
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};
|
||||
}
|
||||
|
||||
template <typename It, typename Sentinel>
|
||||
arg_join<It, Sentinel, wchar_t> join(It begin, Sentinel end, wstring_view sep) {
|
||||
return {begin, end, sep};
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
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>
|
||||
std::basic_string<Char> to_string(const basic_memory_buffer<Char, SIZE>& buf) {
|
||||
auto size = buf.size();
|
||||
@ -2873,9 +2853,6 @@ operator""_a() {
|
||||
constexpr detail::udl_arg<char> operator"" _a(const char* s, size_t) {
|
||||
return {s};
|
||||
}
|
||||
constexpr detail::udl_arg<wchar_t> operator"" _a(const wchar_t* s, size_t) {
|
||||
return {s};
|
||||
}
|
||||
# endif
|
||||
} // namespace literals
|
||||
|
||||
|
@ -148,7 +148,7 @@ class utf16_to_utf8 {
|
||||
|
||||
public:
|
||||
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()); }
|
||||
size_t size() const { return buffer_.size() - 1; }
|
||||
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
|
||||
// throwing exception on conversion error. This method may still throw
|
||||
// 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,
|
||||
|
@ -435,8 +435,8 @@ FMT_CONSTEXPR tuple_arg_join<char, T...> join(const std::tuple<T...>& tuple,
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
FMT_CONSTEXPR tuple_arg_join<wchar_t, T...> join(const std::tuple<T...>& tuple,
|
||||
wstring_view sep) {
|
||||
FMT_CONSTEXPR tuple_arg_join<wchar_t, T...> join(
|
||||
const std::tuple<T...>& tuple, basic_string_view<wchar_t> 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);
|
||||
}
|
||||
|
||||
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_END_NAMESPACE
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
FMT_BEGIN_NAMESPACE
|
||||
FMT_MODULE_EXPORT_BEGIN
|
||||
|
||||
using wstring_view = basic_string_view<wchar_t>;
|
||||
using wformat_parse_context = basic_format_parse_context<wchar_t>;
|
||||
using wformat_context = buffer_context<wchar_t>;
|
||||
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> {
|
||||
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
|
||||
|
||||
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) {
|
||||
wmemory_buffer buffer;
|
||||
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...));
|
||||
}
|
||||
|
||||
/**
|
||||
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_END_NAMESPACE
|
||||
|
||||
|
@ -72,14 +72,14 @@ inline std::size_t convert_rwcount(std::size_t count) { return count; }
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
#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)) {
|
||||
FMT_THROW(windows_error(error_code,
|
||||
"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;
|
||||
int s_size = static_cast<int>(s.size());
|
||||
if (s_size == 0) {
|
||||
@ -129,8 +129,8 @@ class system_message {
|
||||
}
|
||||
~system_message() { LocalFree(message_); }
|
||||
explicit operator bool() const FMT_NOEXCEPT { return result_ != 0; }
|
||||
operator wstring_view() const FMT_NOEXCEPT {
|
||||
return wstring_view(message_, result_);
|
||||
operator basic_string_view<wchar_t>() const FMT_NOEXCEPT {
|
||||
return basic_string_view<wchar_t>(message_, result_);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -22,10 +22,6 @@
|
||||
|
||||
#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::detail::buffer;
|
||||
|
||||
@ -453,11 +449,11 @@ TEST(arg_test, wstring_arg) {
|
||||
wchar_t* str = str_data;
|
||||
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, cstr);
|
||||
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) {
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "fmt/locale.h"
|
||||
#include "fmt/ostream.h"
|
||||
#include "fmt/ranges.h"
|
||||
#include "fmt/wchar.h"
|
||||
|
||||
// Exercise the API to verify that everything we expect to can compile.
|
||||
void test_format_api() {
|
||||
|
@ -1437,18 +1437,6 @@ TEST(format_test, format_explicitly_convertible_to_std_string_view) {
|
||||
}
|
||||
#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 {
|
||||
class QString {
|
||||
public:
|
||||
@ -1640,7 +1628,6 @@ TEST(format_test, join) {
|
||||
EXPECT_EQ("(+01.20, +03.40)",
|
||||
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(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::arg("second", "cad"), fmt::arg("third", 99)),
|
||||
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
|
||||
|
||||
@ -1869,8 +1849,6 @@ TEST(format_test, to_string) {
|
||||
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) {
|
||||
std::list<char> out;
|
||||
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));
|
||||
}
|
||||
|
||||
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 {
|
||||
char* data;
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
using fmt::buffered_file;
|
||||
using testing::HasSubstr;
|
||||
using wstring_view = fmt::basic_string_view<wchar_t>;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
@ -62,9 +63,9 @@ TEST(util_test, utf16_to_utf8_error) {
|
||||
|
||||
TEST(util_test, utf16_to_utf8_convert) {
|
||||
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,
|
||||
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) {
|
||||
@ -98,8 +99,7 @@ TEST(os_test, format_windows_error) {
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
0, ERROR_FILE_EXISTS, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
reinterpret_cast<LPWSTR>(&message), 0, 0);
|
||||
fmt::detail::utf16_to_utf8 utf8_message(
|
||||
fmt::wstring_view(message, result - 2));
|
||||
fmt::detail::utf16_to_utf8 utf8_message(wstring_view(message, result - 2));
|
||||
LocalFree(message);
|
||||
fmt::memory_buffer actual_message;
|
||||
fmt::detail::format_windows_error(actual_message, ERROR_FILE_EXISTS, "test");
|
||||
@ -124,8 +124,7 @@ TEST(os_test, format_long_windows_error) {
|
||||
LocalFree(message);
|
||||
return;
|
||||
}
|
||||
fmt::detail::utf16_to_utf8 utf8_message(
|
||||
fmt::wstring_view(message, result - 2));
|
||||
fmt::detail::utf16_to_utf8 utf8_message(wstring_view(message, result - 2));
|
||||
LocalFree(message);
|
||||
fmt::memory_buffer actual_message;
|
||||
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;
|
||||
}
|
||||
|
||||
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());
|
||||
s.replace(s.find(L'%'), 1, L"%1$");
|
||||
return s;
|
||||
@ -42,7 +42,8 @@ std::string test_sprintf(fmt::string_view format, const Args&... args) {
|
||||
return fmt::sprintf(format, 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...);
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,19 @@
|
||||
|
||||
#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;
|
||||
fmt::basic_format_arg<wcontext> warg = fmt::detail::make_arg<wcontext>(42);
|
||||
auto wargs = fmt::basic_format_args<wcontext>(&warg, 1);
|
||||
@ -21,14 +33,52 @@ TEST(format_test, vformat_to) {
|
||||
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
|
||||
TEST(format_test, format_udl) {
|
||||
TEST(wchar_test, format_udl) {
|
||||
using namespace fmt::literals;
|
||||
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) {
|
||||
// Check that the wide print overload compiles.
|
||||
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)); }
|
||||
|
Loading…
Reference in New Issue
Block a user