1 // Formatting library for C++ - optional wchar_t and exotic character support
3 // Copyright (c) 2012 - present, Victor Zverovich
4 // All rights reserved.
6 // For the license information refer to format.h.
19 using is_exotic_char
= bool_constant
<!std::is_same
<T
, char>::value
>;
22 FMT_MODULE_EXPORT_BEGIN
24 using wstring_view
= basic_string_view
<wchar_t>;
25 using wformat_parse_context
= basic_format_parse_context
<wchar_t>;
26 using wformat_context
= buffer_context
<wchar_t>;
27 using wformat_args
= basic_format_args
<wformat_context
>;
28 using wmemory_buffer
= basic_memory_buffer
<wchar_t>;
30 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
31 // Workaround broken conversion on older gcc.
32 template <typename
... Args
> using wformat_string
= wstring_view
;
34 template <typename
... Args
>
35 using wformat_string
= basic_format_string
<wchar_t, type_identity_t
<Args
>...>;
38 template <> struct is_char
<wchar_t> : std::true_type
{};
39 template <> struct is_char
<detail::char8_type
> : std::true_type
{};
40 template <> struct is_char
<char16_t
> : std::true_type
{};
41 template <> struct is_char
<char32_t
> : std::true_type
{};
43 template <typename
... Args
>
44 constexpr format_arg_store
<wformat_context
, Args
...> make_wformat_args(
45 const Args
&... args
) {
49 inline namespace literals
{
50 constexpr auto operator"" _format(const wchar_t* s
, size_t n
)
51 -> detail::udl_formatter
<wchar_t> {
55 #if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
56 constexpr detail::udl_arg
<wchar_t> operator"" _a(const wchar_t* s
, size_t) {
60 } // namespace literals
62 template <typename It
, typename Sentinel
>
63 auto join(It begin
, Sentinel end
, wstring_view sep
)
64 -> join_view
<It
, Sentinel
, wchar_t> {
65 return {begin
, end
, sep
};
68 template <typename Range
>
69 auto join(Range
&& range
, wstring_view sep
)
70 -> join_view
<detail::iterator_t
<Range
>, detail::sentinel_t
<Range
>,
72 return join(std::begin(range
), std::end(range
), sep
);
76 auto join(std::initializer_list
<T
> list
, wstring_view sep
)
77 -> join_view
<const T
*, const T
*, wchar_t> {
78 return join(std::begin(list
), std::end(list
), sep
);
81 template <typename Char
, FMT_ENABLE_IF(!std::is_same
<Char
, char>::value
)>
82 auto vformat(basic_string_view
<Char
> format_str
,
83 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
)
84 -> std::basic_string
<Char
> {
85 basic_memory_buffer
<Char
> buffer
;
86 detail::vformat_to(buffer
, format_str
, args
);
87 return to_string(buffer
);
90 // Pass char_t as a default template parameter instead of using
91 // std::basic_string<char_t<S>> to reduce the symbol size.
92 template <typename S
, typename
... Args
, typename Char
= char_t
<S
>,
93 FMT_ENABLE_IF(!std::is_same
<Char
, char>::value
)>
94 auto format(const S
& format_str
, Args
&&... args
) -> std::basic_string
<Char
> {
95 const auto& vargs
= fmt::make_args_checked
<Args
...>(format_str
, args
...);
96 return vformat(to_string_view(format_str
), vargs
);
99 template <typename Locale
, typename S
, typename Char
= char_t
<S
>,
100 FMT_ENABLE_IF(detail::is_locale
<Locale
>::value
&&
101 detail::is_exotic_char
<Char
>::value
)>
103 const Locale
& loc
, const S
& format_str
,
104 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
)
105 -> std::basic_string
<Char
> {
106 return detail::vformat(loc
, to_string_view(format_str
), args
);
109 template <typename Locale
, typename S
, typename
... Args
,
110 typename Char
= char_t
<S
>,
111 FMT_ENABLE_IF(detail::is_locale
<Locale
>::value
&&
112 detail::is_exotic_char
<Char
>::value
)>
113 inline auto format(const Locale
& loc
, const S
& format_str
, Args
&&... args
)
114 -> std::basic_string
<Char
> {
115 return detail::vformat(loc
, to_string_view(format_str
),
116 fmt::make_args_checked
<Args
...>(format_str
, args
...));
119 template <typename OutputIt
, typename S
, typename Char
= char_t
<S
>,
120 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, Char
>::value
&&
121 detail::is_exotic_char
<Char
>::value
)>
122 auto vformat_to(OutputIt out
, const S
& format_str
,
123 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
)
125 auto&& buf
= detail::get_buffer
<Char
>(out
);
126 detail::vformat_to(buf
, to_string_view(format_str
), args
);
127 return detail::get_iterator(buf
);
130 template <typename OutputIt
, typename S
, typename
... Args
,
131 typename Char
= char_t
<S
>,
132 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, Char
>::value
&&
133 detail::is_exotic_char
<Char
>::value
)>
134 inline auto format_to(OutputIt out
, const S
& fmt
, Args
&&... args
) -> OutputIt
{
135 const auto& vargs
= fmt::make_args_checked
<Args
...>(fmt
, args
...);
136 return vformat_to(out
, to_string_view(fmt
), vargs
);
139 template <typename S
, typename
... Args
, typename Char
, size_t SIZE
,
140 typename Allocator
, FMT_ENABLE_IF(detail::is_string
<S
>::value
)>
141 FMT_DEPRECATED
auto format_to(basic_memory_buffer
<Char
, SIZE
, Allocator
>& buf
,
142 const S
& format_str
, Args
&&... args
) ->
143 typename buffer_context
<Char
>::iterator
{
144 const auto& vargs
= fmt::make_args_checked
<Args
...>(format_str
, args
...);
145 detail::vformat_to(buf
, to_string_view(format_str
), vargs
, {});
146 return detail::buffer_appender
<Char
>(buf
);
149 template <typename Locale
, typename S
, typename OutputIt
, typename
... Args
,
150 typename Char
= char_t
<S
>,
151 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, Char
>::value
&&
152 detail::is_locale
<Locale
>::value
&&
153 detail::is_exotic_char
<Char
>::value
)>
154 inline auto vformat_to(
155 OutputIt out
, const Locale
& loc
, const S
& format_str
,
156 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
) -> OutputIt
{
157 auto&& buf
= detail::get_buffer
<Char
>(out
);
158 vformat_to(buf
, to_string_view(format_str
), args
, detail::locale_ref(loc
));
159 return detail::get_iterator(buf
);
163 typename OutputIt
, typename Locale
, typename S
, typename
... Args
,
164 typename Char
= char_t
<S
>,
165 bool enable
= detail::is_output_iterator
<OutputIt
, Char
>::value
&&
166 detail::is_locale
<Locale
>::value
&& detail::is_exotic_char
<Char
>::value
>
167 inline auto format_to(OutputIt out
, const Locale
& loc
, const S
& format_str
,
169 typename
std::enable_if
<enable
, OutputIt
>::type
{
170 const auto& vargs
= fmt::make_args_checked
<Args
...>(format_str
, args
...);
171 return vformat_to(out
, loc
, to_string_view(format_str
), vargs
);
174 template <typename OutputIt
, typename Char
, typename
... Args
,
175 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, Char
>::value
&&
176 detail::is_exotic_char
<Char
>::value
)>
177 inline auto vformat_to_n(
178 OutputIt out
, size_t n
, basic_string_view
<Char
> format_str
,
179 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
)
180 -> format_to_n_result
<OutputIt
> {
181 detail::iterator_buffer
<OutputIt
, Char
, detail::fixed_buffer_traits
> buf(out
,
183 detail::vformat_to(buf
, format_str
, args
);
184 return {buf
.out(), buf
.count()};
187 template <typename OutputIt
, typename S
, typename
... Args
,
188 typename Char
= char_t
<S
>,
189 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, Char
>::value
&&
190 detail::is_exotic_char
<Char
>::value
)>
191 inline auto format_to_n(OutputIt out
, size_t n
, const S
& fmt
,
192 const Args
&... args
) -> format_to_n_result
<OutputIt
> {
193 const auto& vargs
= fmt::make_args_checked
<Args
...>(fmt
, args
...);
194 return vformat_to_n(out
, n
, to_string_view(fmt
), vargs
);
197 template <typename S
, typename
... Args
, typename Char
= char_t
<S
>,
198 FMT_ENABLE_IF(detail::is_exotic_char
<Char
>::value
)>
199 inline auto formatted_size(const S
& fmt
, Args
&&... args
) -> size_t {
200 detail::counting_buffer
<Char
> buf
;
201 const auto& vargs
= fmt::make_args_checked
<Args
...>(fmt
, args
...);
202 detail::vformat_to(buf
, to_string_view(fmt
), vargs
);
206 inline void vprint(std::FILE* f
, wstring_view fmt
, wformat_args args
) {
207 wmemory_buffer buffer
;
208 detail::vformat_to(buffer
, fmt
, args
);
209 buffer
.push_back(L
'\0');
210 if (std::fputws(buffer
.data(), f
) == -1)
211 FMT_THROW(system_error(errno
, FMT_STRING("cannot write to file")));
214 inline void vprint(wstring_view fmt
, wformat_args args
) {
215 vprint(stdout
, fmt
, args
);
218 template <typename
... T
>
219 void print(std::FILE* f
, wformat_string
<T
...> fmt
, T
&&... args
) {
220 return vprint(f
, wstring_view(fmt
), fmt::make_wformat_args(args
...));
223 template <typename
... T
> void print(wformat_string
<T
...> fmt
, T
&&... args
) {
224 return vprint(wstring_view(fmt
), fmt::make_wformat_args(args
...));
228 Converts *value* to ``std::wstring`` using the default format for type *T*.
230 template <typename T
> inline auto to_wstring(const T
& value
) -> std::wstring
{
231 return format(FMT_STRING(L
"{}"), value
);
233 FMT_MODULE_EXPORT_END
236 #endif // FMT_XCHAR_H_