@@ -3808,6 +3808,71 @@ template <typename Char> struct udl_arg {
3808
3808
# endif
3809
3809
#endif // FMT_USE_USER_DEFINED_LITERALS
3810
3810
3811
+ template <typename Char> struct format_handler {
3812
+ parse_context<Char> parse_ctx;
3813
+ buffered_context<Char> ctx;
3814
+
3815
+ void on_text (const Char* begin, const Char* end) {
3816
+ copy_noinline<Char>(begin, end, ctx.out ());
3817
+ }
3818
+
3819
+ FMT_CONSTEXPR auto on_arg_id () -> int { return parse_ctx.next_arg_id (); }
3820
+ FMT_CONSTEXPR auto on_arg_id (int id) -> int {
3821
+ parse_ctx.check_arg_id (id);
3822
+ return id;
3823
+ }
3824
+ FMT_CONSTEXPR auto on_arg_id (basic_string_view<Char> id) -> int {
3825
+ parse_ctx.check_arg_id (id);
3826
+ int arg_id = ctx.arg_id (id);
3827
+ if (arg_id < 0 ) report_error (" argument not found" );
3828
+ return arg_id;
3829
+ }
3830
+
3831
+ FMT_INLINE void on_replacement_field (int id, const Char*) {
3832
+ ctx.arg (id).visit (default_arg_formatter<Char>{ctx.out ()});
3833
+ }
3834
+
3835
+ auto on_format_specs (int id, const Char* begin, const Char* end)
3836
+ -> const Char* {
3837
+ auto arg = get_arg (ctx, id);
3838
+ // Not using a visitor for custom types gives better codegen.
3839
+ if (arg.format_custom (begin, parse_ctx, ctx)) return parse_ctx.begin ();
3840
+
3841
+ auto specs = dynamic_format_specs<Char>();
3842
+ begin = parse_format_specs (begin, end, specs, parse_ctx, arg.type ());
3843
+ if (specs.dynamic ()) {
3844
+ handle_dynamic_spec (specs.dynamic_width (), specs.width , specs.width_ref ,
3845
+ ctx);
3846
+ handle_dynamic_spec (specs.dynamic_precision (), specs.precision ,
3847
+ specs.precision_ref , ctx);
3848
+ }
3849
+
3850
+ arg.visit (arg_formatter<Char>{ctx.out (), specs, ctx.locale ()});
3851
+ return begin;
3852
+ }
3853
+
3854
+ FMT_NORETURN void on_error (const char * message) { report_error (message); }
3855
+ };
3856
+
3857
+ // DEPRECATED!
3858
+ // Use vformat_args and avoid type_identity to keep symbols short.
3859
+ template <typename Char = char > struct vformat_args {
3860
+ using type = basic_format_args<buffered_context<Char>>;
3861
+ };
3862
+ template <> struct vformat_args <char > {
3863
+ using type = format_args;
3864
+ };
3865
+
3866
+ template <typename Char>
3867
+ void vformat_to (buffer<Char>& buf, basic_string_view<Char> fmt,
3868
+ typename vformat_args<Char>::type args, locale_ref loc = {}) {
3869
+ auto out = basic_appender<Char>(buf);
3870
+ if (fmt.size () == 2 && equal2 (fmt.data (), " {}" ))
3871
+ return args.get (0 ).visit (default_arg_formatter<Char>{out});
3872
+ parse_format_string (
3873
+ fmt, format_handler<Char>{parse_context<Char>(fmt), {out, args, loc}});
3874
+ }
3875
+
3811
3876
template <typename Locale, typename Char>
3812
3877
auto vformat (const Locale& loc, basic_string_view<Char> fmt,
3813
3878
typename detail::vformat_args<Char>::type args)
@@ -4188,68 +4253,9 @@ FMT_END_EXPORT
4188
4253
4189
4254
namespace detail {
4190
4255
4191
- template <typename Char> struct format_handler {
4192
- parse_context<Char> parse_ctx;
4193
- buffered_context<Char> ctx;
4194
-
4195
- void on_text (const Char* begin, const Char* end) {
4196
- copy_noinline<Char>(begin, end, ctx.out ());
4197
- }
4198
-
4199
- FMT_CONSTEXPR auto on_arg_id () -> int { return parse_ctx.next_arg_id (); }
4200
- FMT_CONSTEXPR auto on_arg_id (int id) -> int {
4201
- parse_ctx.check_arg_id (id);
4202
- return id;
4203
- }
4204
- FMT_CONSTEXPR auto on_arg_id (basic_string_view<Char> id) -> int {
4205
- parse_ctx.check_arg_id (id);
4206
- int arg_id = ctx.arg_id (id);
4207
- if (arg_id < 0 ) report_error (" argument not found" );
4208
- return arg_id;
4209
- }
4210
-
4211
- FMT_INLINE void on_replacement_field (int id, const Char*) {
4212
- ctx.arg (id).visit (default_arg_formatter<Char>{ctx.out ()});
4213
- }
4214
-
4215
- auto on_format_specs (int id, const Char* begin, const Char* end)
4216
- -> const Char* {
4217
- auto arg = get_arg (ctx, id);
4218
- // Not using a visitor for custom types gives better codegen.
4219
- if (arg.format_custom (begin, parse_ctx, ctx)) return parse_ctx.begin ();
4220
-
4221
- auto specs = dynamic_format_specs<Char>();
4222
- begin = parse_format_specs (begin, end, specs, parse_ctx, arg.type ());
4223
- if (specs.dynamic ()) {
4224
- handle_dynamic_spec (specs.dynamic_width (), specs.width , specs.width_ref ,
4225
- ctx);
4226
- handle_dynamic_spec (specs.dynamic_precision (), specs.precision ,
4227
- specs.precision_ref , ctx);
4228
- }
4229
-
4230
- arg.visit (arg_formatter<Char>{ctx.out (), specs, ctx.locale ()});
4231
- return begin;
4232
- }
4233
-
4234
- FMT_NORETURN void on_error (const char * message) { report_error (message); }
4235
- };
4236
-
4237
- template <typename Char>
4238
- void vformat_to (buffer<Char>& buf, basic_string_view<Char> fmt,
4239
- typename vformat_args<Char>::type args, locale_ref loc) {
4240
- auto out = basic_appender<Char>(buf);
4241
- if (fmt.size () == 2 && equal2 (fmt.data (), " {}" ))
4242
- return args.get (0 ).visit (default_arg_formatter<Char>{out});
4243
- parse_format_string (
4244
- fmt, format_handler<Char>{parse_context<Char>(fmt), {out, args, loc}});
4245
- }
4246
-
4247
4256
FMT_BEGIN_EXPORT
4248
4257
4249
4258
#ifndef FMT_HEADER_ONLY
4250
- extern template FMT_API void vformat_to (buffer<char >&, string_view,
4251
- typename vformat_args<>::type,
4252
- locale_ref);
4253
4259
extern template FMT_API auto thousands_sep_impl<char >(locale_ref)
4254
4260
-> thousands_sep_result<char >;
4255
4261
extern template FMT_API auto thousands_sep_impl<wchar_t >(locale_ref)
@@ -4361,8 +4367,8 @@ FMT_NODISCARD FMT_INLINE auto formatted_size(const Locale& loc,
4361
4367
format_string<T...> fmt,
4362
4368
T&&... args) -> size_t {
4363
4369
auto buf = detail::counting_buffer<>();
4364
- detail::vformat_to< char > (buf, fmt, fmt::make_format_args (args...),
4365
- detail::locale_ref (loc));
4370
+ detail::vformat_to (buf, fmt, fmt::make_format_args (args...),
4371
+ detail::locale_ref (loc));
4366
4372
return buf.count ();
4367
4373
}
4368
4374
0 commit comments