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.
15 #ifndef FMT_STATIC_THOUSANDS_SEPARATOR
23 using is_exotic_char
= bool_constant
<!std::is_same
<T
, char>::value
>;
25 inline auto write_loc(std::back_insert_iterator
<detail::buffer
<wchar_t>> out
,
26 loc_value value
, const format_specs
<wchar_t>& specs
,
27 locale_ref loc
) -> bool {
28 #ifndef FMT_STATIC_THOUSANDS_SEPARATOR
30 std::use_facet
<std::numpunct
<wchar_t>>(loc
.get
<std::locale
>());
31 auto separator
= std::wstring();
32 auto grouping
= numpunct
.grouping();
33 if (!grouping
.empty()) separator
= std::wstring(1, numpunct
.thousands_sep());
34 return value
.visit(loc_writer
<wchar_t>{out
, specs
, separator
, grouping
, {}});
42 using wstring_view
= basic_string_view
<wchar_t>;
43 using wformat_parse_context
= basic_format_parse_context
<wchar_t>;
44 using wformat_context
= buffer_context
<wchar_t>;
45 using wformat_args
= basic_format_args
<wformat_context
>;
46 using wmemory_buffer
= basic_memory_buffer
<wchar_t>;
48 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
49 // Workaround broken conversion on older gcc.
50 template <typename
... Args
> using wformat_string
= wstring_view
;
51 inline auto runtime(wstring_view s
) -> wstring_view
{ return s
; }
53 template <typename
... Args
>
54 using wformat_string
= basic_format_string
<wchar_t, type_identity_t
<Args
>...>;
55 inline auto runtime(wstring_view s
) -> runtime_format_string
<wchar_t> {
60 template <> struct is_char
<wchar_t> : std::true_type
{};
61 template <> struct is_char
<detail::char8_type
> : std::true_type
{};
62 template <> struct is_char
<char16_t
> : std::true_type
{};
63 template <> struct is_char
<char32_t
> : std::true_type
{};
65 template <typename
... T
>
66 constexpr format_arg_store
<wformat_context
, T
...> make_wformat_args(
71 inline namespace literals
{
72 #if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_ARGS
73 constexpr detail::udl_arg
<wchar_t> operator"" _a(const wchar_t* s
, size_t) {
77 } // namespace literals
79 template <typename It
, typename Sentinel
>
80 auto join(It begin
, Sentinel end
, wstring_view sep
)
81 -> join_view
<It
, Sentinel
, wchar_t> {
82 return {begin
, end
, sep
};
85 template <typename Range
>
86 auto join(Range
&& range
, wstring_view sep
)
87 -> join_view
<detail::iterator_t
<Range
>, detail::sentinel_t
<Range
>,
89 return join(std::begin(range
), std::end(range
), sep
);
93 auto join(std::initializer_list
<T
> list
, wstring_view sep
)
94 -> join_view
<const T
*, const T
*, wchar_t> {
95 return join(std::begin(list
), std::end(list
), sep
);
98 template <typename Char
, FMT_ENABLE_IF(!std::is_same
<Char
, char>::value
)>
99 auto vformat(basic_string_view
<Char
> format_str
,
100 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
)
101 -> std::basic_string
<Char
> {
102 auto buf
= basic_memory_buffer
<Char
>();
103 detail::vformat_to(buf
, format_str
, args
);
104 return to_string(buf
);
107 template <typename
... T
>
108 auto format(wformat_string
<T
...> fmt
, T
&&... args
) -> std::wstring
{
109 return vformat(fmt::wstring_view(fmt
), fmt::make_wformat_args(args
...));
112 // Pass char_t as a default template parameter instead of using
113 // std::basic_string<char_t<S>> to reduce the symbol size.
114 template <typename S
, typename
... T
, typename Char
= char_t
<S
>,
115 FMT_ENABLE_IF(!std::is_same
<Char
, char>::value
&&
116 !std::is_same
<Char
, wchar_t>::value
)>
117 auto format(const S
& format_str
, T
&&... args
) -> std::basic_string
<Char
> {
118 return vformat(detail::to_string_view(format_str
),
119 fmt::make_format_args
<buffer_context
<Char
>>(args
...));
122 template <typename Locale
, typename S
, typename Char
= char_t
<S
>,
123 FMT_ENABLE_IF(detail::is_locale
<Locale
>::value
&&
124 detail::is_exotic_char
<Char
>::value
)>
126 const Locale
& loc
, const S
& format_str
,
127 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
)
128 -> std::basic_string
<Char
> {
129 return detail::vformat(loc
, detail::to_string_view(format_str
), args
);
132 template <typename Locale
, typename S
, typename
... T
, typename Char
= char_t
<S
>,
133 FMT_ENABLE_IF(detail::is_locale
<Locale
>::value
&&
134 detail::is_exotic_char
<Char
>::value
)>
135 inline auto format(const Locale
& loc
, const S
& format_str
, T
&&... args
)
136 -> std::basic_string
<Char
> {
137 return detail::vformat(loc
, detail::to_string_view(format_str
),
138 fmt::make_format_args
<buffer_context
<Char
>>(args
...));
141 template <typename OutputIt
, typename S
, typename Char
= char_t
<S
>,
142 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, Char
>::value
&&
143 detail::is_exotic_char
<Char
>::value
)>
144 auto vformat_to(OutputIt out
, const S
& format_str
,
145 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
)
147 auto&& buf
= detail::get_buffer
<Char
>(out
);
148 detail::vformat_to(buf
, detail::to_string_view(format_str
), args
);
149 return detail::get_iterator(buf
, out
);
152 template <typename OutputIt
, typename S
, typename
... T
,
153 typename Char
= char_t
<S
>,
154 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, Char
>::value
&&
155 detail::is_exotic_char
<Char
>::value
)>
156 inline auto format_to(OutputIt out
, const S
& fmt
, T
&&... args
) -> OutputIt
{
157 return vformat_to(out
, detail::to_string_view(fmt
),
158 fmt::make_format_args
<buffer_context
<Char
>>(args
...));
161 template <typename Locale
, typename S
, typename OutputIt
, typename
... Args
,
162 typename Char
= char_t
<S
>,
163 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, Char
>::value
&&
164 detail::is_locale
<Locale
>::value
&&
165 detail::is_exotic_char
<Char
>::value
)>
166 inline auto vformat_to(
167 OutputIt out
, const Locale
& loc
, const S
& format_str
,
168 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
) -> OutputIt
{
169 auto&& buf
= detail::get_buffer
<Char
>(out
);
170 vformat_to(buf
, detail::to_string_view(format_str
), args
,
171 detail::locale_ref(loc
));
172 return detail::get_iterator(buf
, out
);
176 typename OutputIt
, typename Locale
, typename S
, typename
... T
,
177 typename Char
= char_t
<S
>,
178 bool enable
= detail::is_output_iterator
<OutputIt
, Char
>::value
&&
179 detail::is_locale
<Locale
>::value
&& detail::is_exotic_char
<Char
>::value
>
180 inline auto format_to(OutputIt out
, const Locale
& loc
, const S
& format_str
,
182 typename
std::enable_if
<enable
, OutputIt
>::type
{
183 return vformat_to(out
, loc
, detail::to_string_view(format_str
),
184 fmt::make_format_args
<buffer_context
<Char
>>(args
...));
187 template <typename OutputIt
, typename Char
, typename
... Args
,
188 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, Char
>::value
&&
189 detail::is_exotic_char
<Char
>::value
)>
190 inline auto vformat_to_n(
191 OutputIt out
, size_t n
, basic_string_view
<Char
> format_str
,
192 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
)
193 -> format_to_n_result
<OutputIt
> {
194 using traits
= detail::fixed_buffer_traits
;
195 auto buf
= detail::iterator_buffer
<OutputIt
, Char
, traits
>(out
, n
);
196 detail::vformat_to(buf
, format_str
, args
);
197 return {buf
.out(), buf
.count()};
200 template <typename OutputIt
, typename S
, typename
... T
,
201 typename Char
= char_t
<S
>,
202 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, Char
>::value
&&
203 detail::is_exotic_char
<Char
>::value
)>
204 inline auto format_to_n(OutputIt out
, size_t n
, const S
& fmt
, T
&&... args
)
205 -> format_to_n_result
<OutputIt
> {
206 return vformat_to_n(out
, n
, detail::to_string_view(fmt
),
207 fmt::make_format_args
<buffer_context
<Char
>>(args
...));
210 template <typename S
, typename
... T
, typename Char
= char_t
<S
>,
211 FMT_ENABLE_IF(detail::is_exotic_char
<Char
>::value
)>
212 inline auto formatted_size(const S
& fmt
, T
&&... args
) -> size_t {
213 auto buf
= detail::counting_buffer
<Char
>();
214 detail::vformat_to(buf
, detail::to_string_view(fmt
),
215 fmt::make_format_args
<buffer_context
<Char
>>(args
...));
219 inline void vprint(std::FILE* f
, wstring_view fmt
, wformat_args args
) {
220 auto buf
= wmemory_buffer();
221 detail::vformat_to(buf
, fmt
, args
);
222 buf
.push_back(L
'\0');
223 if (std::fputws(buf
.data(), f
) == -1)
224 FMT_THROW(system_error(errno
, FMT_STRING("cannot write to file")));
227 inline void vprint(wstring_view fmt
, wformat_args args
) {
228 vprint(stdout
, fmt
, args
);
231 template <typename
... T
>
232 void print(std::FILE* f
, wformat_string
<T
...> fmt
, T
&&... args
) {
233 return vprint(f
, wstring_view(fmt
), fmt::make_wformat_args(args
...));
236 template <typename
... T
> void print(wformat_string
<T
...> fmt
, T
&&... args
) {
237 return vprint(wstring_view(fmt
), fmt::make_wformat_args(args
...));
240 template <typename
... T
>
241 void println(std::FILE* f
, wformat_string
<T
...> fmt
, T
&&... args
) {
242 return print(f
, L
"{}\n", fmt::format(fmt
, std::forward
<T
>(args
)...));
245 template <typename
... T
> void println(wformat_string
<T
...> fmt
, T
&&... args
) {
246 return print(L
"{}\n", fmt::format(fmt
, std::forward
<T
>(args
)...));
250 Converts *value* to ``std::wstring`` using the default format for type *T*.
252 template <typename T
> inline auto to_wstring(const T
& value
) -> std::wstring
{
253 return format(FMT_STRING(L
"{}"), value
);
258 #endif // FMT_XCHAR_H_