Make 'L' a modifier

This commit is contained in:
Victor Zverovich 2021-01-17 09:01:00 -08:00
parent 6972b5f3d2
commit e4f2cf455e
3 changed files with 22 additions and 3 deletions

View File

@ -1252,6 +1252,7 @@ template <typename Char> struct basic_format_specs {
align_t align : 4; align_t align : 4;
sign_t sign : 3; sign_t sign : 3;
bool alt : 1; // Alternate form ('#'). bool alt : 1; // Alternate form ('#').
bool localized : 1;
detail::fill_t<Char> fill; detail::fill_t<Char> fill;
constexpr basic_format_specs() constexpr basic_format_specs()
@ -1260,7 +1261,8 @@ template <typename Char> struct basic_format_specs {
type(0), type(0),
align(align::none), align(align::none),
sign(sign::none), sign(sign::none),
alt(false) {} alt(false),
localized(false) {}
}; };
using format_specs = basic_format_specs<char>; using format_specs = basic_format_specs<char>;
@ -1427,6 +1429,7 @@ FMT_CONSTEXPR float_specs parse_float_type_spec(
const basic_format_specs<Char>& specs, ErrorHandler&& eh = {}) { const basic_format_specs<Char>& specs, ErrorHandler&& eh = {}) {
auto result = float_specs(); auto result = float_specs();
result.showpoint = specs.alt; result.showpoint = specs.alt;
result.locale = specs.localized;
switch (specs.type) { switch (specs.type) {
case 0: case 0:
result.format = float_format::general; result.format = float_format::general;
@ -1693,6 +1696,7 @@ template <typename OutputIt, typename Char, typename UInt> struct int_writer {
} }
FMT_CONSTEXPR void on_dec() { FMT_CONSTEXPR void on_dec() {
if (specs.localized) return on_num();
auto num_digits = count_digits(abs_value); auto num_digits = count_digits(abs_value);
out = write_int( out = write_int(
out, num_digits, get_prefix(), specs, [this, num_digits](iterator it) { out, num_digits, get_prefix(), specs, [this, num_digits](iterator it) {
@ -2527,6 +2531,7 @@ template <typename Char> class specs_setter {
FMT_CONSTEXPR void on_minus() { specs_.sign = sign::minus; } FMT_CONSTEXPR void on_minus() { specs_.sign = sign::minus; }
FMT_CONSTEXPR void on_space() { specs_.sign = sign::space; } FMT_CONSTEXPR void on_space() { specs_.sign = sign::space; }
FMT_CONSTEXPR void on_hash() { specs_.alt = true; } FMT_CONSTEXPR void on_hash() { specs_.alt = true; }
FMT_CONSTEXPR void on_localized() { specs_.localized = true; }
FMT_CONSTEXPR void on_zero() { FMT_CONSTEXPR void on_zero() {
specs_.align = align::numeric; specs_.align = align::numeric;
@ -2616,6 +2621,11 @@ template <typename Handler> class specs_checker : public Handler {
Handler::on_hash(); Handler::on_hash();
} }
FMT_CONSTEXPR void on_localized() {
checker_.require_numeric_argument();
Handler::on_localized();
}
FMT_CONSTEXPR void on_zero() { FMT_CONSTEXPR void on_zero() {
checker_.require_numeric_argument(); checker_.require_numeric_argument();
Handler::on_zero(); Handler::on_zero();
@ -2996,6 +3006,12 @@ FMT_CONSTEXPR const Char* parse_format_specs(const Char* begin, const Char* end,
// Parse precision. // Parse precision.
if (*begin == '.') { if (*begin == '.') {
begin = parse_precision(begin, end, handler); begin = parse_precision(begin, end, handler);
if (begin == end) return begin;
}
if (*begin == 'L') {
handler.on_localized();
++begin;
} }
// Parse type. // Parse type.

View File

@ -1112,7 +1112,7 @@ TEST(FormatterTest, RuntimePrecision) {
template <typename T> template <typename T>
void check_unknown_types(const T& value, const char* types, const char*) { void check_unknown_types(const T& value, const char* types, const char*) {
char format_str[BUFFER_SIZE]; char format_str[BUFFER_SIZE];
const char* special = ".0123456789}"; const char* special = ".0123456789L}";
for (int i = CHAR_MIN; i <= CHAR_MAX; ++i) { for (int i = CHAR_MIN; i <= CHAR_MAX; ++i) {
char c = static_cast<char>(i); char c = static_cast<char>(i);
if (std::strchr(types, c) || std::strchr(special, c) || !c) continue; if (std::strchr(types, c) || std::strchr(special, c) || !c) continue;
@ -2140,7 +2140,7 @@ TEST(FormatTest, ConstexprParseArgID) {
} }
struct test_format_specs_handler { struct test_format_specs_handler {
enum Result { NONE, PLUS, MINUS, SPACE, HASH, ZERO, ERROR }; enum Result { NONE, PLUS, MINUS, SPACE, HASH, ZERO, LOC, ERROR };
Result res = NONE; Result res = NONE;
fmt::align_t alignment = fmt::align::none; fmt::align_t alignment = fmt::align::none;
@ -2172,6 +2172,7 @@ struct test_format_specs_handler {
FMT_CONSTEXPR void on_space() { res = SPACE; } FMT_CONSTEXPR void on_space() { res = SPACE; }
FMT_CONSTEXPR void on_hash() { res = HASH; } FMT_CONSTEXPR void on_hash() { res = HASH; }
FMT_CONSTEXPR void on_zero() { res = ZERO; } FMT_CONSTEXPR void on_zero() { res = ZERO; }
FMT_CONSTEXPR void on_localized() { res = LOC; }
FMT_CONSTEXPR void on_width(int w) { width = w; } FMT_CONSTEXPR void on_width(int w) { width = w; }
FMT_CONSTEXPR void on_dynamic_width(fmt::detail::auto_id) {} FMT_CONSTEXPR void on_dynamic_width(fmt::detail::auto_id) {}
@ -2204,6 +2205,7 @@ TEST(FormatTest, ConstexprParseFormatSpecs) {
static_assert(parse_test_specs(" ").res == handler::SPACE, ""); static_assert(parse_test_specs(" ").res == handler::SPACE, "");
static_assert(parse_test_specs("#").res == handler::HASH, ""); static_assert(parse_test_specs("#").res == handler::HASH, "");
static_assert(parse_test_specs("0").res == handler::ZERO, ""); static_assert(parse_test_specs("0").res == handler::ZERO, "");
static_assert(parse_test_specs("L").res == handler::LOC, "");
static_assert(parse_test_specs("42").width == 42, ""); static_assert(parse_test_specs("42").width == 42, "");
static_assert(parse_test_specs("{42}").width_ref.val.index == 42, ""); static_assert(parse_test_specs("{42}").width_ref.val.index == 42, "");
static_assert(parse_test_specs(".42").precision == 42, ""); static_assert(parse_test_specs(".42").precision == 42, "");

View File

@ -45,6 +45,7 @@ template <typename Char> struct small_grouping : std::numpunct<Char> {
TEST(LocaleTest, DoubleDecimalPoint) { TEST(LocaleTest, DoubleDecimalPoint) {
std::locale loc(std::locale(), new numpunct<char>()); std::locale loc(std::locale(), new numpunct<char>());
EXPECT_EQ("1?23", fmt::format(loc, "{:L}", 1.23)); EXPECT_EQ("1?23", fmt::format(loc, "{:L}", 1.23));
EXPECT_EQ("1?230000", fmt::format(loc, "{:Lf}", 1.23));
} }
TEST(LocaleTest, Format) { TEST(LocaleTest, Format) {