Don't use stringstream

This commit is contained in:
Victor Zverovich
2022-09-02 12:58:40 -07:00
parent d6a8704605
commit fc5e59fe4a
3 changed files with 28 additions and 34 deletions

View File

@ -17,7 +17,6 @@
#include <cstring> // std::memmove #include <cstring> // std::memmove
#include <cwchar> #include <cwchar>
#include <exception> #include <exception>
#include <sstream>
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR #ifndef FMT_STATIC_THOUSANDS_SEPARATOR
# include <locale> # include <locale>
@ -119,20 +118,18 @@ template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref) {
} }
#endif #endif
FMT_FUNC auto write_int(unsigned long long value, const format_specs& specs, FMT_FUNC auto write_int(appender out, unsigned long long value,
locale_ref loc) -> std::string { const format_specs& specs, locale_ref loc) -> bool {
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR #ifndef FMT_STATIC_THOUSANDS_SEPARATOR
auto locale = loc.get<std::locale>(); auto locale = loc.get<std::locale>();
// We cannot use the num_put<char> facet because it may produce output in // We cannot use the num_put<char> facet because it may produce output in
// a wrong encoding. // a wrong encoding.
if (!std::has_facet<num_format_facet<std::locale>>(locale)) return {}; if (!std::has_facet<num_format_facet<std::locale>>(locale)) return {};
auto&& buf = std::basic_stringbuf<char>();
auto out = std::ostreambuf_iterator<char>(&buf);
std::use_facet<num_format_facet<std::locale>>(locale).put(out, value, specs, std::use_facet<num_format_facet<std::locale>>(locale).put(out, value, specs,
locale); locale);
return buf.str(); return true;
#endif #endif
return {}; return false;
} }
} // namespace detail } // namespace detail

View File

@ -2014,33 +2014,35 @@ auto write_int(OutputIt out, UInt value, unsigned prefix,
}); });
} }
FMT_API auto write_int(unsigned long long value, const format_specs& specs, FMT_API auto write_int(appender out, unsigned long long value,
locale_ref loc) -> std::string; const format_specs& specs, locale_ref loc) -> bool;
template <typename Char> template <typename OutputIt, typename Char>
inline auto write_int(unsigned long long, const basic_format_specs<Char>&, inline auto write_int(OutputIt, unsigned long long,
locale_ref) -> std::string { const basic_format_specs<Char>&, locale_ref) -> bool {
return {}; return false;
} }
template <typename OutputIt, typename UInt, typename Char> template <typename OutputIt, typename UInt, typename Char>
auto write_int(OutputIt& out, UInt value, unsigned prefix, auto write_int(OutputIt& out, UInt value, unsigned prefix,
const basic_format_specs<Char>& specs, locale_ref loc) -> bool { const basic_format_specs<Char>& specs, locale_ref loc) -> bool {
auto str = std::string(); auto result = false;
auto buf = memory_buffer();
if (sizeof(value) <= sizeof(unsigned long long)) if (sizeof(value) <= sizeof(unsigned long long))
str = write_int(static_cast<unsigned long long>(value), specs, loc); result = write_int(appender(buf), static_cast<unsigned long long>(value),
if (str.empty()) { specs, loc);
if (!result) {
auto grouping = digit_grouping<Char>(loc); auto grouping = digit_grouping<Char>(loc);
out = write_int(out, value, prefix, specs, grouping); out = write_int(out, value, prefix, specs, grouping);
return true; return true;
} }
size_t size = to_unsigned((prefix != 0 ? 1 : 0) + str.size()); size_t size = to_unsigned((prefix != 0 ? 1 : 0) + buf.size());
out = write_padded<align::right>( out = write_padded<align::right>(
out, specs, size, size, [&](reserve_iterator<OutputIt> it) { out, specs, size, size, [&](reserve_iterator<OutputIt> it) {
if (prefix != 0) { if (prefix != 0) {
char sign = static_cast<char>(prefix); char sign = static_cast<char>(prefix);
*it++ = static_cast<Char>(sign); *it++ = static_cast<Char>(sign);
} }
return copy_str<Char>(str.data(), str.data() + str.size(), it); return copy_str<Char>(buf.data(), buf.data() + buf.size(), it);
}); });
return true; return true;
} }
@ -4180,17 +4182,14 @@ template <typename Locale> class num_format_facet : public Locale::facet {
public: public:
static FMT_API typename Locale::id id; static FMT_API typename Locale::id id;
using iter_type = std::ostreambuf_iterator<char>; void put(appender out, unsigned long long val, const format_specs& specs,
Locale& loc) const {
auto put(iter_type out, unsigned long long val, const format_specs& specs, do_put(out, val, specs, loc);
Locale& loc) const -> iter_type {
return do_put(out, val, specs, loc);
} }
protected: protected:
virtual auto do_put(iter_type out, unsigned long long val, virtual void do_put(appender out, unsigned long long val,
const format_specs& specs, Locale& loc) const const format_specs& specs, Locale& loc) const = 0;
-> iter_type = 0;
}; };
#if FMT_USE_USER_DEFINED_LITERALS #if FMT_USE_USER_DEFINED_LITERALS

View File

@ -522,20 +522,18 @@ TEST(locale_test, sign) {
class num_format : public fmt::num_format_facet<std::locale> { class num_format : public fmt::num_format_facet<std::locale> {
protected: protected:
iter_type do_put(iter_type out, unsigned long long, const fmt::format_specs&, void do_put(fmt::appender out, unsigned long long, const fmt::format_specs&,
std::locale&) const override; std::locale&) const override;
}; };
num_format::iter_type num_format::do_put(iter_type out, unsigned long long, void num_format::do_put(fmt::appender out, unsigned long long value,
const fmt::format_specs&, const fmt::format_specs&, std::locale&) const {
std::locale&) const { fmt::format_to(out, "[{}]", value);
const char s[] = "foo";
return std::copy_n(s, sizeof(s) - 1, out);
} }
TEST(locale_test, num_format) { TEST(locale_test, num_format) {
auto loc = std::locale(std::locale(), new num_format()); auto loc = std::locale(std::locale(), new num_format());
EXPECT_EQ(fmt::format(loc, "{:L}", 42), "foo"); EXPECT_EQ(fmt::format(loc, "{:L}", 42), "[42]");
} }
#endif // FMT_STATIC_THOUSANDS_SEPARATOR #endif // FMT_STATIC_THOUSANDS_SEPARATOR