Pass buffer instead of writer to format_value

This commit is contained in:
Victor Zverovich
2017-02-14 19:39:34 -05:00
parent 6e568f3a08
commit fefaf07b6f
13 changed files with 258 additions and 297 deletions
+29 -36
View File
@@ -106,7 +106,7 @@ inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
const char RESET_COLOR[] = "\x1b[0m";
typedef void (*FormatFunc)(writer &, int, StringRef);
typedef void (*FormatFunc)(buffer &, int, StringRef);
// Portable thread-safe version of strerror.
// Sets buffer to point to a string describing the error code.
@@ -176,7 +176,7 @@ int safe_strerror(
return StrError(error_code, buffer, buffer_size).run();
}
void format_error_code(writer &out, int error_code,
void format_error_code(buffer &out, int error_code,
StringRef message) FMT_NOEXCEPT {
// Report error code making sure that the output fits into
// INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
@@ -193,18 +193,19 @@ void format_error_code(writer &out, int error_code,
++error_code_size;
}
error_code_size += internal::count_digits(abs_value);
basic_writer<char> w(out);
if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size) {
out.write(message);
out.write(SEP);
w.write(message);
w.write(SEP);
}
out.write(ERROR_STR);
out.write(error_code);
w.write(ERROR_STR);
w.write(error_code);
assert(out.size() <= internal::INLINE_BUFFER_SIZE);
}
void report_error(FormatFunc func, int error_code,
StringRef message) FMT_NOEXCEPT {
MemoryWriter full_message;
internal::MemoryBuffer<char> full_message;
func(full_message, error_code, message);
// Use Writer::data instead of Writer::c_str to avoid potential memory
// allocation.
@@ -213,23 +214,13 @@ void report_error(FormatFunc func, int error_code,
}
} // namespace
namespace internal {
// This method is used to preserve binary compatibility with fmt 3.0.
// It can be removed in 4.0.
FMT_FUNC void format_system_error(
writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
fmt::format_system_error(out, error_code, message);
}
} // namespace internal
FMT_FUNC void SystemError::init(
int err_code, CStringRef format_str, args args) {
error_code_ = err_code;
MemoryWriter w;
format_system_error(w, err_code, vformat(format_str, args));
internal::MemoryBuffer<char> buf;
format_system_error(buf, err_code, vformat(format_str, args));
std::runtime_error &base = *this;
base = std::runtime_error(w.str());
base = std::runtime_error(to_string(buf));
}
template <typename T>
@@ -388,7 +379,7 @@ FMT_FUNC void internal::format_windows_error(
#endif // FMT_USE_WINDOWS_H
FMT_FUNC void format_system_error(
writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
buffer &out, int error_code, StringRef message) FMT_NOEXCEPT {
FMT_TRY {
internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> buffer;
buffer.resize(internal::INLINE_BUFFER_SIZE);
@@ -396,9 +387,10 @@ FMT_FUNC void format_system_error(
char *system_message = &buffer[0];
int result = safe_strerror(error_code, system_message, buffer.size());
if (result == 0) {
out.write(message);
out.write(": ");
out.write(system_message);
basic_writer<char> w(out);
w.write(message);
w.write(": ");
w.write(system_message);
return;
}
if (result != ERANGE)
@@ -410,7 +402,7 @@ FMT_FUNC void format_system_error(
}
template <typename Char>
void internal::FixedBuffer<Char>::grow(std::size_t) {
void FixedBuffer<Char>::grow(std::size_t) {
FMT_THROW(std::runtime_error("buffer overflow"));
}
@@ -429,9 +421,9 @@ FMT_FUNC void report_windows_error(
#endif
FMT_FUNC void vprint(std::FILE *f, CStringRef format_str, args args) {
MemoryWriter w;
w.vformat(format_str, args);
std::fwrite(w.data(), 1, w.size(), f);
internal::MemoryBuffer<char> buffer;
vformat_to(buffer, format_str, args);
std::fwrite(buffer.data(), 1, buffer.size(), f);
}
FMT_FUNC void vprint(CStringRef format_str, args args) {
@@ -451,10 +443,11 @@ void printf(basic_writer<Char> &w, BasicCStringRef<Char> format,
args args);
FMT_FUNC int vfprintf(std::FILE *f, CStringRef format, printf_args args) {
MemoryWriter w;
printf(w, format, args);
std::size_t size = w.size();
return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
internal::MemoryBuffer<char> buffer;
printf(buffer, format, args);
std::size_t size = buffer.size();
return std::fwrite(
buffer.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
}
#ifndef FMT_HEADER_ONLY
@@ -463,11 +456,11 @@ template struct internal::BasicData<void>;
// Explicit instantiations for char.
template void internal::FixedBuffer<char>::grow(std::size_t);
template void FixedBuffer<char>::grow(std::size_t);
template void internal::ArgMap<context>::init(const args &args);
template void printf_context<char>::format(writer &writer);
template void printf_context<char>::format(buffer &);
template int internal::CharTraits<char>::format_float(
char *buffer, std::size_t size, const char *format,
@@ -481,11 +474,11 @@ template int internal::CharTraits<char>::format_float(
template class basic_context<wchar_t>;
template void internal::FixedBuffer<wchar_t>::grow(std::size_t);
template void FixedBuffer<wchar_t>::grow(std::size_t);
template void internal::ArgMap<wcontext>::init(const wargs &args);
template void printf_context<wchar_t>::format(wwriter &writer);
template void printf_context<wchar_t>::format(wbuffer &);
template int internal::CharTraits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format,
+93 -104
View File
@@ -365,10 +365,13 @@ using std::move;
#endif
template <typename Char>
class basic_writer;
class basic_buffer;
typedef basic_writer<char> writer;
typedef basic_writer<wchar_t> wwriter;
typedef basic_buffer<char> buffer;
typedef basic_buffer<wchar_t> wbuffer;
template <typename Char>
class basic_writer;
template <typename Context>
class basic_arg;
@@ -616,6 +619,9 @@ class basic_buffer {
/** Returns the capacity of this buffer. */
std::size_t capacity() const { return capacity_; }
/** Returns a pointer to the buffer data. */
const T *data() const { return ptr_; }
/**
Resizes the buffer. If T is a POD type new elements may not be initialized.
*/
@@ -662,11 +668,17 @@ void basic_buffer<T>::append(const U *begin, const U *end) {
size_ = new_size;
}
template <typename Char>
inline std::basic_string<Char> to_string(const basic_buffer<Char>& buffer) {
return std::basic_string<Char>(buffer.data(), buffer.size());
}
namespace internal {
// A memory buffer for trivially copyable/constructible types with the first
// SIZE elements stored in the object itself.
template <typename T, std::size_t SIZE, typename Allocator = std::allocator<T> >
template <typename T, std::size_t SIZE = INLINE_BUFFER_SIZE,
typename Allocator = std::allocator<T> >
class MemoryBuffer : private Allocator, public basic_buffer<T> {
private:
T data_[SIZE];
@@ -741,17 +753,6 @@ void MemoryBuffer<T, SIZE, Allocator>::grow(std::size_t size) {
Allocator::deallocate(old_ptr, old_capacity);
}
// A fixed-size buffer.
template <typename Char>
class FixedBuffer : public fmt::basic_buffer<Char> {
public:
FixedBuffer(Char *array, std::size_t size)
: fmt::basic_buffer<Char>(array, size) {}
protected:
FMT_API void grow(std::size_t size);
};
template <typename Char>
class BasicCharTraits {
public:
@@ -988,7 +989,7 @@ class UTF16ToUTF8 {
FMT_API int convert(WStringRef s);
};
FMT_API void format_windows_error(fmt::writer &out, int error_code,
FMT_API void format_windows_error(fmt::buffer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT;
#endif
@@ -1085,7 +1086,7 @@ struct string_value {
template <typename Char>
struct CustomValue {
typedef void (*FormatFunc)(
basic_writer<Char> &writer, const void *arg, void *ctx);
basic_buffer<Char> &buffer, const void *arg, void *ctx);
const void *value;
FormatFunc format;
@@ -1207,8 +1208,8 @@ class value {
// Formats an argument of a custom type, such as a user-defined class.
template <typename T>
static void format_custom_arg(
basic_writer<Char> &writer, const void *arg, void *context) {
format_value(writer, *static_cast<const T*>(arg),
basic_buffer<Char> &buffer, const void *arg, void *context) {
format_value(buffer, *static_cast<const T*>(arg),
*static_cast<Context*>(context));
}
@@ -1464,7 +1465,7 @@ inline fmt::StringRef thousands_sep(...) { return ""; }
#endif
template <typename Formatter, typename T, typename Char>
void format_value(basic_writer<Char> &, const T &, Formatter &, const Char *) {
void format_value(basic_buffer<Char> &, const T &, Formatter &, const Char *) {
FMT_STATIC_ASSERT(False<T>::value,
"Cannot format argument. To enable the use of ostream "
"operator<< include fmt/ostream.h. Otherwise provide "
@@ -1858,7 +1859,7 @@ class ArgFormatterBase {
typedef basic_format_specs<Char> format_specs;
private:
basic_writer<Char> &writer_;
basic_writer<Char> writer_;
format_specs &spec_;
FMT_DISALLOW_COPY_AND_ASSIGN(ArgFormatterBase);
@@ -1901,8 +1902,8 @@ class ArgFormatterBase {
public:
typedef Char char_type;
ArgFormatterBase(basic_writer<Char> &w, format_specs &s)
: writer_(w), spec_(s) {}
ArgFormatterBase(basic_buffer<Char> &b, format_specs &s)
: writer_(b), spec_(s) {}
void operator()(monostate) {
FMT_ASSERT(false, "invalid argument type");
@@ -1973,12 +1974,6 @@ class ArgFormatterBase {
}
};
template <typename Char>
inline void write(basic_writer<Char> &w, const Char *start, const Char *end) {
if (start != end)
w.write(BasicStringRef<Char>(start, internal::to_unsigned(end - start)));
}
template <typename Char, typename Context>
class context_base {
private:
@@ -2047,20 +2042,20 @@ class ArgFormatter : public internal::ArgFormatterBase<Char> {
/**
\rst
Constructs an argument formatter object.
*writer* is a reference to the writer to be used for output,
*buffer* is a reference to the buffer to be used for output,
*ctx* is a reference to the formatting context, *spec* contains
format specifier information for standard argument types.
\endrst
*/
ArgFormatter(basic_writer<Char> &writer, basic_context<Char> &ctx,
ArgFormatter(basic_buffer<Char> &buffer, basic_context<Char> &ctx,
format_specs &spec)
: internal::ArgFormatterBase<Char>(writer, spec), ctx_(ctx) {}
: internal::ArgFormatterBase<Char>(buffer, spec), ctx_(ctx) {}
using internal::ArgFormatterBase<Char>::operator();
/** Formats an argument of a custom (user-defined) type. */
void operator()(internal::CustomValue<Char> c) {
c.format(this->writer(), c.value, &ctx_);
c.format(this->writer().buffer(), c.value, &ctx_);
}
};
@@ -2160,7 +2155,7 @@ class SystemError : public internal::RuntimeError {
may look like "Unknown error -1" and is platform-dependent.
\endrst
*/
FMT_API void format_system_error(fmt::writer &out, int error_code,
FMT_API void format_system_error(fmt::buffer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT;
namespace internal {
@@ -2298,13 +2293,12 @@ class basic_writer {
template <typename Char_>
friend class PrintfArgFormatter;
protected:
public:
/**
Constructs a ``basic_writer`` object.
*/
explicit basic_writer(basic_buffer<Char> &b) : buffer_(b) {}
public:
/**
\rst
Destroys a ``basic_writer`` object.
@@ -2343,38 +2337,6 @@ class basic_writer {
return std::basic_string<Char>(&buffer_[0], buffer_.size());
}
void vformat(BasicCStringRef<Char> format,
basic_args<basic_context<Char>> args);
/**
\rst
Writes formatted data.
*args* is an argument list representing arbitrary arguments.
**Example**::
MemoryWriter out;
out.format("Current point:\n");
out.format("({:+f}, {:+f})", -3.14, 3.14);
This will write the following output to the ``out`` object:
.. code-block:: none
Current point:
(-3.140000, +3.140000)
The output can be accessed using :func:`data()`, :func:`c_str` or
:func:`str` methods.
See also :ref:`syntax`.
\endrst
*/
template <typename... Args>
void format(BasicCStringRef<Char> format, const Args & ... args) {
vformat(format, make_args<basic_context<Char>>(args...));
}
void write(int value) {
write_decimal(value);
}
@@ -2881,6 +2843,23 @@ class BasicMemoryWriter : public basic_writer<Char> {
typedef BasicMemoryWriter<char> MemoryWriter;
typedef BasicMemoryWriter<wchar_t> WMemoryWriter;
// A fixed-size buffer.
template <typename Char>
class FixedBuffer : public fmt::basic_buffer<Char> {
public:
/**
\rst
Constructs a :class:`fmt::FixedBuffer` object for *array* of the
given size.
\endrst
*/
FixedBuffer(Char *array, std::size_t size)
: fmt::basic_buffer<Char>(array, size) {}
protected:
FMT_API void grow(std::size_t size);
};
/**
\rst
This class template provides operations for formatting and writing data
@@ -2904,15 +2883,9 @@ typedef BasicMemoryWriter<wchar_t> WMemoryWriter;
template <typename Char>
class BasicArrayWriter : public basic_writer<Char> {
private:
internal::FixedBuffer<Char> buffer_;
FixedBuffer<Char> buffer_;
public:
/**
\rst
Constructs a :class:`fmt::BasicArrayWriter` object for *array* of the
given size.
\endrst
*/
BasicArrayWriter(Char *array, std::size_t size)
: basic_writer<Char>(buffer_), buffer_(array, size) {}
@@ -3000,10 +2973,34 @@ inline void print_colored(Color c, CStringRef format_str,
vprint_colored(c, format_str, make_args(args...));
}
template <typename ArgFormatter, typename Char, typename Context>
void vformat_to(basic_buffer<Char> &buffer, BasicCStringRef<Char> format_str,
basic_args<Context> args);
inline void vformat_to(buffer &buf, CStringRef format_str, args args) {
vformat_to<ArgFormatter<char>>(buf, format_str, args);
}
inline void vformat_to(wbuffer &buf, WCStringRef format_str, wargs args) {
vformat_to<ArgFormatter<wchar_t>>(buf, format_str, args);
}
template <typename... Args>
inline void format_to(buffer &buf, CStringRef format_str,
const Args & ... args) {
vformat_to(buf, format_str, make_args(args...));
}
template <typename... Args>
inline void format_to(wbuffer &buf, WCStringRef format_str,
const Args & ... args) {
vformat_to(buf, format_str, make_args<wcontext>(args...));
}
inline std::string vformat(CStringRef format_str, args args) {
MemoryWriter w;
w.vformat(format_str, args);
return w.str();
internal::MemoryBuffer<char> buffer;
vformat_to(buffer, format_str, args);
return to_string(buffer);
}
/**
@@ -3021,15 +3018,14 @@ inline std::string format(CStringRef format_str, const Args & ... args) {
}
inline std::wstring vformat(WCStringRef format_str, wargs args) {
WMemoryWriter w;
w.vformat(format_str, args);
return w.str();
internal::MemoryBuffer<wchar_t> buffer;
vformat_to(buffer, format_str, args);
return to_string(buffer);
}
template <typename... Args>
inline std::wstring format(WCStringRef format_str, const Args & ... args) {
auto vargs = make_args<wcontext>(args...);
return vformat(format_str, vargs);
return vformat(format_str, make_args<wcontext>(args...));
}
FMT_API void vprint(std::FILE *f, CStringRef format_str, args args);
@@ -3273,15 +3269,15 @@ void check_sign(const Char *&s, const basic_arg<Context> &arg) {
template <typename Char, typename Context>
class CustomFormatter {
private:
basic_writer<Char> &writer_;
basic_buffer<Char> &buffer_;
Context &ctx_;
public:
CustomFormatter(basic_writer<Char> &writer, Context &ctx)
: writer_(writer), ctx_(ctx) {}
CustomFormatter(basic_buffer<Char> &buffer, Context &ctx)
: buffer_(buffer), ctx_(ctx) {}
bool operator()(internal::CustomValue<Char> custom) {
custom.format(writer_, custom.value, &ctx_);
custom.format(buffer_, custom.value, &ctx_);
return true;
}
@@ -3374,12 +3370,12 @@ inline typename basic_context<Char>::format_arg
// Formats a single argument.
template <typename ArgFormatter, typename Char, typename Context>
void do_format_arg(basic_writer<Char> &writer, basic_arg<Context> arg,
void do_format_arg(basic_buffer<Char> &buffer, basic_arg<Context> arg,
Context &ctx) {
const Char *&s = ctx.ptr();
basic_format_specs<Char> spec;
if (*s == ':') {
if (visit(internal::CustomFormatter<Char, Context>(writer, ctx), arg))
if (visit(internal::CustomFormatter<Char, Context>(buffer, ctx), arg))
return;
++s;
// Parse fill and alignment.
@@ -3495,13 +3491,13 @@ void do_format_arg(basic_writer<Char> &writer, basic_arg<Context> arg,
FMT_THROW(format_error("missing '}' in format string"));
// Format argument.
visit(ArgFormatter(writer, ctx, spec), arg);
visit(ArgFormatter(buffer, ctx, spec), arg);
}
/** Formats arguments and writes the output to the writer. */
/** Formats arguments and writes the output to the buffer. */
template <typename ArgFormatter, typename Char, typename Context>
void vwrite(basic_writer<Char> &writer, BasicCStringRef<Char> format_str,
basic_args<Context> args) {
void vformat_to(basic_buffer<Char> &buffer, BasicCStringRef<Char> format_str,
basic_args<Context> args) {
basic_context<Char> ctx(format_str.c_str(), args);
const Char *&s = ctx.ptr();
const Char *start = s;
@@ -3509,26 +3505,19 @@ void vwrite(basic_writer<Char> &writer, BasicCStringRef<Char> format_str,
Char c = *s++;
if (c != '{' && c != '}') continue;
if (*s == c) {
internal::write(writer, start, s);
buffer.append(start, s);
start = ++s;
continue;
}
if (c == '}')
FMT_THROW(format_error("unmatched '}' in format string"));
internal::write(writer, start, s - 1);
do_format_arg<ArgFormatter>(writer, ctx.parse_arg_id(), ctx);
buffer.append(start, s - 1);
do_format_arg<ArgFormatter>(buffer, ctx.parse_arg_id(), ctx);
if (*s != '}')
FMT_THROW(format_error(fmt::format("unknown format specifier")));
start = ++s;
}
internal::write(writer, start, s);
}
template <typename Char>
inline void basic_writer<Char>::vformat(
BasicCStringRef<Char> format,
basic_args<basic_context<Char>> args) {
vwrite<ArgFormatter<Char>>(*this, format, args);
buffer.append(start, s);
}
} // namespace fmt
+7 -8
View File
@@ -12,10 +12,10 @@
namespace fmt {
namespace internal {
FMT_FUNC void write(std::ostream &os, writer &w) {
const char *data = w.data();
FMT_FUNC void write(std::ostream &os, buffer &buf) {
const char *data = buf.data();
typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize;
UnsignedStreamSize size = w.size();
UnsignedStreamSize size = buf.size();
UnsignedStreamSize max_size =
internal::to_unsigned((std::numeric_limits<std::streamsize>::max)());
do {
@@ -27,10 +27,9 @@ FMT_FUNC void write(std::ostream &os, writer &w) {
}
}
FMT_FUNC void vprint(std::ostream &os, CStringRef format_str,
args args) {
MemoryWriter w;
w.vformat(format_str, args);
internal::write(os, w);
FMT_FUNC void vprint(std::ostream &os, CStringRef format_str, args args) {
internal::MemoryBuffer<char> buffer;
vformat_to(buffer, format_str, args);
internal::write(os, buffer);
}
} // namespace fmt
+8 -9
View File
@@ -67,28 +67,27 @@ struct ConvertToIntImpl<T, true> {
};
};
// Write the content of w to os.
void write(std::ostream &os, writer &w);
// Write the content of buf to os.
void write(std::ostream &os, buffer &buf);
template <typename Char, typename T>
BasicStringRef<Char> format_value(
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> &buffer,
const T &value) {
void format_value(basic_buffer<Char> &buffer, const T &value) {
internal::FormatBuf<Char> format_buf(buffer);
std::basic_ostream<Char> output(&format_buf);
output << value;
return BasicStringRef<Char>(&buffer[0], format_buf.size());
buffer.resize(format_buf.size());
}
} // namespace internal
// Formats a value.
template <typename Char, typename T>
void format_value(basic_writer<Char> &w, const T &value,
void format_value(basic_buffer<Char> &buf, const T &value,
basic_context<Char> &ctx) {
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
auto str = internal::format_value(buffer, value);
internal::format_value(buffer, value);
BasicStringRef<Char> str(buffer.data(), buffer.size());
do_format_arg< ArgFormatter<Char> >(
w, internal::make_arg< basic_context<Char> >(str), ctx);
buf, internal::make_arg< basic_context<Char> >(str), ctx);
}
FMT_API void vprint(std::ostream &os, CStringRef format_str, args args);
+25 -26
View File
@@ -225,12 +225,12 @@ class PrintfArgFormatter : public internal::ArgFormatterBase<Char> {
/**
\rst
Constructs an argument formatter object.
*writer* is a reference to the output writer and *spec* contains format
*buffer* is a reference to the output buffer and *spec* contains format
specifier information for standard argument types.
\endrst
*/
PrintfArgFormatter(basic_writer<Char> &writer, format_specs &spec)
: internal::ArgFormatterBase<Char>(writer, spec) {}
PrintfArgFormatter(basic_buffer<Char> &buffer, format_specs &spec)
: internal::ArgFormatterBase<Char>(buffer, spec) {}
using Base::operator();
@@ -289,7 +289,7 @@ class PrintfArgFormatter : public internal::ArgFormatterBase<Char> {
const Char format_str[] = {'}', '\0'};
auto args = basic_args<basic_context<Char>>();
basic_context<Char> ctx(format_str, args);
c.format(this->writer(), c.value, &ctx);
c.format(this->writer().buffer(), c.value, &ctx);
}
};
@@ -331,8 +331,8 @@ class printf_context :
basic_args<printf_context> args)
: Base(format_str.c_str(), args) {}
/** Formats stored arguments and writes the output to the writer. */
FMT_API void format(basic_writer<Char> &writer);
/** Formats stored arguments and writes the output to the buffer. */
FMT_API void format(basic_buffer<Char> &buffer);
};
template <typename Char, typename AF>
@@ -408,18 +408,18 @@ unsigned printf_context<Char, AF>::parse_header(
}
template <typename Char, typename AF>
void printf_context<Char, AF>::format(basic_writer<Char> &writer) {
void printf_context<Char, AF>::format(basic_buffer<Char> &buffer) {
const Char *start = this->ptr();
const Char *s = start;
while (*s) {
Char c = *s++;
if (c != '%') continue;
if (*s == c) {
internal::write(writer, start, s);
buffer.append(start, s);
start = ++s;
continue;
}
internal::write(writer, start, s - 1);
buffer.append(start, s - 1);
format_specs spec;
spec.align_ = ALIGN_RIGHT;
@@ -501,31 +501,30 @@ void printf_context<Char, AF>::format(basic_writer<Char> &writer) {
start = s;
// Format argument.
visit(AF(writer, spec), arg);
visit(AF(buffer, spec), arg);
}
internal::write(writer, start, s);
buffer.append(start, s);
}
// Formats a value.
template <typename Char, typename T>
void format_value(basic_writer<Char> &w, const T &value,
void format_value(basic_buffer<Char> &buf, const T &value,
printf_context<Char>& ctx) {
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
w.write(internal::format_value(buffer, value));
internal::format_value(buf, value);
}
template <typename Char>
void printf(basic_writer<Char> &w, BasicCStringRef<Char> format,
void printf(basic_buffer<Char> &buf, BasicCStringRef<Char> format,
basic_args<printf_context<Char>> args) {
printf_context<Char>(format, args).format(w);
printf_context<Char>(format, args).format(buf);
}
typedef basic_args<printf_context<char>> printf_args;
inline std::string vsprintf(CStringRef format, printf_args args) {
MemoryWriter w;
printf(w, format, args);
return w.str();
internal::MemoryBuffer<char> buffer;
printf(buffer, format, args);
return to_string(buffer);
}
/**
@@ -544,9 +543,9 @@ inline std::string sprintf(CStringRef format_str, const Args & ... args) {
inline std::wstring vsprintf(
WCStringRef format, basic_args<printf_context<wchar_t>> args) {
WMemoryWriter w;
printf(w, format, args);
return w.str();
internal::MemoryBuffer<wchar_t> buffer;
printf(buffer, format, args);
return to_string(buffer);
}
template <typename... Args>
@@ -591,10 +590,10 @@ inline int printf(CStringRef format_str, const Args & ... args) {
}
inline int vfprintf(std::ostream &os, CStringRef format_str, printf_args args) {
MemoryWriter w;
printf(w, format_str, args);
internal::write(os, w);
return static_cast<int>(w.size());
internal::MemoryBuffer<char> buffer;
printf(buffer, format_str, args);
internal::write(os, buffer);
return static_cast<int>(buffer.size());
}
/**
+6 -7
View File
@@ -15,7 +15,7 @@
namespace fmt {
void format_value(writer &w, const std::tm &tm, context &ctx) {
void format_value(buffer &buf, const std::tm &tm, context &ctx) {
const char *&s = ctx.ptr();
if (*s == ':')
++s;
@@ -27,13 +27,12 @@ void format_value(writer &w, const std::tm &tm, context &ctx) {
internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> format;
format.append(s, end + 1);
format[format.size() - 1] = '\0';
basic_buffer<char> &buffer = w.buffer();
std::size_t start = buffer.size();
std::size_t start = buf.size();
for (;;) {
std::size_t size = buffer.capacity() - start;
std::size_t count = std::strftime(&buffer[start], size, &format[0], &tm);
std::size_t size = buf.capacity() - start;
std::size_t count = std::strftime(&buf[start], size, &format[0], &tm);
if (count != 0) {
buffer.resize(start + count);
buf.resize(start + count);
break;
}
if (size >= format.size() * 256) {
@@ -44,7 +43,7 @@ void format_value(writer &w, const std::tm &tm, context &ctx) {
break;
}
const std::size_t MIN_GROWTH = 10;
buffer.reserve(buffer.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH));
buf.reserve(buf.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH));
}
s = end;
}