This commit is contained in:
Victor Zverovich 2019-07-07 07:21:20 -07:00
parent 79209598f5
commit 9c20e72de3
2 changed files with 32 additions and 40 deletions

View File

@ -842,9 +842,8 @@ Char* format_uint(Char* buffer, internal::fallback_uintptr n, int num_digits,
template <unsigned BASE_BITS, typename Char, typename It, typename UInt> template <unsigned BASE_BITS, typename Char, typename It, typename UInt>
inline It format_uint(It out, UInt value, int num_digits, bool upper = false) { inline It format_uint(It out, UInt value, int num_digits, bool upper = false) {
// Buffer should be large enough to hold all digits (digits / BASE_BITS + 1) // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1).
// and null. char buffer[std::numeric_limits<UInt>::digits / BASE_BITS + 1];
char buffer[std::numeric_limits<UInt>::digits / BASE_BITS + 2];
format_uint<BASE_BITS>(buffer, value, num_digits, upper); format_uint<BASE_BITS>(buffer, value, num_digits, upper);
return internal::copy_str<Char>(buffer, buffer + num_digits, out); return internal::copy_str<Char>(buffer, buffer + num_digits, out);
} }
@ -966,14 +965,10 @@ template <typename Char, typename It> It write_exponent(int exp, It it) {
if (exp >= 100) { if (exp >= 100) {
*it++ = static_cast<Char>(static_cast<char>('0' + exp / 100)); *it++ = static_cast<Char>(static_cast<char>('0' + exp / 100));
exp %= 100; exp %= 100;
const char* d = data::digits + exp * 2;
*it++ = static_cast<Char>(d[0]);
*it++ = static_cast<Char>(d[1]);
} else {
const char* d = data::digits + exp * 2;
*it++ = static_cast<Char>(d[0]);
*it++ = static_cast<Char>(d[1]);
} }
const char* d = data::digits + exp * 2;
*it++ = static_cast<Char>(d[0]);
*it++ = static_cast<Char>(d[1]);
return it; return it;
} }
@ -1226,7 +1221,7 @@ void arg_map<Context>::init(const basic_format_args<Context>& args) {
if (map_) return; if (map_) return;
map_ = new entry[args.max_size()]; map_ = new entry[args.max_size()];
if (args.is_packed()) { if (args.is_packed()) {
for (unsigned i = 0; /*nothing*/; ++i) { for (unsigned i = 0;; ++i) {
internal::type arg_type = args.type(i); internal::type arg_type = args.type(i);
if (arg_type == internal::none_type) return; if (arg_type == internal::none_type) return;
if (arg_type == internal::named_arg_type) push_back(args.values_[i]); if (arg_type == internal::named_arg_type) push_back(args.values_[i]);
@ -1239,15 +1234,13 @@ void arg_map<Context>::init(const basic_format_args<Context>& args) {
} }
} }
/** // This template provides operations for formatting and writing data into a
This template provides operations for formatting and writing data into a // character range.
character range.
*/
template <typename Range> class basic_writer { template <typename Range> class basic_writer {
public: public:
typedef typename Range::value_type char_type; using char_type = typename Range::value_type;
typedef decltype(std::declval<Range>().begin()) iterator; using iterator = typename Range::iterator;
typedef basic_format_specs<char_type> format_specs; using format_specs = basic_format_specs<char_type>;
private: private:
iterator out_; // Output iterator. iterator out_; // Output iterator.
@ -1403,7 +1396,7 @@ template <typename Range> class basic_writer {
bin_writer<3>{abs_value, num_digits}); bin_writer<3>{abs_value, num_digits});
} }
enum { SEP_SIZE = 1 }; enum { sep_size = 1 };
struct num_writer { struct num_writer {
unsigned_type abs_value; unsigned_type abs_value;
@ -1411,7 +1404,7 @@ template <typename Range> class basic_writer {
char_type sep; char_type sep;
template <typename It> void operator()(It&& it) const { template <typename It> void operator()(It&& it) const {
basic_string_view<char_type> s(&sep, SEP_SIZE); basic_string_view<char_type> s(&sep, sep_size);
// Index of a decimal digit with the least significant digit having // Index of a decimal digit with the least significant digit having
// index 0. // index 0.
unsigned digit_index = 0; unsigned digit_index = 0;
@ -1428,7 +1421,7 @@ template <typename Range> class basic_writer {
void on_num() { void on_num() {
int num_digits = internal::count_digits(abs_value); int num_digits = internal::count_digits(abs_value);
char_type sep = internal::thousands_sep<char_type>(writer.locale_); char_type sep = internal::thousands_sep<char_type>(writer.locale_);
int size = num_digits + SEP_SIZE * ((num_digits - 1) / 3); int size = num_digits + sep_size * ((num_digits - 1) / 3);
writer.write_int(size, get_prefix(), specs, writer.write_int(size, get_prefix(), specs,
num_writer{abs_value, size, sep}); num_writer{abs_value, size, sep});
} }
@ -1438,7 +1431,7 @@ template <typename Range> class basic_writer {
} }
}; };
enum { INF_SIZE = 3 }; // This is an enum to workaround a bug in MSVC. enum { inf_size = 3 }; // This is an enum to workaround a bug in MSVC.
struct inf_or_nan_writer { struct inf_or_nan_writer {
char sign; char sign;
@ -1446,7 +1439,7 @@ template <typename Range> class basic_writer {
const char* str; const char* str;
size_t size() const { size_t size() const {
return static_cast<std::size_t>(INF_SIZE + (sign ? 1 : 0) + return static_cast<std::size_t>(inf_size + (sign ? 1 : 0) +
(as_percentage ? 1 : 0)); (as_percentage ? 1 : 0));
} }
size_t width() const { return size(); } size_t width() const { return size(); }
@ -1454,7 +1447,7 @@ template <typename Range> class basic_writer {
template <typename It> void operator()(It&& it) const { template <typename It> void operator()(It&& it) const {
if (sign) *it++ = static_cast<char_type>(sign); if (sign) *it++ = static_cast<char_type>(sign);
it = internal::copy_str<char_type>( it = internal::copy_str<char_type>(
str, str + static_cast<std::size_t>(INF_SIZE), it); str, str + static_cast<std::size_t>(inf_size), it);
if (as_percentage) *it++ = static_cast<char_type>('%'); if (as_percentage) *it++ = static_cast<char_type>('%');
} }
}; };
@ -1672,12 +1665,12 @@ using writer = basic_writer<buffer_range<char>>;
template <typename Range, typename ErrorHandler = internal::error_handler> template <typename Range, typename ErrorHandler = internal::error_handler>
class arg_formatter_base { class arg_formatter_base {
public: public:
typedef typename Range::value_type char_type; using char_type = typename Range::value_type;
typedef decltype(std::declval<Range>().begin()) iterator; using iterator = typename Range::iterator;
typedef basic_format_specs<char_type> format_specs; using format_specs = basic_format_specs<char_type>;
private: private:
typedef basic_writer<Range> writer_type; using writer_type = basic_writer<Range>;
writer_type writer_; writer_type writer_;
format_specs* specs_; format_specs* specs_;

View File

@ -16,8 +16,8 @@ namespace internal {
template <class Char> class formatbuf : public std::basic_streambuf<Char> { template <class Char> class formatbuf : public std::basic_streambuf<Char> {
private: private:
typedef typename std::basic_streambuf<Char>::int_type int_type; using int_type = typename std::basic_streambuf<Char>::int_type;
typedef typename std::basic_streambuf<Char>::traits_type traits_type; using traits_type = typename std::basic_streambuf<Char>::traits_type;
buffer<Char>& buffer_; buffer<Char>& buffer_;
@ -63,7 +63,7 @@ template <typename T, typename Char> class is_streamable {
template <typename> static std::false_type test(...); template <typename> static std::false_type test(...);
typedef decltype(test<T>(0)) result; using result = decltype(test<T>(0));
public: public:
static const bool value = result::value; static const bool value = result::value;
@ -73,12 +73,12 @@ template <typename T, typename Char> class is_streamable {
template <typename Char> template <typename Char>
void write(std::basic_ostream<Char>& os, buffer<Char>& buf) { void write(std::basic_ostream<Char>& os, buffer<Char>& buf) {
const Char* buf_data = buf.data(); const Char* buf_data = buf.data();
typedef std::make_unsigned<std::streamsize>::type UnsignedStreamSize; using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
UnsignedStreamSize size = buf.size(); unsigned_streamsize size = buf.size();
UnsignedStreamSize max_size = unsigned_streamsize max_size =
internal::to_unsigned((std::numeric_limits<std::streamsize>::max)()); to_unsigned((std::numeric_limits<std::streamsize>::max)());
do { do {
UnsignedStreamSize n = size <= max_size ? size : max_size; unsigned_streamsize n = size <= max_size ? size : max_size;
os.write(buf_data, static_cast<std::streamsize>(n)); os.write(buf_data, static_cast<std::streamsize>(n));
buf_data += n; buf_data += n;
size -= n; size -= n;
@ -87,7 +87,7 @@ void write(std::basic_ostream<Char>& os, buffer<Char>& buf) {
template <typename Char, typename T> template <typename Char, typename T>
void format_value(buffer<Char>& buf, const T& value) { void format_value(buffer<Char>& buf, const T& value) {
internal::formatbuf<Char> format_buf(buf); formatbuf<Char> format_buf(buf);
std::basic_ostream<Char> output(&format_buf); std::basic_ostream<Char> output(&format_buf);
output.exceptions(std::ios_base::failbit | std::ios_base::badbit); output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
output << value; output << value;
@ -96,13 +96,12 @@ void format_value(buffer<Char>& buf, const T& value) {
// Formats an object of type T that has an overloaded ostream operator<<. // Formats an object of type T that has an overloaded ostream operator<<.
template <typename T, typename Char> template <typename T, typename Char>
struct fallback_formatter<T, Char, struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>
enable_if_t<internal::is_streamable<T, Char>::value>>
: formatter<basic_string_view<Char>, Char> { : formatter<basic_string_view<Char>, Char> {
template <typename Context> template <typename Context>
auto format(const T& value, Context& ctx) -> decltype(ctx.out()) { auto format(const T& value, Context& ctx) -> decltype(ctx.out()) {
basic_memory_buffer<Char> buffer; basic_memory_buffer<Char> buffer;
internal::format_value(buffer, value); format_value(buffer, value);
basic_string_view<Char> str(buffer.data(), buffer.size()); basic_string_view<Char> str(buffer.data(), buffer.size());
return formatter<basic_string_view<Char>, Char>::format(str, ctx); return formatter<basic_string_view<Char>, Char>::format(str, ctx);
} }