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.
17 # if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
26 using is_exotic_char
= bool_constant
<!std::is_same
<T
, char>::value
>;
28 template <typename S
, typename
= void> struct format_string_char
{};
31 struct format_string_char
<
32 S
, void_t
<decltype(sizeof(detail::to_string_view(std::declval
<S
>())))>> {
33 using type
= char_t
<S
>;
37 struct format_string_char
<S
, enable_if_t
<is_compile_string
<S
>::value
>> {
38 using type
= typename
S::char_type
;
42 using format_string_char_t
= typename format_string_char
<S
>::type
;
44 inline auto write_loc(basic_appender
<wchar_t> out
, loc_value value
,
45 const format_specs
& specs
, locale_ref loc
) -> bool {
46 #ifndef FMT_STATIC_THOUSANDS_SEPARATOR
48 std::use_facet
<std::numpunct
<wchar_t>>(loc
.get
<std::locale
>());
49 auto separator
= std::wstring();
50 auto grouping
= numpunct
.grouping();
51 if (!grouping
.empty()) separator
= std::wstring(1, numpunct
.thousands_sep());
52 return value
.visit(loc_writer
<wchar_t>{out
, specs
, separator
, grouping
, {}});
60 using wstring_view
= basic_string_view
<wchar_t>;
61 using wformat_parse_context
= basic_format_parse_context
<wchar_t>;
62 using wformat_context
= buffered_context
<wchar_t>;
63 using wformat_args
= basic_format_args
<wformat_context
>;
64 using wmemory_buffer
= basic_memory_buffer
<wchar_t>;
66 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
67 // Workaround broken conversion on older gcc.
68 template <typename
... Args
> using wformat_string
= wstring_view
;
69 inline auto runtime(wstring_view s
) -> wstring_view
{ return s
; }
71 template <typename
... Args
>
72 using wformat_string
= basic_format_string
<wchar_t, type_identity_t
<Args
>...>;
73 inline auto runtime(wstring_view s
) -> runtime_format_string
<wchar_t> {
78 template <> struct is_char
<wchar_t> : std::true_type
{};
79 template <> struct is_char
<char16_t
> : std::true_type
{};
80 template <> struct is_char
<char32_t
> : std::true_type
{};
84 struct is_char
<char8_t
> : bool_constant
<detail::is_utf8_enabled()> {};
87 template <typename
... T
>
88 constexpr auto make_wformat_args(T
&... args
)
89 -> decltype(fmt::make_format_args
<wformat_context
>(args
...)) {
90 return fmt::make_format_args
<wformat_context
>(args
...);
93 inline namespace literals
{
94 #if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_ARGS
95 constexpr auto operator""_a(const wchar_t* s
, size_t)
96 -> detail::udl_arg
<wchar_t> {
100 } // namespace literals
102 template <typename It
, typename Sentinel
>
103 auto join(It begin
, Sentinel end
, wstring_view sep
)
104 -> join_view
<It
, Sentinel
, wchar_t> {
105 return {begin
, end
, sep
};
108 template <typename Range
>
109 auto join(Range
&& range
, wstring_view sep
)
110 -> join_view
<detail::iterator_t
<Range
>, detail::sentinel_t
<Range
>,
112 return join(std::begin(range
), std::end(range
), sep
);
115 template <typename T
>
116 auto join(std::initializer_list
<T
> list
, wstring_view sep
)
117 -> join_view
<const T
*, const T
*, wchar_t> {
118 return join(std::begin(list
), std::end(list
), sep
);
121 template <typename
... T
>
122 auto join(const std::tuple
<T
...>& tuple
, basic_string_view
<wchar_t> sep
)
123 -> tuple_join_view
<wchar_t, T
...> {
127 template <typename Char
, FMT_ENABLE_IF(!std::is_same
<Char
, char>::value
)>
128 auto vformat(basic_string_view
<Char
> format_str
,
129 typename
detail::vformat_args
<Char
>::type args
)
130 -> std::basic_string
<Char
> {
131 auto buf
= basic_memory_buffer
<Char
>();
132 detail::vformat_to(buf
, format_str
, args
);
133 return to_string(buf
);
136 template <typename
... T
>
137 auto format(wformat_string
<T
...> fmt
, T
&&... args
) -> std::wstring
{
138 return vformat(fmt::wstring_view(fmt
), fmt::make_wformat_args(args
...));
141 template <typename OutputIt
, typename
... T
>
142 auto format_to(OutputIt out
, wformat_string
<T
...> fmt
, T
&&... args
)
144 return vformat_to(out
, fmt::wstring_view(fmt
),
145 fmt::make_wformat_args(args
...));
148 // Pass char_t as a default template parameter instead of using
149 // std::basic_string<char_t<S>> to reduce the symbol size.
150 template <typename S
, typename
... T
,
151 typename Char
= detail::format_string_char_t
<S
>,
152 FMT_ENABLE_IF(!std::is_same
<Char
, char>::value
&&
153 !std::is_same
<Char
, wchar_t>::value
)>
154 auto format(const S
& format_str
, T
&&... args
) -> std::basic_string
<Char
> {
155 return vformat(detail::to_string_view(format_str
),
156 fmt::make_format_args
<buffered_context
<Char
>>(args
...));
159 template <typename Locale
, typename S
,
160 typename Char
= detail::format_string_char_t
<S
>,
161 FMT_ENABLE_IF(detail::is_locale
<Locale
>::value
&&
162 detail::is_exotic_char
<Char
>::value
)>
163 inline auto vformat(const Locale
& loc
, const S
& format_str
,
164 typename
detail::vformat_args
<Char
>::type args
)
165 -> std::basic_string
<Char
> {
166 return detail::vformat(loc
, detail::to_string_view(format_str
), args
);
169 template <typename Locale
, typename S
, typename
... T
,
170 typename Char
= detail::format_string_char_t
<S
>,
171 FMT_ENABLE_IF(detail::is_locale
<Locale
>::value
&&
172 detail::is_exotic_char
<Char
>::value
)>
173 inline auto format(const Locale
& loc
, const S
& format_str
, T
&&... args
)
174 -> std::basic_string
<Char
> {
175 return detail::vformat(
176 loc
, detail::to_string_view(format_str
),
177 fmt::make_format_args
<buffered_context
<Char
>>(args
...));
180 template <typename OutputIt
, typename S
,
181 typename Char
= detail::format_string_char_t
<S
>,
182 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, Char
>::value
&&
183 detail::is_exotic_char
<Char
>::value
)>
184 auto vformat_to(OutputIt out
, const S
& format_str
,
185 typename
detail::vformat_args
<Char
>::type args
) -> OutputIt
{
186 auto&& buf
= detail::get_buffer
<Char
>(out
);
187 detail::vformat_to(buf
, detail::to_string_view(format_str
), args
);
188 return detail::get_iterator(buf
, out
);
191 template <typename OutputIt
, typename S
, typename
... T
,
192 typename Char
= detail::format_string_char_t
<S
>,
193 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, Char
>::value
&&
194 !std::is_same
<Char
, char>::value
&&
195 !std::is_same
<Char
, wchar_t>::value
)>
196 inline auto format_to(OutputIt out
, const S
& fmt
, T
&&... args
) -> OutputIt
{
197 return vformat_to(out
, detail::to_string_view(fmt
),
198 fmt::make_format_args
<buffered_context
<Char
>>(args
...));
201 template <typename Locale
, typename S
, typename OutputIt
, typename
... Args
,
202 typename Char
= detail::format_string_char_t
<S
>,
203 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, Char
>::value
&&
204 detail::is_locale
<Locale
>::value
&&
205 detail::is_exotic_char
<Char
>::value
)>
206 inline auto vformat_to(OutputIt out
, const Locale
& loc
, const S
& format_str
,
207 typename
detail::vformat_args
<Char
>::type args
)
209 auto&& buf
= detail::get_buffer
<Char
>(out
);
210 vformat_to(buf
, detail::to_string_view(format_str
), args
,
211 detail::locale_ref(loc
));
212 return detail::get_iterator(buf
, out
);
215 template <typename OutputIt
, typename Locale
, typename S
, typename
... T
,
216 typename Char
= detail::format_string_char_t
<S
>,
217 bool enable
= detail::is_output_iterator
<OutputIt
, Char
>::value
&&
218 detail::is_locale
<Locale
>::value
&&
219 detail::is_exotic_char
<Char
>::value
>
220 inline auto format_to(OutputIt out
, const Locale
& loc
, const S
& format_str
,
222 typename
std::enable_if
<enable
, OutputIt
>::type
{
223 return vformat_to(out
, loc
, detail::to_string_view(format_str
),
224 fmt::make_format_args
<buffered_context
<Char
>>(args
...));
227 template <typename OutputIt
, typename Char
, typename
... Args
,
228 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, Char
>::value
&&
229 detail::is_exotic_char
<Char
>::value
)>
230 inline auto vformat_to_n(OutputIt out
, size_t n
,
231 basic_string_view
<Char
> format_str
,
232 typename
detail::vformat_args
<Char
>::type args
)
233 -> format_to_n_result
<OutputIt
> {
234 using traits
= detail::fixed_buffer_traits
;
235 auto buf
= detail::iterator_buffer
<OutputIt
, Char
, traits
>(out
, n
);
236 detail::vformat_to(buf
, format_str
, args
);
237 return {buf
.out(), buf
.count()};
240 template <typename OutputIt
, typename S
, typename
... T
,
241 typename Char
= detail::format_string_char_t
<S
>,
242 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, Char
>::value
&&
243 detail::is_exotic_char
<Char
>::value
)>
244 inline auto format_to_n(OutputIt out
, size_t n
, const S
& fmt
, T
&&... args
)
245 -> format_to_n_result
<OutputIt
> {
246 return vformat_to_n(out
, n
, fmt::basic_string_view
<Char
>(fmt
),
247 fmt::make_format_args
<buffered_context
<Char
>>(args
...));
250 template <typename S
, typename
... T
,
251 typename Char
= detail::format_string_char_t
<S
>,
252 FMT_ENABLE_IF(detail::is_exotic_char
<Char
>::value
)>
253 inline auto formatted_size(const S
& fmt
, T
&&... args
) -> size_t {
254 auto buf
= detail::counting_buffer
<Char
>();
255 detail::vformat_to(buf
, detail::to_string_view(fmt
),
256 fmt::make_format_args
<buffered_context
<Char
>>(args
...));
260 inline void vprint(std::FILE* f
, wstring_view fmt
, wformat_args args
) {
261 auto buf
= wmemory_buffer();
262 detail::vformat_to(buf
, fmt
, args
);
263 buf
.push_back(L
'\0');
264 if (std::fputws(buf
.data(), f
) == -1)
265 FMT_THROW(system_error(errno
, FMT_STRING("cannot write to file")));
268 inline void vprint(wstring_view fmt
, wformat_args args
) {
269 vprint(stdout
, fmt
, args
);
272 template <typename
... T
>
273 void print(std::FILE* f
, wformat_string
<T
...> fmt
, T
&&... args
) {
274 return vprint(f
, wstring_view(fmt
), fmt::make_wformat_args(args
...));
277 template <typename
... T
> void print(wformat_string
<T
...> fmt
, T
&&... args
) {
278 return vprint(wstring_view(fmt
), fmt::make_wformat_args(args
...));
281 template <typename
... T
>
282 void println(std::FILE* f
, wformat_string
<T
...> fmt
, T
&&... args
) {
283 return print(f
, L
"{}\n", fmt::format(fmt
, std::forward
<T
>(args
)...));
286 template <typename
... T
> void println(wformat_string
<T
...> fmt
, T
&&... args
) {
287 return print(L
"{}\n", fmt::format(fmt
, std::forward
<T
>(args
)...));
290 inline auto vformat(const text_style
& ts
, wstring_view fmt
, wformat_args args
)
292 auto buf
= wmemory_buffer();
293 detail::vformat_to(buf
, ts
, fmt
, args
);
294 return fmt::to_string(buf
);
297 template <typename
... T
>
298 inline auto format(const text_style
& ts
, wformat_string
<T
...> fmt
, T
&&... args
)
300 return fmt::vformat(ts
, fmt
, fmt::make_wformat_args(args
...));
303 template <typename
... T
>
304 FMT_DEPRECATED
void print(std::FILE* f
, const text_style
& ts
,
305 wformat_string
<T
...> fmt
, const T
&... args
) {
306 vprint(f
, ts
, fmt
, fmt::make_wformat_args(args
...));
309 template <typename
... T
>
310 FMT_DEPRECATED
void print(const text_style
& ts
, wformat_string
<T
...> fmt
,
312 return print(stdout
, ts
, fmt
, args
...);
315 /// Converts `value` to `std::wstring` using the default format for type `T`.
316 template <typename T
> inline auto to_wstring(const T
& value
) -> std::wstring
{
317 return format(FMT_STRING(L
"{}"), value
);
322 #endif // FMT_XCHAR_H_