From 96c28f748d6451b22a6f422c44973b872360e791 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Thu, 19 May 2016 18:12:56 -0700 Subject: [PATCH] Detect if lconv contains thousands_sep --- fmt/format.h | 34 ++++++++++++++++------------------ test/util-test.cc | 14 ++++++++++++++ 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/fmt/format.h b/fmt/format.h index ab675f35..7cdac979 100644 --- a/fmt/format.h +++ b/fmt/format.h @@ -910,23 +910,6 @@ class ThousandsSep { } }; -// Returns the thousands separator for the current locale. -// On android the lconv structure is stubbed using an empty structure. -// The test is for the size only, not for the presense of -// thousands_sep in std::lconv, because if one would add thousands_sep -// at some point, the size of structure would be at least sizeof(char*). -template= sizeof(char*))> -struct Locale { - static fmt::StringRef thousands_sep() { return ""; } -}; - -template -struct Locale { - static fmt::StringRef thousands_sep() { - return static_cast(std::localeconv())->thousands_sep; - } -}; - // Formats a decimal unsigned integer value writing into buffer. // thousands_sep is a functor that is called after writing each char to // add a thousands separator if necessary. @@ -1135,6 +1118,21 @@ struct Not { enum { value = 0 }; }; template<> struct Not { enum { value = 1 }; }; +template struct LConvCheck { + LConvCheck(int) {} +}; + +// Returns the thousands separator for the current locale. +// We check if ``lconv`` contains ``thousands_sep`` because on Android +// ``lconv`` is stubbed as an empty struct. +template +inline StringRef thousands_sep( + LConv *lc, LConvCheck = 0) { + return lc->thousands_sep; +} + +inline fmt::StringRef thousands_sep(...) { return ""; } + // Makes an Arg object from any type. template class MakeValue : public Arg { @@ -2795,7 +2793,7 @@ void BasicWriter::write_int(T value, Spec spec) { } case 'n': { unsigned num_digits = internal::count_digits(abs_value); - fmt::StringRef sep = internal::Locale::thousands_sep(); + fmt::StringRef sep = internal::thousands_sep(std::localeconv()); unsigned size = static_cast( num_digits + sep.size() * (num_digits - 1) / 3); CharPtr p = prepare_int_buffer(size, spec, prefix, prefix_size) + 1; diff --git a/test/util-test.cc b/test/util-test.cc index 28bb77b1..838b3b14 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -956,3 +956,17 @@ TEST(UtilTest, Conditional) { fmt::internal::Conditional::type *pc = &c; (void)pc; } + +struct TestLConv { + char *thousands_sep; +}; + +struct EmptyLConv {}; + +TEST(UtilTest, ThousandsSep) { + char foo[] = "foo"; + TestLConv lc = {foo}; + EXPECT_EQ("foo", fmt::internal::thousands_sep(&lc).to_string()); + EmptyLConv empty_lc; + EXPECT_EQ("", fmt::internal::thousands_sep(&empty_lc)); +}