1212#include < fmt/format.h>
1313#include < fmt/base.h>
1414#include < boost/decimal/detail/config.hpp>
15+ #include < boost/decimal/detail/locale_conversion.hpp>
1516#include < boost/decimal/charconv.hpp>
1617#include < algorithm>
1718#include < format>
@@ -40,11 +41,19 @@ constexpr auto parse_impl(ParseContext &ctx)
4041 boost::decimal::chars_format fmt = boost::decimal::chars_format::general;
4142 bool is_upper = false ;
4243 int padding_digits = 0 ;
44+ bool use_locale = false ;
4345 auto it {ctx.begin ()};
4446
4547 if (it == nullptr )
4648 {
47- return std::make_tuple (ctx_precision, fmt, is_upper, padding_digits, sign_character, it);
49+ return std::make_tuple (ctx_precision, fmt, is_upper, padding_digits, sign_character, use_locale, it);
50+ }
51+
52+ // Check for the locale character
53+ if (*it == ' L' )
54+ {
55+ use_locale = true ;
56+ ++it;
4857 }
4958
5059 // Check for a sign character
@@ -156,7 +165,7 @@ constexpr auto parse_impl(ParseContext &ctx)
156165 BOOST_DECIMAL_THROW_EXCEPTION (std::logic_error (" Expected '}' in format string" )); // LCOV_EXCL_LINE
157166 }
158167
159- return std::make_tuple (ctx_precision, fmt, is_upper, padding_digits, sign_character, it);
168+ return std::make_tuple (ctx_precision, fmt, is_upper, padding_digits, sign_character, use_locale, it);
160169}
161170
162171template <typename T>
@@ -167,12 +176,14 @@ struct formatter
167176 int padding_digits;
168177 int ctx_precision;
169178 bool is_upper;
179+ bool use_locale;
170180
171181 constexpr formatter () : sign{sign_option::minus},
172182 fmt{chars_format::general},
173183 padding_digits{0 },
174184 ctx_precision{6 },
175- is_upper{false } {}
185+ is_upper{false },
186+ use_locale{false } {}
176187
177188 constexpr auto parse (fmt::format_parse_context &ctx)
178189 {
@@ -183,8 +194,9 @@ struct formatter
183194 is_upper = std::get<2 >(res);
184195 padding_digits = std::get<3 >(res);
185196 sign = std::get<4 >(res);
197+ use_locale = std::get<5 >(res);
186198
187- return std::get<5 >(res);
199+ return std::get<6 >(res);
188200 }
189201
190202 template <typename FormatContext>
@@ -254,6 +266,16 @@ struct formatter
254266 s.insert (s.begin () + static_cast <std::size_t >(has_sign), static_cast <std::size_t >(padding_digits) - s.size (), ' 0' );
255267 }
256268
269+ if (use_locale)
270+ {
271+ // We need approximately 1/3 more space in order to insert the thousands separators,
272+ // but after we have done our processing we need to shrink the string back down
273+ const auto initial_length {s.length ()};
274+ s.resize (s.length () * 4 / 3 + 1 );
275+ const auto offset {static_cast <std::size_t >(convert_pointer_pair_to_local_locale (const_cast <char *>(s.data ()), s.data () + s.length ()))};
276+ s.resize (initial_length + offset);
277+ }
278+
257279 return fmt::format_to (ctx.out (), " {}" , s);
258280 }
259281};
0 commit comments