mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-23 10:50:05 +00:00
Parameterize basic_writer on buffer type
This commit is contained in:
parent
6f2769d0b4
commit
3663414053
@ -287,14 +287,14 @@ FMT_DISABLE_CONVERSION_TO_INT(float);
|
|||||||
FMT_DISABLE_CONVERSION_TO_INT(double);
|
FMT_DISABLE_CONVERSION_TO_INT(double);
|
||||||
FMT_DISABLE_CONVERSION_TO_INT(long double);
|
FMT_DISABLE_CONVERSION_TO_INT(long double);
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Context>
|
||||||
struct named_arg;
|
struct named_arg;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_named_arg : std::false_type {};
|
struct is_named_arg : std::false_type {};
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Context>
|
||||||
struct is_named_arg<named_arg<Char>> : std::true_type {};
|
struct is_named_arg<named_arg<Context>> : std::true_type {};
|
||||||
|
|
||||||
enum type {
|
enum type {
|
||||||
NONE, NAMED_ARG,
|
NONE, NAMED_ARG,
|
||||||
@ -488,12 +488,12 @@ class value {
|
|||||||
custom.format = &format_custom_arg<T>;
|
custom.format = &format_custom_arg<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Additional template param `Char` is needed here because get_type always
|
// Additional template param `Ctx` is needed here because get_type always
|
||||||
// uses char.
|
// uses basic_context<char>.
|
||||||
template <typename Char>
|
template <typename Ctx>
|
||||||
value(const named_arg<Char> &value) {
|
value(const named_arg<Ctx> &value) {
|
||||||
static_assert(
|
static_assert(
|
||||||
get_type<const named_arg<Char> &>() == NAMED_ARG, "invalid type");
|
get_type<const named_arg<Ctx> &>() == NAMED_ARG, "invalid type");
|
||||||
pointer = &value;
|
pointer = &value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -664,12 +664,12 @@ inline typename std::enable_if<!IS_PACKED, basic_arg<Context>>::type
|
|||||||
|
|
||||||
template <typename Context>
|
template <typename Context>
|
||||||
struct named_arg : basic_arg<Context> {
|
struct named_arg : basic_arg<Context> {
|
||||||
typedef typename Context::char_type Char;
|
using char_type = typename Context::char_type;
|
||||||
|
|
||||||
basic_string_view<Char> name;
|
basic_string_view<char_type> name;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
named_arg(basic_string_view<Char> argname, const T &value)
|
named_arg(basic_string_view<char_type> argname, const T &value)
|
||||||
: basic_arg<Context>(make_arg<Context>(value)), name(argname) {}
|
: basic_arg<Context>(make_arg<Context>(value)), name(argname) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -678,10 +678,10 @@ class arg_map {
|
|||||||
private:
|
private:
|
||||||
FMT_DISALLOW_COPY_AND_ASSIGN(arg_map);
|
FMT_DISALLOW_COPY_AND_ASSIGN(arg_map);
|
||||||
|
|
||||||
using Char = typename Context::char_type;
|
using char_type = typename Context::char_type;
|
||||||
|
|
||||||
struct arg {
|
struct arg {
|
||||||
fmt::basic_string_view<Char> name;
|
fmt::basic_string_view<char_type> name;
|
||||||
basic_arg<Context> value;
|
basic_arg<Context> value;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -699,7 +699,7 @@ class arg_map {
|
|||||||
~arg_map() { delete [] map_; }
|
~arg_map() { delete [] map_; }
|
||||||
|
|
||||||
const basic_arg<Context>
|
const basic_arg<Context>
|
||||||
*find(const fmt::basic_string_view<Char> &name) const {
|
*find(const fmt::basic_string_view<char_type> &name) const {
|
||||||
// The list is unsorted, so just return the first matching name.
|
// The list is unsorted, so just return the first matching name.
|
||||||
for (auto it = map_, end = map_ + size_; it != end; ++it) {
|
for (auto it = map_, end = map_ + size_; it != end; ++it) {
|
||||||
if (it->name == name)
|
if (it->name == name)
|
||||||
|
@ -198,7 +198,7 @@ void format_error_code(buffer &out, int error_code,
|
|||||||
++error_code_size;
|
++error_code_size;
|
||||||
}
|
}
|
||||||
error_code_size += internal::count_digits(abs_value);
|
error_code_size += internal::count_digits(abs_value);
|
||||||
basic_writer<char> w(out);
|
basic_writer<buffer> w(out);
|
||||||
if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size) {
|
if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size) {
|
||||||
w.write(message);
|
w.write(message);
|
||||||
w.write(SEP);
|
w.write(SEP);
|
||||||
@ -380,13 +380,13 @@ FMT_FUNC void internal::format_windows_error(
|
|||||||
FMT_FUNC void format_system_error(
|
FMT_FUNC void format_system_error(
|
||||||
buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
|
buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
|
||||||
FMT_TRY {
|
FMT_TRY {
|
||||||
memory_buffer buffer;
|
memory_buffer buf;
|
||||||
buffer.resize(internal::INLINE_BUFFER_SIZE);
|
buf.resize(internal::INLINE_BUFFER_SIZE);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char *system_message = &buffer[0];
|
char *system_message = &buf[0];
|
||||||
int result = safe_strerror(error_code, system_message, buffer.size());
|
int result = safe_strerror(error_code, system_message, buf.size());
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
basic_writer<char> w(out);
|
basic_writer<buffer> w(out);
|
||||||
w.write(message);
|
w.write(message);
|
||||||
w.write(": ");
|
w.write(": ");
|
||||||
w.write(system_message);
|
w.write(system_message);
|
||||||
@ -394,7 +394,7 @@ FMT_FUNC void format_system_error(
|
|||||||
}
|
}
|
||||||
if (result != ERANGE)
|
if (result != ERANGE)
|
||||||
break; // Can't get error message, report error code instead.
|
break; // Can't get error message, report error code instead.
|
||||||
buffer.resize(buffer.size() * 2);
|
buf.resize(buf.size() * 2);
|
||||||
}
|
}
|
||||||
} FMT_CATCH(...) {}
|
} FMT_CATCH(...) {}
|
||||||
fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
|
fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
|
||||||
|
@ -336,6 +336,8 @@ class basic_buffer {
|
|||||||
virtual void grow(std::size_t capacity) = 0;
|
virtual void grow(std::size_t capacity) = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
|
||||||
virtual ~basic_buffer() {}
|
virtual ~basic_buffer() {}
|
||||||
|
|
||||||
/** Returns the size of this buffer. */
|
/** Returns the size of this buffer. */
|
||||||
@ -1298,13 +1300,14 @@ class arg_formatter_base {
|
|||||||
typedef basic_format_specs<Char> format_specs;
|
typedef basic_format_specs<Char> format_specs;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
basic_writer<Char> writer_;
|
using writer_type = basic_writer<basic_buffer<Char>>;
|
||||||
|
writer_type writer_;
|
||||||
format_specs &specs_;
|
format_specs &specs_;
|
||||||
|
|
||||||
FMT_DISALLOW_COPY_AND_ASSIGN(arg_formatter_base);
|
FMT_DISALLOW_COPY_AND_ASSIGN(arg_formatter_base);
|
||||||
|
|
||||||
void write_char(Char value) {
|
void write_char(Char value) {
|
||||||
using pointer_type = typename basic_writer<Char>::pointer_type;
|
using pointer_type = typename writer_type::pointer_type;
|
||||||
Char fill = internal::char_traits<Char>::cast(specs_.fill());
|
Char fill = internal::char_traits<Char>::cast(specs_.fill());
|
||||||
pointer_type out = pointer_type();
|
pointer_type out = pointer_type();
|
||||||
const unsigned character_width = 1;
|
const unsigned character_width = 1;
|
||||||
@ -1333,7 +1336,7 @@ class arg_formatter_base {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
basic_writer<Char> &writer() { return writer_; }
|
writer_type &writer() { return writer_; }
|
||||||
format_specs &spec() { return specs_; }
|
format_specs &spec() { return specs_; }
|
||||||
|
|
||||||
void write(bool value) {
|
void write(bool value) {
|
||||||
@ -2156,39 +2159,39 @@ FMT_API void format_system_error(fmt::buffer &out, int error_code,
|
|||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
This template provides operations for formatting and writing data into a
|
This template provides operations for formatting and writing data into a
|
||||||
character buffer. The output buffer is specified by a subclass such as
|
character buffer.
|
||||||
:class:`fmt::BasicMemoryWriter`.
|
|
||||||
|
|
||||||
You can use one of the following typedefs for common character types:
|
You can use one of the following typedefs for common character types:
|
||||||
|
|
||||||
+---------+-----------------------+
|
+---------+-----------------------+
|
||||||
| Type | Definition |
|
| Type | Definition |
|
||||||
+=========+=======================+
|
+=========+=======================+
|
||||||
| writer | basic_writer<char> |
|
| writer | basic_writer<buffer> |
|
||||||
+---------+-----------------------+
|
+---------+-----------------------+
|
||||||
| wwriter | basic_writer<wchar_t> |
|
| wwriter | basic_writer<wbuffer> |
|
||||||
+---------+-----------------------+
|
+---------+-----------------------+
|
||||||
|
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
template <typename Char>
|
template <typename Buffer>
|
||||||
class basic_writer {
|
class basic_writer {
|
||||||
public:
|
public:
|
||||||
typedef basic_format_specs<Char> format_specs;
|
using char_type = typename Buffer::value_type;
|
||||||
|
typedef basic_format_specs<char_type> format_specs;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Output buffer.
|
// Output buffer.
|
||||||
basic_buffer<Char> &buffer_;
|
Buffer &buffer_;
|
||||||
|
|
||||||
FMT_DISALLOW_COPY_AND_ASSIGN(basic_writer);
|
FMT_DISALLOW_COPY_AND_ASSIGN(basic_writer);
|
||||||
|
|
||||||
#if FMT_SECURE_SCL
|
#if FMT_SECURE_SCL
|
||||||
typedef stdext::checked_array_iterator<Char*> pointer_type;
|
typedef stdext::checked_array_iterator<Char*> pointer_type;
|
||||||
// Returns pointer value.
|
// Returns pointer value.
|
||||||
static Char *get(pointer_type p) { return p.base(); }
|
static char_type *get(pointer_type p) { return p.base(); }
|
||||||
#else
|
#else
|
||||||
typedef Char *pointer_type;
|
typedef char_type *pointer_type;
|
||||||
static Char *get(Char *p) { return p; }
|
static char_type *get(char_type *p) { return p; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Fills the padding around the content and returns the pointer to the
|
// Fills the padding around the content and returns the pointer to the
|
||||||
@ -2206,9 +2209,9 @@ class basic_writer {
|
|||||||
|
|
||||||
// Writes an unsigned decimal integer.
|
// Writes an unsigned decimal integer.
|
||||||
template <typename UInt>
|
template <typename UInt>
|
||||||
Char *write_unsigned_decimal(UInt value, unsigned prefix_size = 0) {
|
char_type *write_unsigned_decimal(UInt value, unsigned prefix_size = 0) {
|
||||||
unsigned num_digits = internal::count_digits(value);
|
unsigned num_digits = internal::count_digits(value);
|
||||||
Char *ptr = get(grow_buffer(prefix_size + num_digits));
|
char_type *ptr = get(grow_buffer(prefix_size + num_digits));
|
||||||
internal::format_decimal(ptr + prefix_size, value, num_digits);
|
internal::format_decimal(ptr + prefix_size, value, num_digits);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
@ -2248,30 +2251,30 @@ class basic_writer {
|
|||||||
void write_double(T value, const format_specs &spec);
|
void write_double(T value, const format_specs &spec);
|
||||||
|
|
||||||
// Writes a formatted string.
|
// Writes a formatted string.
|
||||||
template <typename StrChar>
|
template <typename Char>
|
||||||
pointer_type write_str(
|
pointer_type write_str(
|
||||||
const StrChar *s, std::size_t size, const align_spec &spec);
|
const Char *s, std::size_t size, const align_spec &spec);
|
||||||
|
|
||||||
template <typename StrChar>
|
template <typename Char>
|
||||||
void write_str(basic_string_view<StrChar> str, const format_specs &spec);
|
void write_str(basic_string_view<Char> str, const format_specs &spec);
|
||||||
|
|
||||||
// Appends floating-point length specifier to the format string.
|
// Appends floating-point length specifier to the format string.
|
||||||
// The second argument is only used for overload resolution.
|
// The second argument is only used for overload resolution.
|
||||||
void append_float_length(Char *&format_ptr, long double) {
|
void append_float_length(char_type *&format_ptr, long double) {
|
||||||
*format_ptr++ = 'L';
|
*format_ptr++ = 'L';
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void append_float_length(Char *&, T) {}
|
void append_float_length(char_type *&, T) {}
|
||||||
|
|
||||||
template <typename Char_>
|
template <typename Char>
|
||||||
friend class internal::arg_formatter_base;
|
friend class internal::arg_formatter_base;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
Constructs a ``basic_writer`` object.
|
Constructs a ``basic_writer`` object.
|
||||||
*/
|
*/
|
||||||
explicit basic_writer(basic_buffer<Char> &b) : buffer_(b) {}
|
explicit basic_writer(Buffer &b) : buffer_(b) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
@ -2289,13 +2292,13 @@ class basic_writer {
|
|||||||
Returns a pointer to the output buffer content. No terminating null
|
Returns a pointer to the output buffer content. No terminating null
|
||||||
character is appended.
|
character is appended.
|
||||||
*/
|
*/
|
||||||
const Char *data() const FMT_NOEXCEPT { return &buffer_[0]; }
|
const char_type *data() const FMT_NOEXCEPT { return &buffer_[0]; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns a pointer to the output buffer content with terminating null
|
Returns a pointer to the output buffer content with terminating null
|
||||||
character appended.
|
character appended.
|
||||||
*/
|
*/
|
||||||
const Char *c_str() const {
|
const char_type *c_str() const {
|
||||||
std::size_t size = buffer_.size();
|
std::size_t size = buffer_.size();
|
||||||
buffer_.reserve(size + 1);
|
buffer_.reserve(size + 1);
|
||||||
buffer_[size] = '\0';
|
buffer_[size] = '\0';
|
||||||
@ -2307,8 +2310,8 @@ class basic_writer {
|
|||||||
Returns the content of the output buffer as an `std::string`.
|
Returns the content of the output buffer as an `std::string`.
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
std::basic_string<Char> str() const {
|
std::basic_string<char_type> str() const {
|
||||||
return std::basic_string<Char>(&buffer_[0], buffer_.size());
|
return std::basic_string<char_type>(&buffer_[0], buffer_.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(int value) {
|
void write(int value) {
|
||||||
@ -2354,7 +2357,7 @@ class basic_writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void write(wchar_t value) {
|
void write(wchar_t value) {
|
||||||
internal::require_wchar<Char>();
|
internal::require_wchar<char_type>();
|
||||||
buffer_.push_back(value);
|
buffer_.push_back(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2369,29 +2372,29 @@ class basic_writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void write(basic_string_view<wchar_t> value) {
|
void write(basic_string_view<wchar_t> value) {
|
||||||
internal::require_wchar<Char>();
|
internal::require_wchar<char_type>();
|
||||||
const wchar_t *str = value.data();
|
const wchar_t *str = value.data();
|
||||||
buffer_.append(str, str + value.size());
|
buffer_.append(str, str + value.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... FormatSpecs>
|
template <typename... FormatSpecs>
|
||||||
void write(basic_string_view<Char> str, FormatSpecs... specs) {
|
void write(basic_string_view<char_type> str, FormatSpecs... specs) {
|
||||||
write_str(str, format_specs(specs...));
|
write_str(str, format_specs(specs...));
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() FMT_NOEXCEPT { buffer_.resize(0); }
|
void clear() FMT_NOEXCEPT { buffer_.resize(0); }
|
||||||
|
|
||||||
basic_buffer<Char> &buffer() FMT_NOEXCEPT { return buffer_; }
|
Buffer &buffer() FMT_NOEXCEPT { return buffer_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Buffer>
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
template <typename StrChar>
|
typename basic_writer<Buffer>::pointer_type basic_writer<Buffer>::write_str(
|
||||||
typename basic_writer<Char>::pointer_type basic_writer<Char>::write_str(
|
const Char *s, std::size_t size, const align_spec &spec) {
|
||||||
const StrChar *s, std::size_t size, const align_spec &spec) {
|
|
||||||
pointer_type out = pointer_type();
|
pointer_type out = pointer_type();
|
||||||
if (spec.width() > size) {
|
if (spec.width() > size) {
|
||||||
out = grow_buffer(spec.width());
|
out = grow_buffer(spec.width());
|
||||||
Char fill = internal::char_traits<Char>::cast(spec.fill());
|
char_type fill = internal::char_traits<char_type>::cast(spec.fill());
|
||||||
if (spec.align() == ALIGN_RIGHT) {
|
if (spec.align() == ALIGN_RIGHT) {
|
||||||
std::uninitialized_fill_n(out, spec.width() - size, fill);
|
std::uninitialized_fill_n(out, spec.width() - size, fill);
|
||||||
out += spec.width() - size;
|
out += spec.width() - size;
|
||||||
@ -2407,13 +2410,13 @@ typename basic_writer<Char>::pointer_type basic_writer<Char>::write_str(
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Buffer>
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
template <typename StrChar>
|
void basic_writer<Buffer>::write_str(
|
||||||
void basic_writer<Char>::write_str(
|
basic_string_view<Char> s, const format_specs &spec) {
|
||||||
basic_string_view<StrChar> s, const format_specs &spec) {
|
// Check if Char is convertible to char_type.
|
||||||
// Check if StrChar is convertible to Char.
|
internal::char_traits<char_type>::convert(Char());
|
||||||
internal::char_traits<Char>::convert(StrChar());
|
const Char *str_value = s.data();
|
||||||
const StrChar *str_value = s.data();
|
|
||||||
std::size_t str_size = s.size();
|
std::size_t str_size = s.size();
|
||||||
if (str_size == 0 && !str_value)
|
if (str_size == 0 && !str_value)
|
||||||
FMT_THROW(format_error("string pointer is null"));
|
FMT_THROW(format_error("string pointer is null"));
|
||||||
@ -2423,13 +2426,13 @@ void basic_writer<Char>::write_str(
|
|||||||
write_str(str_value, str_size, spec);
|
write_str(str_value, str_size, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Buffer>
|
||||||
typename basic_writer<Char>::pointer_type basic_writer<Char>::fill_padding(
|
typename basic_writer<Buffer>::pointer_type basic_writer<Buffer>::fill_padding(
|
||||||
pointer_type buffer, unsigned total_size,
|
pointer_type buffer, unsigned total_size,
|
||||||
std::size_t content_size, wchar_t fill) {
|
std::size_t content_size, wchar_t fill) {
|
||||||
std::size_t padding = total_size - content_size;
|
std::size_t padding = total_size - content_size;
|
||||||
std::size_t left_padding = padding / 2;
|
std::size_t left_padding = padding / 2;
|
||||||
Char fill_char = internal::char_traits<Char>::cast(fill);
|
char_type fill_char = internal::char_traits<char_type>::cast(fill);
|
||||||
std::uninitialized_fill_n(buffer, left_padding, fill_char);
|
std::uninitialized_fill_n(buffer, left_padding, fill_char);
|
||||||
buffer += left_padding;
|
buffer += left_padding;
|
||||||
pointer_type content = buffer;
|
pointer_type content = buffer;
|
||||||
@ -2438,15 +2441,15 @@ typename basic_writer<Char>::pointer_type basic_writer<Char>::fill_padding(
|
|||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Buffer>
|
||||||
template <typename Spec>
|
template <typename Spec>
|
||||||
typename basic_writer<Char>::pointer_type
|
typename basic_writer<Buffer>::pointer_type
|
||||||
basic_writer<Char>::prepare_int_buffer(
|
basic_writer<Buffer>::prepare_int_buffer(
|
||||||
unsigned num_digits, const Spec &spec,
|
unsigned num_digits, const Spec &spec,
|
||||||
const char *prefix, unsigned prefix_size) {
|
const char *prefix, unsigned prefix_size) {
|
||||||
unsigned width = spec.width();
|
unsigned width = spec.width();
|
||||||
alignment align = spec.align();
|
alignment align = spec.align();
|
||||||
Char fill = internal::char_traits<Char>::cast(spec.fill());
|
char_type fill = internal::char_traits<char_type>::cast(spec.fill());
|
||||||
if (spec.precision() > static_cast<int>(num_digits)) {
|
if (spec.precision() > static_cast<int>(num_digits)) {
|
||||||
// Octal prefix '0' is counted as a digit, so ignore it if precision
|
// Octal prefix '0' is counted as a digit, so ignore it if precision
|
||||||
// is specified.
|
// is specified.
|
||||||
@ -2502,18 +2505,18 @@ typename basic_writer<Char>::pointer_type
|
|||||||
return p - 1;
|
return p - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Buffer>
|
||||||
template <typename T, typename Spec>
|
template <typename T, typename Spec>
|
||||||
void basic_writer<Char>::write_int(T value, const Spec& spec) {
|
void basic_writer<Buffer>::write_int(T value, const Spec& spec) {
|
||||||
using unsigned_type = typename internal::int_traits<T>::main_type;
|
using unsigned_type = typename internal::int_traits<T>::main_type;
|
||||||
struct spec_handler {
|
struct spec_handler {
|
||||||
basic_writer<Char> &writer;
|
basic_writer<Buffer> &writer;
|
||||||
const Spec& spec;
|
const Spec& spec;
|
||||||
unsigned prefix_size = 0;
|
unsigned prefix_size = 0;
|
||||||
unsigned_type abs_value;
|
unsigned_type abs_value;
|
||||||
char prefix[4] = "";
|
char prefix[4] = "";
|
||||||
|
|
||||||
spec_handler(basic_writer<Char> &w, T val, const Spec& s)
|
spec_handler(basic_writer<Buffer> &w, T val, const Spec& s)
|
||||||
: writer(w), spec(s), abs_value(static_cast<unsigned_type>(val)) {
|
: writer(w), spec(s), abs_value(static_cast<unsigned_type>(val)) {
|
||||||
if (internal::is_negative(val)) {
|
if (internal::is_negative(val)) {
|
||||||
prefix[0] = '-';
|
prefix[0] = '-';
|
||||||
@ -2542,7 +2545,7 @@ void basic_writer<Char>::write_int(T value, const Spec& spec) {
|
|||||||
do {
|
do {
|
||||||
++num_digits;
|
++num_digits;
|
||||||
} while ((n >>= 4) != 0);
|
} while ((n >>= 4) != 0);
|
||||||
Char *p =
|
char_type *p =
|
||||||
get(writer.prepare_int_buffer(num_digits, spec, prefix, prefix_size));
|
get(writer.prepare_int_buffer(num_digits, spec, prefix, prefix_size));
|
||||||
n = abs_value;
|
n = abs_value;
|
||||||
const char *digits = spec.type() == 'x' ?
|
const char *digits = spec.type() == 'x' ?
|
||||||
@ -2562,11 +2565,11 @@ void basic_writer<Char>::write_int(T value, const Spec& spec) {
|
|||||||
do {
|
do {
|
||||||
++num_digits;
|
++num_digits;
|
||||||
} while ((n >>= 1) != 0);
|
} while ((n >>= 1) != 0);
|
||||||
Char *p =
|
char_type *p =
|
||||||
get(writer.prepare_int_buffer(num_digits, spec, prefix, prefix_size));
|
get(writer.prepare_int_buffer(num_digits, spec, prefix, prefix_size));
|
||||||
n = abs_value;
|
n = abs_value;
|
||||||
do {
|
do {
|
||||||
*p-- = static_cast<Char>('0' + (n & 1));
|
*p-- = static_cast<char_type>('0' + (n & 1));
|
||||||
} while ((n >>= 1) != 0);
|
} while ((n >>= 1) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2578,24 +2581,24 @@ void basic_writer<Char>::write_int(T value, const Spec& spec) {
|
|||||||
do {
|
do {
|
||||||
++num_digits;
|
++num_digits;
|
||||||
} while ((n >>= 3) != 0);
|
} while ((n >>= 3) != 0);
|
||||||
Char *p =
|
char_type *p =
|
||||||
get(writer.prepare_int_buffer(num_digits, spec, prefix, prefix_size));
|
get(writer.prepare_int_buffer(num_digits, spec, prefix, prefix_size));
|
||||||
n = abs_value;
|
n = abs_value;
|
||||||
do {
|
do {
|
||||||
*p-- = static_cast<Char>('0' + (n & 7));
|
*p-- = static_cast<char_type>('0' + (n & 7));
|
||||||
} while ((n >>= 3) != 0);
|
} while ((n >>= 3) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_num() {
|
void on_num() {
|
||||||
unsigned num_digits = internal::count_digits(abs_value);
|
unsigned num_digits = internal::count_digits(abs_value);
|
||||||
Char thousands_sep = internal::thousands_sep(writer.buffer_);
|
char_type thousands_sep = internal::thousands_sep(writer.buffer_);
|
||||||
fmt::basic_string_view<Char> sep(&thousands_sep, 1);
|
fmt::basic_string_view<char_type> sep(&thousands_sep, 1);
|
||||||
unsigned size = static_cast<unsigned>(
|
unsigned size = static_cast<unsigned>(
|
||||||
num_digits + sep.size() * ((num_digits - 1) / 3));
|
num_digits + sep.size() * ((num_digits - 1) / 3));
|
||||||
pointer_type p =
|
pointer_type p =
|
||||||
writer.prepare_int_buffer(size, spec, prefix, prefix_size) + 1;
|
writer.prepare_int_buffer(size, spec, prefix, prefix_size) + 1;
|
||||||
internal::format_decimal(get(p), abs_value, 0,
|
internal::format_decimal(get(p), abs_value, 0,
|
||||||
internal::add_thousands_sep<Char>(sep));
|
internal::add_thousands_sep<char_type>(sep));
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_error() {
|
void on_error() {
|
||||||
@ -2605,9 +2608,9 @@ void basic_writer<Char>::write_int(T value, const Spec& spec) {
|
|||||||
internal::handle_int_type_spec(spec.type(), spec_handler(*this, value, spec));
|
internal::handle_int_type_spec(spec.type(), spec_handler(*this, value, spec));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Buffer>
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void basic_writer<Char>::write_double(T value, const format_specs &spec) {
|
void basic_writer<Buffer>::write_double(T value, const format_specs &spec) {
|
||||||
// Check type.
|
// Check type.
|
||||||
struct spec_handler {
|
struct spec_handler {
|
||||||
char type;
|
char type;
|
||||||
@ -2700,8 +2703,8 @@ void basic_writer<Char>::write_double(T value, const format_specs &spec) {
|
|||||||
|
|
||||||
// Build format string.
|
// Build format string.
|
||||||
enum { MAX_FORMAT_SIZE = 10}; // longest format: %#-*.*Lg
|
enum { MAX_FORMAT_SIZE = 10}; // longest format: %#-*.*Lg
|
||||||
Char format[MAX_FORMAT_SIZE];
|
char_type format[MAX_FORMAT_SIZE];
|
||||||
Char *format_ptr = format;
|
char_type *format_ptr = format;
|
||||||
*format_ptr++ = '%';
|
*format_ptr++ = '%';
|
||||||
unsigned width_for_sprintf = width;
|
unsigned width_for_sprintf = width;
|
||||||
if (spec.flag(HASH_FLAG))
|
if (spec.flag(HASH_FLAG))
|
||||||
@ -2724,9 +2727,9 @@ void basic_writer<Char>::write_double(T value, const format_specs &spec) {
|
|||||||
*format_ptr = '\0';
|
*format_ptr = '\0';
|
||||||
|
|
||||||
// Format using snprintf.
|
// Format using snprintf.
|
||||||
Char fill = internal::char_traits<Char>::cast(spec.fill());
|
char_type fill = internal::char_traits<char_type>::cast(spec.fill());
|
||||||
unsigned n = 0;
|
unsigned n = 0;
|
||||||
Char *start = 0;
|
char_type *start = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
std::size_t buffer_size = buffer_.capacity() - offset;
|
std::size_t buffer_size = buffer_.capacity() - offset;
|
||||||
#if FMT_MSC_VER
|
#if FMT_MSC_VER
|
||||||
@ -2739,7 +2742,7 @@ void basic_writer<Char>::write_double(T value, const format_specs &spec) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
start = &buffer_[offset];
|
start = &buffer_[offset];
|
||||||
int result = internal::char_traits<Char>::format_float(
|
int result = internal::char_traits<char_type>::format_float(
|
||||||
start, buffer_size, format, width_for_sprintf, spec.precision(), value);
|
start, buffer_size, format, width_for_sprintf, spec.precision(), value);
|
||||||
if (result >= 0) {
|
if (result >= 0) {
|
||||||
n = internal::to_unsigned(result);
|
n = internal::to_unsigned(result);
|
||||||
@ -2765,7 +2768,7 @@ void basic_writer<Char>::write_double(T value, const format_specs &spec) {
|
|||||||
if (spec.align() == ALIGN_CENTER && spec.width() > n) {
|
if (spec.align() == ALIGN_CENTER && spec.width() > n) {
|
||||||
width = spec.width();
|
width = spec.width();
|
||||||
pointer_type p = grow_buffer(width);
|
pointer_type p = grow_buffer(width);
|
||||||
std::memmove(get(p) + (width - n) / 2, get(p), n * sizeof(Char));
|
std::memmove(get(p) + (width - n) / 2, get(p), n * sizeof(char_type));
|
||||||
fill_padding(p, spec.width(), n, fill);
|
fill_padding(p, spec.width(), n, fill);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ typedef basic_string_buffer<wchar_t> wstring_buffer;
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
std::string to_string(const T &value) {
|
std::string to_string(const T &value) {
|
||||||
string_buffer buf;
|
string_buffer buf;
|
||||||
basic_writer<char>(buf).write(value);
|
basic_writer<buffer>(buf).write(value);
|
||||||
std::string str;
|
std::string str;
|
||||||
buf.move_to(str);
|
buf.move_to(str);
|
||||||
return str;
|
return str;
|
||||||
|
@ -31,12 +31,9 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <type_traits>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#if FMT_USE_TYPE_TRAITS
|
|
||||||
# include <type_traits>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
// Test that the library compiles if None is defined to 0 as done by xlib.h.
|
// Test that the library compiles if None is defined to 0 as done by xlib.h.
|
||||||
@ -92,7 +89,7 @@ void std_format(long double value, std::wstring &result) {
|
|||||||
template <typename Char, typename T>
|
template <typename Char, typename T>
|
||||||
::testing::AssertionResult check_write(const T &value, const char *type) {
|
::testing::AssertionResult check_write(const T &value, const char *type) {
|
||||||
fmt::basic_memory_buffer<Char> buffer;
|
fmt::basic_memory_buffer<Char> buffer;
|
||||||
fmt::basic_writer<Char> writer(buffer);
|
fmt::basic_writer<fmt::basic_buffer<Char>> writer(buffer);
|
||||||
writer.write(value);
|
writer.write(value);
|
||||||
std::basic_string<Char> actual = writer.str();
|
std::basic_string<Char> actual = writer.str();
|
||||||
std::basic_string<Char> expected;
|
std::basic_string<Char> expected;
|
||||||
@ -144,19 +141,17 @@ TEST(StringViewTest, ConvertToString) {
|
|||||||
EXPECT_EQ("abc", s);
|
EXPECT_EQ("abc", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FMT_USE_TYPE_TRAITS
|
|
||||||
TEST(WriterTest, NotCopyConstructible) {
|
TEST(WriterTest, NotCopyConstructible) {
|
||||||
EXPECT_FALSE(std::is_copy_constructible<basic_writer<char> >::value);
|
EXPECT_FALSE(std::is_copy_constructible<basic_writer<fmt::buffer>>::value);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WriterTest, NotCopyAssignable) {
|
TEST(WriterTest, NotCopyAssignable) {
|
||||||
EXPECT_FALSE(std::is_copy_assignable<basic_writer<char> >::value);
|
EXPECT_FALSE(std::is_copy_assignable<basic_writer<fmt::buffer>>::value);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
TEST(WriterTest, Ctor) {
|
TEST(WriterTest, Ctor) {
|
||||||
memory_buffer buf;
|
memory_buffer buf;
|
||||||
fmt::basic_writer<char> w(buf);
|
fmt::basic_writer<fmt::buffer> w(buf);
|
||||||
EXPECT_EQ(0u, w.size());
|
EXPECT_EQ(0u, w.size());
|
||||||
EXPECT_STREQ("", w.c_str());
|
EXPECT_STREQ("", w.c_str());
|
||||||
EXPECT_EQ("", w.str());
|
EXPECT_EQ("", w.str());
|
||||||
@ -164,7 +159,7 @@ TEST(WriterTest, Ctor) {
|
|||||||
|
|
||||||
TEST(WriterTest, Data) {
|
TEST(WriterTest, Data) {
|
||||||
memory_buffer buf;
|
memory_buffer buf;
|
||||||
fmt::basic_writer<char> w(buf);
|
fmt::basic_writer<fmt::buffer> w(buf);
|
||||||
w.write(42);
|
w.write(42);
|
||||||
EXPECT_EQ("42", std::string(w.data(), w.size()));
|
EXPECT_EQ("42", std::string(w.data(), w.size()));
|
||||||
}
|
}
|
||||||
@ -217,14 +212,14 @@ TEST(WriterTest, WriteLongDouble) {
|
|||||||
|
|
||||||
TEST(WriterTest, WriteDoubleAtBufferBoundary) {
|
TEST(WriterTest, WriteDoubleAtBufferBoundary) {
|
||||||
memory_buffer buf;
|
memory_buffer buf;
|
||||||
fmt::basic_writer<char> writer(buf);
|
fmt::basic_writer<fmt::buffer> writer(buf);
|
||||||
for (int i = 0; i < 100; ++i)
|
for (int i = 0; i < 100; ++i)
|
||||||
writer.write(1.23456789);
|
writer.write(1.23456789);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WriterTest, WriteDoubleWithFilledBuffer) {
|
TEST(WriterTest, WriteDoubleWithFilledBuffer) {
|
||||||
memory_buffer buf;
|
memory_buffer buf;
|
||||||
fmt::basic_writer<char> writer(buf);
|
fmt::basic_writer<fmt::buffer> writer(buf);
|
||||||
// Fill the buffer.
|
// Fill the buffer.
|
||||||
for (int i = 0; i < fmt::internal::INLINE_BUFFER_SIZE; ++i)
|
for (int i = 0; i < fmt::internal::INLINE_BUFFER_SIZE; ++i)
|
||||||
writer.write(' ');
|
writer.write(' ');
|
||||||
@ -256,7 +251,7 @@ TEST(WriterTest, WriteWideString) {
|
|||||||
template <typename... T>
|
template <typename... T>
|
||||||
std::string write_str(T... args) {
|
std::string write_str(T... args) {
|
||||||
memory_buffer buf;
|
memory_buffer buf;
|
||||||
fmt::basic_writer<char> writer(buf);
|
fmt::basic_writer<fmt::buffer> writer(buf);
|
||||||
using namespace fmt;
|
using namespace fmt;
|
||||||
writer.write(args...);
|
writer.write(args...);
|
||||||
return writer.str();
|
return writer.str();
|
||||||
@ -265,7 +260,7 @@ std::string write_str(T... args) {
|
|||||||
template <typename... T>
|
template <typename... T>
|
||||||
std::wstring write_wstr(T... args) {
|
std::wstring write_wstr(T... args) {
|
||||||
wmemory_buffer buf;
|
wmemory_buffer buf;
|
||||||
fmt::basic_writer<wchar_t> writer(buf);
|
fmt::basic_writer<fmt::wbuffer> writer(buf);
|
||||||
using namespace fmt;
|
using namespace fmt;
|
||||||
writer.write(args...);
|
writer.write(args...);
|
||||||
return writer.str();
|
return writer.str();
|
||||||
@ -356,7 +351,7 @@ TEST(WriterTest, pad) {
|
|||||||
EXPECT_EQ(" 44", write_str(44ull, width=7));
|
EXPECT_EQ(" 44", write_str(44ull, width=7));
|
||||||
|
|
||||||
memory_buffer buf;
|
memory_buffer buf;
|
||||||
fmt::basic_writer<char> w(buf);
|
fmt::basic_writer<fmt::buffer> w(buf);
|
||||||
w.clear();
|
w.clear();
|
||||||
w.write(42, fmt::width=5, fmt::fill='0');
|
w.write(42, fmt::width=5, fmt::fill='0');
|
||||||
EXPECT_EQ("00042", w.str());
|
EXPECT_EQ("00042", w.str());
|
||||||
|
Loading…
Reference in New Issue
Block a user