Commit ec4233f2 authored by gabime's avatar gabime

Fixed warnings conversion 'size_t' to 'int' on windows issue #119

parent 77acf29c
/* /*
Formatting library for C++ Formatting library for C++
Copyright (c) 2012 - 2015, Victor Zverovich Copyright (c) 2012 - 2015, Victor Zverovich
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this 1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer. list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, 2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution. and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "format.h" #include "format.h"
...@@ -133,9 +133,7 @@ struct IntChecker { ...@@ -133,9 +133,7 @@ struct IntChecker {
unsigned max = INT_MAX; unsigned max = INT_MAX;
return value <= max; return value <= max;
} }
static bool fits_in_int(bool) { static bool fits_in_int(bool) { return true; }
return true;
}
}; };
template <> template <>
...@@ -148,7 +146,7 @@ struct IntChecker<true> { ...@@ -148,7 +146,7 @@ struct IntChecker<true> {
const char RESET_COLOR[] = "\x1b[0m"; const char RESET_COLOR[] = "\x1b[0m";
typedef void(*FormatFunc)(fmt::Writer &, int, fmt::StringRef); typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
// Portable thread-safe version of strerror. // Portable thread-safe version of strerror.
// Sets buffer to point to a string describing the error code. // Sets buffer to point to a string describing the error code.
...@@ -160,7 +158,7 @@ typedef void(*FormatFunc)(fmt::Writer &, int, fmt::StringRef); ...@@ -160,7 +158,7 @@ typedef void(*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
// other - failure // other - failure
// Buffer should be at least of size 1. // Buffer should be at least of size 1.
int safe_strerror( int safe_strerror(
int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT{ int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer"); FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer");
class StrError { class StrError {
...@@ -219,7 +217,7 @@ int safe_strerror( ...@@ -219,7 +217,7 @@ int safe_strerror(
} }
void format_error_code(fmt::Writer &out, int error_code, void format_error_code(fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT{ fmt::StringRef message) FMT_NOEXCEPT {
// Report error code making sure that the output fits into // Report error code making sure that the output fits into
// INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
// bad_alloc. // bad_alloc.
...@@ -237,7 +235,7 @@ void format_error_code(fmt::Writer &out, int error_code, ...@@ -237,7 +235,7 @@ void format_error_code(fmt::Writer &out, int error_code,
} }
void report_error(FormatFunc func, void report_error(FormatFunc func,
int error_code, fmt::StringRef message) FMT_NOEXCEPT{ int error_code, fmt::StringRef message) FMT_NOEXCEPT {
fmt::MemoryWriter full_message; fmt::MemoryWriter full_message;
func(full_message, error_code, message); func(full_message, error_code, message);
// Use Writer::data instead of Writer::c_str to avoid potential memory // Use Writer::data instead of Writer::c_str to avoid potential memory
...@@ -248,11 +246,9 @@ void report_error(FormatFunc func, ...@@ -248,11 +246,9 @@ void report_error(FormatFunc func,
// IsZeroInt::visit(arg) returns true iff arg is a zero integer. // IsZeroInt::visit(arg) returns true iff arg is a zero integer.
class IsZeroInt : public fmt::internal::ArgVisitor<IsZeroInt, bool> { class IsZeroInt : public fmt::internal::ArgVisitor<IsZeroInt, bool> {
public: public:
template <typename T> template <typename T>
bool visit_any_int(T value) { bool visit_any_int(T value) { return value == 0; }
return value == 0;
}
}; };
// Parses an unsigned integer advancing s to the end of the parsed input. // Parses an unsigned integer advancing s to the end of the parsed input.
...@@ -302,12 +298,12 @@ void check_sign(const Char *&s, const Arg &arg) { ...@@ -302,12 +298,12 @@ void check_sign(const Char *&s, const Arg &arg) {
// Checks if an argument is a valid printf width specifier and sets // Checks if an argument is a valid printf width specifier and sets
// left alignment if it is negative. // left alignment if it is negative.
class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> { class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
private: private:
fmt::FormatSpec &spec_; fmt::FormatSpec &spec_;
FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler); FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
public: public:
explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {} explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
void report_unhandled_arg() { void report_unhandled_arg() {
...@@ -330,7 +326,7 @@ public: ...@@ -330,7 +326,7 @@ public:
class PrecisionHandler : class PrecisionHandler :
public fmt::internal::ArgVisitor<PrecisionHandler, int> { public fmt::internal::ArgVisitor<PrecisionHandler, int> {
public: public:
void report_unhandled_arg() { void report_unhandled_arg() {
FMT_THROW(fmt::FormatError("precision is not integer")); FMT_THROW(fmt::FormatError("precision is not integer"));
} }
...@@ -346,13 +342,13 @@ public: ...@@ -346,13 +342,13 @@ public:
// Converts an integer argument to an integral type T for printf. // Converts an integer argument to an integral type T for printf.
template <typename T> template <typename T>
class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> { class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
private: private:
fmt::internal::Arg &arg_; fmt::internal::Arg &arg_;
wchar_t type_; wchar_t type_;
FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter); FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
public: public:
ArgConverter(fmt::internal::Arg &arg, wchar_t type) ArgConverter(fmt::internal::Arg &arg, wchar_t type)
: arg_(arg), type_(type) {} : arg_(arg), type_(type) {}
...@@ -365,20 +361,17 @@ public: ...@@ -365,20 +361,17 @@ public:
if (is_signed) { if (is_signed) {
arg_.type = Arg::INT; arg_.type = Arg::INT;
arg_.int_value = static_cast<int>(static_cast<T>(value)); arg_.int_value = static_cast<int>(static_cast<T>(value));
} } else {
else {
arg_.type = Arg::UINT; arg_.type = Arg::UINT;
arg_.uint_value = static_cast<unsigned>( arg_.uint_value = static_cast<unsigned>(
static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value)); static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value));
} }
} } else {
else {
if (is_signed) { if (is_signed) {
arg_.type = Arg::LONG_LONG; arg_.type = Arg::LONG_LONG;
arg_.long_long_value = arg_.long_long_value =
static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value); static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
} } else {
else {
arg_.type = Arg::ULONG_LONG; arg_.type = Arg::ULONG_LONG;
arg_.ulong_long_value = arg_.ulong_long_value =
static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value); static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
...@@ -389,12 +382,12 @@ public: ...@@ -389,12 +382,12 @@ public:
// Converts an integer argument to char for printf. // Converts an integer argument to char for printf.
class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> { class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
private: private:
fmt::internal::Arg &arg_; fmt::internal::Arg &arg_;
FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter); FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
public: public:
explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {} explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
template <typename T> template <typename T>
...@@ -409,33 +402,25 @@ namespace internal { ...@@ -409,33 +402,25 @@ namespace internal {
template <typename Impl, typename Char> template <typename Impl, typename Char>
class BasicArgFormatter : public ArgVisitor<Impl, void> { class BasicArgFormatter : public ArgVisitor<Impl, void> {
private: private:
BasicWriter<Char> &writer_; BasicWriter<Char> &writer_;
FormatSpec &spec_; FormatSpec &spec_;
FMT_DISALLOW_COPY_AND_ASSIGN(BasicArgFormatter); FMT_DISALLOW_COPY_AND_ASSIGN(BasicArgFormatter);
protected: protected:
BasicWriter<Char> &writer() { BasicWriter<Char> &writer() { return writer_; }
return writer_; const FormatSpec &spec() const { return spec_; }
}
const FormatSpec &spec() const {
return spec_;
}
public: public:
BasicArgFormatter(BasicWriter<Char> &w, FormatSpec &s) BasicArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
: writer_(w), spec_(s) {} : writer_(w), spec_(s) {}
template <typename T> template <typename T>
void visit_any_int(T value) { void visit_any_int(T value) { writer_.write_int(value, spec_); }
writer_.write_int(value, spec_);
}
template <typename T> template <typename T>
void visit_any_double(T value) { void visit_any_double(T value) { writer_.write_double(value, spec_); }
writer_.write_double(value, spec_);
}
void visit_bool(bool value) { void visit_bool(bool value) {
if (spec_.type_) { if (spec_.type_) {
...@@ -463,15 +448,12 @@ public: ...@@ -463,15 +448,12 @@ public:
if (spec_.align_ == ALIGN_RIGHT) { if (spec_.align_ == ALIGN_RIGHT) {
std::fill_n(out, spec_.width_ - 1, fill); std::fill_n(out, spec_.width_ - 1, fill);
out += spec_.width_ - 1; out += spec_.width_ - 1;
} } else if (spec_.align_ == ALIGN_CENTER) {
else if (spec_.align_ == ALIGN_CENTER) {
out = writer_.fill_padding(out, spec_.width_, 1, fill); out = writer_.fill_padding(out, spec_.width_, 1, fill);
} } else {
else {
std::fill_n(out + 1, spec_.width_ - 1, fill); std::fill_n(out + 1, spec_.width_ - 1, fill);
} }
} } else {
else {
out = writer_.grow_buffer(1); out = writer_.grow_buffer(1);
} }
*out = internal::CharTraits<Char>::cast(value); *out = internal::CharTraits<Char>::cast(value);
...@@ -499,11 +481,11 @@ public: ...@@ -499,11 +481,11 @@ public:
// An argument formatter. // An argument formatter.
template <typename Char> template <typename Char>
class ArgFormatter : public BasicArgFormatter<ArgFormatter<Char>, Char> { class ArgFormatter : public BasicArgFormatter<ArgFormatter<Char>, Char> {
private: private:
BasicFormatter<Char> &formatter_; BasicFormatter<Char> &formatter_;
const Char *format_; const Char *format_;
public: public:
ArgFormatter(BasicFormatter<Char> &f, FormatSpec &s, const Char *fmt) ArgFormatter(BasicFormatter<Char> &f, FormatSpec &s, const Char *fmt)
: BasicArgFormatter<ArgFormatter<Char>, Char>(f.writer(), s), : BasicArgFormatter<ArgFormatter<Char>, Char>(f.writer(), s),
formatter_(f), format_(fmt) {} formatter_(f), format_(fmt) {}
...@@ -516,7 +498,7 @@ public: ...@@ -516,7 +498,7 @@ public:
template <typename Char> template <typename Char>
class PrintfArgFormatter : class PrintfArgFormatter :
public BasicArgFormatter<PrintfArgFormatter<Char>, Char> { public BasicArgFormatter<PrintfArgFormatter<Char>, Char> {
public: public:
PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s) PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
: BasicArgFormatter<PrintfArgFormatter<Char>, Char>(w, s) {} : BasicArgFormatter<PrintfArgFormatter<Char>, Char>(w, s) {}
...@@ -533,12 +515,10 @@ public: ...@@ -533,12 +515,10 @@ public:
if (fmt_spec.align_ != ALIGN_LEFT) { if (fmt_spec.align_ != ALIGN_LEFT) {
std::fill_n(out, fmt_spec.width_ - 1, fill); std::fill_n(out, fmt_spec.width_ - 1, fill);
out += fmt_spec.width_ - 1; out += fmt_spec.width_ - 1;
} } else {
else {
std::fill_n(out + 1, fmt_spec.width_ - 1, fill); std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
} }
} } else {
else {
out = w.grow_buffer(1); out = w.grow_buffer(1);
} }
*out = static_cast<Char>(value); *out = static_cast<Char>(value);
...@@ -632,14 +612,17 @@ FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) { ...@@ -632,14 +612,17 @@ FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
#if FMT_USE_WINDOWS_H #if FMT_USE_WINDOWS_H
FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) { FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
int length = MultiByteToWideChar(
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s.size(), 0, 0);
static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16"; static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
if (s.size() > INT_MAX)
FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
int s_size = static_cast<int>(s.size());
int length = MultiByteToWideChar(
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
if (length == 0) if (length == 0)
FMT_THROW(WindowsError(GetLastError(), ERROR_MSG)); FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
buffer_.resize(length + 1); buffer_.resize(length + 1);
length = MultiByteToWideChar( length = MultiByteToWideChar(
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s.size(), &buffer_[0], length); CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
if (length == 0) if (length == 0)
FMT_THROW(WindowsError(GetLastError(), ERROR_MSG)); FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
buffer_[length] = 0; buffer_[length] = 0;
...@@ -653,12 +636,15 @@ FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) { ...@@ -653,12 +636,15 @@ FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
} }
FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) { FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s.size(), 0, 0, 0, 0); if (s.size() > INT_MAX)
return ERROR_INVALID_PARAMETER;
int s_size = static_cast<int>(s.size());
int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
if (length == 0) if (length == 0)
return GetLastError(); return GetLastError();
buffer_.resize(length + 1); buffer_.resize(length + 1);
length = WideCharToMultiByte( length = WideCharToMultiByte(
CP_UTF8, 0, s.data(), s.size(), &buffer_[0], length, 0, 0); CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
if (length == 0) if (length == 0)
return GetLastError(); return GetLastError();
buffer_[length] = 0; buffer_[length] = 0;
...@@ -676,22 +662,18 @@ FMT_FUNC void fmt::WindowsError::init( ...@@ -676,22 +662,18 @@ FMT_FUNC void fmt::WindowsError::init(
FMT_FUNC void fmt::internal::format_windows_error( FMT_FUNC void fmt::internal::format_windows_error(
fmt::Writer &out, int error_code, fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT{ fmt::StringRef message) FMT_NOEXCEPT {
class String { class String {
private: private:
LPWSTR str_; LPWSTR str_;
public: public:
String() : str_() {} String() : str_() {}
~String() { ~String() { LocalFree(str_); }
LocalFree(str_); LPWSTR *ptr() { return &str_; }
}
LPWSTR *ptr() {
return &str_;
}
LPCWSTR c_str() const { return str_; } LPCWSTR c_str() const { return str_; }
}; };
FMT_TRY{ FMT_TRY {
String system_message; String system_message;
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
...@@ -711,8 +693,8 @@ FMT_FUNC void fmt::internal::format_windows_error( ...@@ -711,8 +693,8 @@ FMT_FUNC void fmt::internal::format_windows_error(
FMT_FUNC void fmt::internal::format_system_error( FMT_FUNC void fmt::internal::format_system_error(
fmt::Writer &out, int error_code, fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT{ fmt::StringRef message) FMT_NOEXCEPT {
FMT_TRY{ FMT_TRY {
MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer; MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer;
buffer.resize(INLINE_BUFFER_SIZE); buffer.resize(INLINE_BUFFER_SIZE);
for (;;) { for (;;) {
...@@ -749,8 +731,7 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) { ...@@ -749,8 +731,7 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
map_.insert(Pair(named_arg->name, *named_arg)); map_.insert(Pair(named_arg->name, *named_arg));
break; break;
default: default:
/*nothing*/ /*nothing*/;
;
} }
} }
return; return;
...@@ -771,8 +752,7 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) { ...@@ -771,8 +752,7 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
map_.insert(Pair(named_arg->name, *named_arg)); map_.insert(Pair(named_arg->name, *named_arg));
break; break;
default: default:
/*nothing*/ /*nothing*/;
;
} }
} }
} }
...@@ -854,8 +834,7 @@ FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg( ...@@ -854,8 +834,7 @@ FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
case Arg::NAMED_ARG: case Arg::NAMED_ARG:
arg = *static_cast<const internal::Arg*>(arg.pointer); arg = *static_cast<const internal::Arg*>(arg.pointer);
default: default:
/*nothing*/ /*nothing*/;
;
} }
return arg; return arg;
} }
...@@ -933,8 +912,7 @@ unsigned fmt::internal::PrintfFormatter<Char>::parse_header( ...@@ -933,8 +912,7 @@ unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
if (*s == '$') { // value is an argument index if (*s == '$') { // value is an argument index
++s; ++s;
arg_index = value; arg_index = value;
} } else {
else {
if (c == '0') if (c == '0')
spec.fill_ = '0'; spec.fill_ = '0';
if (value != 0) { if (value != 0) {
...@@ -949,8 +927,7 @@ unsigned fmt::internal::PrintfFormatter<Char>::parse_header( ...@@ -949,8 +927,7 @@ unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
// Parse width. // Parse width.
if (*s >= '0' && *s <= '9') { if (*s >= '0' && *s <= '9') {
spec.width_ = parse_nonnegative_int(s); spec.width_ = parse_nonnegative_int(s);
} } else if (*s == '*') {
else if (*s == '*') {
++s; ++s;
spec.width_ = WidthHandler(spec).visit(get_arg(s)); spec.width_ = WidthHandler(spec).visit(get_arg(s));
} }
...@@ -983,8 +960,7 @@ void fmt::internal::PrintfFormatter<Char>::format( ...@@ -983,8 +960,7 @@ void fmt::internal::PrintfFormatter<Char>::format(
++s; ++s;
if ('0' <= *s && *s <= '9') { if ('0' <= *s && *s <= '9') {
spec.precision_ = parse_nonnegative_int(s); spec.precision_ = parse_nonnegative_int(s);
} } else if (*s == '*') {
else if (*s == '*') {
++s; ++s;
spec.precision_ = PrecisionHandler().visit(get_arg(s)); spec.precision_ = PrecisionHandler().visit(get_arg(s));
} }
...@@ -1039,8 +1015,7 @@ void fmt::internal::PrintfFormatter<Char>::format( ...@@ -1039,8 +1015,7 @@ void fmt::internal::PrintfFormatter<Char>::format(
if (arg.type <= Arg::LAST_INTEGER_TYPE) { if (arg.type <= Arg::LAST_INTEGER_TYPE) {
// Normalize type. // Normalize type.
switch (spec.type_) { switch (spec.type_) {
case 'i': case 'i': case 'u':
case 'u':
spec.type_ = 'd'; spec.type_ = 'd';
break; break;
case 'c': case 'c':
...@@ -1095,8 +1070,7 @@ const Char *fmt::BasicFormatter<Char>::format( ...@@ -1095,8 +1070,7 @@ const Char *fmt::BasicFormatter<Char>::format(
FMT_THROW(FormatError("invalid fill character '{'")); FMT_THROW(FormatError("invalid fill character '{'"));
s += 2; s += 2;
spec.fill_ = c; spec.fill_ = c;
} } else ++s;
else ++s;
if (spec.align_ == ALIGN_NUMERIC) if (spec.align_ == ALIGN_NUMERIC)
require_numeric_argument(arg, '='); require_numeric_argument(arg, '=');
break; break;
...@@ -1137,8 +1111,7 @@ const Char *fmt::BasicFormatter<Char>::format( ...@@ -1137,8 +1111,7 @@ const Char *fmt::BasicFormatter<Char>::format(
// Parse width. // Parse width.
if ('0' <= *s && *s <= '9') { if ('0' <= *s && *s <= '9') {
spec.width_ = parse_nonnegative_int(s); spec.width_ = parse_nonnegative_int(s);
} } else if (*s == '{') {
else if (*s == '{') {
++s; ++s;
Arg width_arg = is_name_start(*s) ? Arg width_arg = is_name_start(*s) ?
parse_arg_name(s) : parse_arg_index(s); parse_arg_name(s) : parse_arg_index(s);
...@@ -1176,8 +1149,7 @@ const Char *fmt::BasicFormatter<Char>::format( ...@@ -1176,8 +1149,7 @@ const Char *fmt::BasicFormatter<Char>::format(
spec.precision_ = 0; spec.precision_ = 0;
if ('0' <= *s && *s <= '9') { if ('0' <= *s && *s <= '9') {
spec.precision_ = parse_nonnegative_int(s); spec.precision_ = parse_nonnegative_int(s);
} } else if (*s == '{') {
else if (*s == '{') {
++s; ++s;
Arg precision_arg = Arg precision_arg =
is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s); is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s);
...@@ -1207,8 +1179,7 @@ const Char *fmt::BasicFormatter<Char>::format( ...@@ -1207,8 +1179,7 @@ const Char *fmt::BasicFormatter<Char>::format(
if (value > INT_MAX) if (value > INT_MAX)
FMT_THROW(FormatError("number is too big")); FMT_THROW(FormatError("number is too big"));
spec.precision_ = static_cast<int>(value); spec.precision_ = static_cast<int>(value);
} } else {
else {
FMT_THROW(FormatError("missing precision specifier")); FMT_THROW(FormatError("missing precision specifier"));
} }
if (arg.type <= Arg::LAST_INTEGER_TYPE || arg.type == Arg::POINTER) { if (arg.type <= Arg::LAST_INTEGER_TYPE || arg.type == Arg::POINTER) {
...@@ -1253,13 +1224,13 @@ void fmt::BasicFormatter<Char>::format(BasicCStringRef<Char> format_str) { ...@@ -1253,13 +1224,13 @@ void fmt::BasicFormatter<Char>::format(BasicCStringRef<Char> format_str) {
} }
FMT_FUNC void fmt::report_system_error( FMT_FUNC void fmt::report_system_error(
int error_code, fmt::StringRef message) FMT_NOEXCEPT{ int error_code, fmt::StringRef message) FMT_NOEXCEPT {
report_error(internal::format_system_error, error_code, message); report_error(internal::format_system_error, error_code, message);
} }
#if FMT_USE_WINDOWS_H #if FMT_USE_WINDOWS_H
FMT_FUNC void fmt::report_windows_error( FMT_FUNC void fmt::report_windows_error(
int error_code, fmt::StringRef message) FMT_NOEXCEPT{ int error_code, fmt::StringRef message) FMT_NOEXCEPT {
report_error(internal::format_windows_error, error_code, message); report_error(internal::format_windows_error, error_code, message);
} }
#endif #endif
......
/* /*
Formatting library for C++ Formatting library for C++
Copyright (c) 2012 - 2015, Victor Zverovich Copyright (c) 2012 - 2015, Victor Zverovich
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this 1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer. list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, 2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution. and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef FMT_FORMAT_H_ #ifndef FMT_FORMAT_H_
#define FMT_FORMAT_H_ #define FMT_FORMAT_H_
...@@ -206,36 +206,36 @@ template <typename Char, typename T> ...@@ -206,36 +206,36 @@ template <typename Char, typename T>
void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value); void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value);
/** /**
\rst \rst
A string reference. It can be constructed from a C string or ``std::string``. A string reference. It can be constructed from a C string or ``std::string``.
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 |
+============+=========================+ +============+=========================+
| StringRef | BasicStringRef<char> | | StringRef | BasicStringRef<char> |
+------------+-------------------------+ +------------+-------------------------+
| WStringRef | BasicStringRef<wchar_t> | | WStringRef | BasicStringRef<wchar_t> |
+------------+-------------------------+ +------------+-------------------------+
This class is most useful as a parameter type to allow passing This class is most useful as a parameter type to allow passing
different types of strings to a function, for example:: different types of strings to a function, for example::
template <typename... Args> template <typename... Args>
std::string format(StringRef format_str, const Args & ... args); std::string format(StringRef format_str, const Args & ... args);
format("{}", 42); format("{}", 42);
format(std::string("{}"), 42); format(std::string("{}"), 42);
\endrst \endrst
*/ */
template <typename Char> template <typename Char>
class BasicStringRef { class BasicStringRef {
private: private:
const Char *data_; const Char *data_;
std::size_t size_; std::size_t size_;
public: public:
/** Constructs a string reference object from a C string and a size. */ /** Constructs a string reference object from a C string and a size. */
BasicStringRef(const Char *s, std::size_t size) : data_(s), size_(size) {} BasicStringRef(const Char *s, std::size_t size) : data_(s), size_(size) {}
...@@ -266,14 +266,10 @@ public: ...@@ -266,14 +266,10 @@ public:
} }
/** Returns the pointer to a C string. */ /** Returns the pointer to a C string. */
const Char *data() const { const Char *data() const { return data_; }
return data_;
}
/** Returns the string size. */ /** Returns the string size. */
std::size_t size() const { std::size_t size() const { return size_; }
return size_;
}
friend bool operator==(BasicStringRef lhs, BasicStringRef rhs) { friend bool operator==(BasicStringRef lhs, BasicStringRef rhs) {
return lhs.data_ == rhs.data_; return lhs.data_ == rhs.data_;
...@@ -292,36 +288,36 @@ typedef BasicStringRef<wchar_t> WStringRef; ...@@ -292,36 +288,36 @@ typedef BasicStringRef<wchar_t> WStringRef;
/** /**
\rst \rst
A reference to a null terminated string. It can be constructed from a C A reference to a null terminated string. It can be constructed from a C
string or ``std::string``. string or ``std::string``.
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 |
+=============+==========================+ +=============+==========================+
| CStringRef | BasicCStringRef<char> | | CStringRef | BasicCStringRef<char> |
+-------------+--------------------------+ +-------------+--------------------------+
| WCStringRef | BasicCStringRef<wchar_t> | | WCStringRef | BasicCStringRef<wchar_t> |
+-------------+--------------------------+ +-------------+--------------------------+
This class is most useful as a parameter type to allow passing This class is most useful as a parameter type to allow passing
different types of strings to a function, for example:: different types of strings to a function, for example::
template <typename... Args> template <typename... Args>
std::string format(CStringRef format_str, const Args & ... args); std::string format(CStringRef format_str, const Args & ... args);
format("{}", 42); format("{}", 42);
format(std::string("{}"), 42); format(std::string("{}"), 42);
\endrst \endrst
*/ */
template <typename Char> template <typename Char>
class BasicCStringRef { class BasicCStringRef {
private: private:
const Char *data_; const Char *data_;
public: public:
/** Constructs a string reference object from a C string. */ /** Constructs a string reference object from a C string. */
BasicCStringRef(const Char *s) : data_(s) {} BasicCStringRef(const Char *s) : data_(s) {}
...@@ -333,19 +329,17 @@ public: ...@@ -333,19 +329,17 @@ public:
BasicCStringRef(const std::basic_string<Char> &s) : data_(s.c_str()) {} BasicCStringRef(const std::basic_string<Char> &s) : data_(s.c_str()) {}
/** Returns the pointer to a C string. */ /** Returns the pointer to a C string. */
const Char *c_str() const { const Char *c_str() const { return data_; }
return data_;
}
}; };
typedef BasicCStringRef<char> CStringRef; typedef BasicCStringRef<char> CStringRef;
typedef BasicCStringRef<wchar_t> WCStringRef; typedef BasicCStringRef<wchar_t> WCStringRef;
/** /**
A formatting error such as invalid format string. A formatting error such as invalid format string.
*/ */
class FormatError : public std::runtime_error { class FormatError : public std::runtime_error {
public: public:
explicit FormatError(CStringRef message) explicit FormatError(CStringRef message)
: std::runtime_error(message.c_str()) {} : std::runtime_error(message.c_str()) {}
}; };
...@@ -363,23 +357,21 @@ inline stdext::checked_array_iterator<T*> make_ptr(T *ptr, std::size_t size) { ...@@ -363,23 +357,21 @@ inline stdext::checked_array_iterator<T*> make_ptr(T *ptr, std::size_t size) {
} }
#else #else
template <typename T> template <typename T>
inline T *make_ptr(T *ptr, std::size_t) { inline T *make_ptr(T *ptr, std::size_t) { return ptr; }
return ptr;
}
#endif #endif
} // namespace internal } // namespace internal
/** /**
\rst \rst
A buffer supporting a subset of ``std::vector``'s operations. A buffer supporting a subset of ``std::vector``'s operations.
\endrst \endrst
*/ */
template <typename T> template <typename T>
class Buffer { class Buffer {
private: private:
FMT_DISALLOW_COPY_AND_ASSIGN(Buffer); FMT_DISALLOW_COPY_AND_ASSIGN(Buffer);
protected: protected:
T *ptr_; T *ptr_;
std::size_t size_; std::size_t size_;
std::size_t capacity_; std::size_t capacity_;
...@@ -395,18 +387,14 @@ protected: ...@@ -395,18 +387,14 @@ protected:
*/ */
virtual void grow(std::size_t size) = 0; virtual void grow(std::size_t size) = 0;
public: public:
virtual ~Buffer() {} virtual ~Buffer() {}
/** Returns the size of this buffer. */ /** Returns the size of this buffer. */
std::size_t size() const { std::size_t size() const { return size_; }
return size_;
}
/** Returns the capacity of this buffer. */ /** Returns the capacity of this buffer. */
std::size_t capacity() const { std::size_t capacity() const { return capacity_; }
return capacity_;
}
/** /**
Resizes the buffer. If T is a POD type new elements may not be initialized. Resizes the buffer. If T is a POD type new elements may not be initialized.
...@@ -427,7 +415,7 @@ public: ...@@ -427,7 +415,7 @@ public:
grow(capacity); grow(capacity);
} }
void clear() FMT_NOEXCEPT{ size_ = 0; } void clear() FMT_NOEXCEPT { size_ = 0; }
void push_back(const T &value) { void push_back(const T &value) {
if (size_ == capacity_) if (size_ == capacity_)
...@@ -439,12 +427,8 @@ public: ...@@ -439,12 +427,8 @@ public:
template <typename U> template <typename U>
void append(const U *begin, const U *end); void append(const U *begin, const U *end);
T &operator[](std::size_t index) { T &operator[](std::size_t index) { return ptr_[index]; }
return ptr_[index]; const T &operator[](std::size_t index) const { return ptr_[index]; }
}
const T &operator[](std::size_t index) const {
return ptr_[index];
}
}; };
template <typename T> template <typename T>
...@@ -463,7 +447,7 @@ namespace internal { ...@@ -463,7 +447,7 @@ namespace internal {
// the object itself. // the object itself.
template <typename T, std::size_t SIZE, typename Allocator = std::allocator<T> > template <typename T, std::size_t SIZE, typename Allocator = std::allocator<T> >
class MemoryBuffer : private Allocator, public Buffer<T> { class MemoryBuffer : private Allocator, public Buffer<T> {
private: private:
T data_[SIZE]; T data_[SIZE];
// Free memory allocated by the buffer. // Free memory allocated by the buffer.
...@@ -471,18 +455,16 @@ private: ...@@ -471,18 +455,16 @@ private:
if (this->ptr_ != data_) this->deallocate(this->ptr_, this->capacity_); if (this->ptr_ != data_) this->deallocate(this->ptr_, this->capacity_);
} }
protected: protected:
void grow(std::size_t size); void grow(std::size_t size);
public: public:
explicit MemoryBuffer(const Allocator &alloc = Allocator()) explicit MemoryBuffer(const Allocator &alloc = Allocator())
: Allocator(alloc), Buffer<T>(data_, SIZE) {} : Allocator(alloc), Buffer<T>(data_, SIZE) {}
~MemoryBuffer() { ~MemoryBuffer() { free(); }
free();
}
#if FMT_USE_RVALUE_REFERENCES #if FMT_USE_RVALUE_REFERENCES
private: private:
// Move data from other to this buffer. // Move data from other to this buffer.
void move(MemoryBuffer &other) { void move(MemoryBuffer &other) {
Allocator &this_alloc = *this, &other_alloc = other; Allocator &this_alloc = *this, &other_alloc = other;
...@@ -493,8 +475,7 @@ private: ...@@ -493,8 +475,7 @@ private:
this->ptr_ = data_; this->ptr_ = data_;
std::copy(other.data_, std::copy(other.data_,
other.data_ + this->size_, make_ptr(data_, this->capacity_)); other.data_ + this->size_, make_ptr(data_, this->capacity_));
} } else {
else {
this->ptr_ = other.ptr_; this->ptr_ = other.ptr_;
// Set pointer to the inline array so that delete is not called // Set pointer to the inline array so that delete is not called
// when freeing. // when freeing.
...@@ -502,7 +483,7 @@ private: ...@@ -502,7 +483,7 @@ private:
} }
} }
public: public:
MemoryBuffer(MemoryBuffer &&other) { MemoryBuffer(MemoryBuffer &&other) {
move(other); move(other);
} }
...@@ -516,9 +497,7 @@ public: ...@@ -516,9 +497,7 @@ public:
#endif #endif
// Returns a copy of the allocator associated with this buffer. // Returns a copy of the allocator associated with this buffer.
Allocator get_allocator() const { Allocator get_allocator() const { return *this; }
return *this;
}
}; };
template <typename T, std::size_t SIZE, typename Allocator> template <typename T, std::size_t SIZE, typename Allocator>
...@@ -543,10 +522,10 @@ void MemoryBuffer<T, SIZE, Allocator>::grow(std::size_t size) { ...@@ -543,10 +522,10 @@ void MemoryBuffer<T, SIZE, Allocator>::grow(std::size_t size) {
// A fixed-size buffer. // A fixed-size buffer.
template <typename Char> template <typename Char>
class FixedBuffer : public fmt::Buffer<Char> { class FixedBuffer : public fmt::Buffer<Char> {
public: public:
FixedBuffer(Char *array, std::size_t size) : fmt::Buffer<Char>(array, size) {} FixedBuffer(Char *array, std::size_t size) : fmt::Buffer<Char>(array, size) {}
protected: protected:
void grow(std::size_t size); void grow(std::size_t size);
}; };
...@@ -564,19 +543,11 @@ inline int getsign(double x) { ...@@ -564,19 +543,11 @@ inline int getsign(double x) {
// Portable version of isinf. // Portable version of isinf.
# ifdef isinf # ifdef isinf
inline int isinfinity(double x) { inline int isinfinity(double x) { return isinf(x); }
return isinf(x); inline int isinfinity(long double x) { return isinf(x); }
}
inline int isinfinity(long double x) {
return isinf(x);
}
# else # else
inline int isinfinity(double x) { inline int isinfinity(double x) { return std::isinf(x); }
return std::isinf(x); inline int isinfinity(long double x) { return std::isinf(x); }
}
inline int isinfinity(long double x) {
return std::isinf(x);
}
# endif # endif
#else #else
inline int getsign(double value) { inline int getsign(double value) {
...@@ -587,9 +558,7 @@ inline int getsign(double value) { ...@@ -587,9 +558,7 @@ inline int getsign(double value) {
_ecvt_s(buffer, sizeof(buffer), value, 0, &dec, &sign); _ecvt_s(buffer, sizeof(buffer), value, 0, &dec, &sign);
return sign; return sign;
} }
inline int isinfinity(double x) { inline int isinfinity(double x) { return !_finite(x); }
return !_finite(x);
}
inline int isinfinity(long double x) { inline int isinfinity(long double x) {
return !_finite(static_cast<double>(x)); return !_finite(static_cast<double>(x));
} }
...@@ -597,15 +566,13 @@ inline int isinfinity(long double x) { ...@@ -597,15 +566,13 @@ inline int isinfinity(long double x) {
template <typename Char> template <typename Char>
class BasicCharTraits { class BasicCharTraits {
public: public:
#if _SECURE_SCL #if _SECURE_SCL
typedef stdext::checked_array_iterator<Char*> CharPtr; typedef stdext::checked_array_iterator<Char*> CharPtr;
#else #else
typedef Char *CharPtr; typedef Char *CharPtr;
#endif #endif
static Char cast(wchar_t value) { static Char cast(wchar_t value) { return static_cast<Char>(value); }
return static_cast<Char>(value);
}
}; };
template <typename Char> template <typename Char>
...@@ -613,14 +580,12 @@ class CharTraits; ...@@ -613,14 +580,12 @@ class CharTraits;
template <> template <>
class CharTraits<char> : public BasicCharTraits<char> { class CharTraits<char> : public BasicCharTraits<char> {
private: private:
// Conversion from wchar_t to char is not allowed. // Conversion from wchar_t to char is not allowed.
static char convert(wchar_t); static char convert(wchar_t);
public: public:
static char convert(char value) { static char convert(char value) { return value; }
return value;
}
// Formats a floating-point number. // Formats a floating-point number.
template <typename T> template <typename T>
...@@ -630,13 +595,9 @@ public: ...@@ -630,13 +595,9 @@ public:
template <> template <>
class CharTraits<wchar_t> : public BasicCharTraits<wchar_t> { class CharTraits<wchar_t> : public BasicCharTraits<wchar_t> {
public: public:
static wchar_t convert(char value) { static wchar_t convert(char value) { return value; }
return value; static wchar_t convert(wchar_t value) { return value; }
}
static wchar_t convert(wchar_t value) {
return value;
}
template <typename T> template <typename T>
static int format_float(wchar_t *buffer, std::size_t size, static int format_float(wchar_t *buffer, std::size_t size,
...@@ -647,17 +608,13 @@ public: ...@@ -647,17 +608,13 @@ public:
template <bool IsSigned> template <bool IsSigned>
struct SignChecker { struct SignChecker {
template <typename T> template <typename T>
static bool is_negative(T value) { static bool is_negative(T value) { return value < 0; }
return value < 0;
}
}; };
template <> template <>
struct SignChecker<false> { struct SignChecker<false> {
template <typename T> template <typename T>
static bool is_negative(T) { static bool is_negative(T) { return false; }
return false;
}
}; };
// Returns true if value is negative, false otherwise. // Returns true if value is negative, false otherwise.
...@@ -669,14 +626,10 @@ inline bool is_negative(T value) { ...@@ -669,14 +626,10 @@ inline bool is_negative(T value) {
// Selects uint32_t if FitsIn32Bits is true, uint64_t otherwise. // Selects uint32_t if FitsIn32Bits is true, uint64_t otherwise.
template <bool FitsIn32Bits> template <bool FitsIn32Bits>
struct TypeSelector { struct TypeSelector { typedef uint32_t Type; };
typedef uint32_t Type;
};
template <> template <>
struct TypeSelector<false> { struct TypeSelector<false> { typedef uint64_t Type; };
typedef uint64_t Type;
};
template <typename T> template <typename T>
struct IntTraits { struct IntTraits {
...@@ -688,9 +641,7 @@ struct IntTraits { ...@@ -688,9 +641,7 @@ struct IntTraits {
// MakeUnsigned<T>::Type gives an unsigned type corresponding to integer type T. // MakeUnsigned<T>::Type gives an unsigned type corresponding to integer type T.
template <typename T> template <typename T>
struct MakeUnsigned { struct MakeUnsigned { typedef T Type; };
typedef T Type;
};
#define FMT_SPECIALIZE_MAKE_UNSIGNED(T, U) \ #define FMT_SPECIALIZE_MAKE_UNSIGNED(T, U) \
template <> \ template <> \
...@@ -793,46 +744,30 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) { ...@@ -793,46 +744,30 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) {
// A converter from UTF-8 to UTF-16. // A converter from UTF-8 to UTF-16.
// It is only provided for Windows since other systems support UTF-8 natively. // It is only provided for Windows since other systems support UTF-8 natively.
class UTF8ToUTF16 { class UTF8ToUTF16 {
private: private:
MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer_; MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer_;
public: public:
explicit UTF8ToUTF16(StringRef s); explicit UTF8ToUTF16(StringRef s);
operator WStringRef() const { operator WStringRef() const { return WStringRef(&buffer_[0], size()); }
return WStringRef(&buffer_[0], size()); size_t size() const { return buffer_.size() - 1; }
} const wchar_t *c_str() const { return &buffer_[0]; }
size_t size() const { std::wstring str() const { return std::wstring(&buffer_[0], size()); }
return buffer_.size() - 1;
}
const wchar_t *c_str() const {
return &buffer_[0];
}
std::wstring str() const {
return std::wstring(&buffer_[0], size());
}
}; };
// A converter from UTF-16 to UTF-8. // A converter from UTF-16 to UTF-8.
// It is only provided for Windows since other systems support UTF-8 natively. // It is only provided for Windows since other systems support UTF-8 natively.
class UTF16ToUTF8 { class UTF16ToUTF8 {
private: private:
MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer_; MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer_;
public: public:
UTF16ToUTF8() {} UTF16ToUTF8() {}
explicit UTF16ToUTF8(WStringRef s); explicit UTF16ToUTF8(WStringRef s);
operator StringRef() const { operator StringRef() const { return StringRef(&buffer_[0], size()); }
return StringRef(&buffer_[0], size()); size_t size() const { return buffer_.size() - 1; }
} const char *c_str() const { return &buffer_[0]; }
size_t size() const { std::string str() const { return std::string(&buffer_[0], size()); }
return buffer_.size() - 1;
}
const char *c_str() const {
return &buffer_[0];
}
std::string str() const {
return std::string(&buffer_[0], size());
}
// Performs conversion returning a system error code instead of // Performs conversion returning a system error code instead of
// throwing exception on conversion error. This method may still throw // throwing exception on conversion error. This method may still throw
...@@ -855,7 +790,7 @@ struct Value { ...@@ -855,7 +790,7 @@ struct Value {
std::size_t size; std::size_t size;
}; };
typedef void(*FormatFunc)( typedef void (*FormatFunc)(
void *formatter, const void *arg, void *format_str_ptr); void *formatter, const void *arg, void *format_str_ptr);
struct CustomValue { struct CustomValue {
...@@ -916,7 +851,7 @@ struct WCharHelper<T, wchar_t> { ...@@ -916,7 +851,7 @@ struct WCharHelper<T, wchar_t> {
template <typename T> template <typename T>
class IsConvertibleToInt { class IsConvertibleToInt {
private: private:
typedef char yes[1]; typedef char yes[1];
typedef char no[2]; typedef char no[2];
...@@ -925,7 +860,7 @@ private: ...@@ -925,7 +860,7 @@ private:
static yes &convert(fmt::ULongLong); static yes &convert(fmt::ULongLong);
static no &convert(...); static no &convert(...);
public: public:
enum { value = (sizeof(convert(get())) == sizeof(yes)) }; enum { value = (sizeof(convert(get())) == sizeof(yes)) };
}; };
...@@ -945,30 +880,22 @@ template<bool B, class T = void> ...@@ -945,30 +880,22 @@ template<bool B, class T = void>
struct EnableIf {}; struct EnableIf {};
template<class T> template<class T>
struct EnableIf<true, T> { struct EnableIf<true, T> { typedef T type; };
typedef T type;
};
template<bool B, class T, class F> template<bool B, class T, class F>
struct Conditional { struct Conditional { typedef T type; };
typedef T type;
};
template<class T, class F> template<class T, class F>
struct Conditional<false, T, F> { struct Conditional<false, T, F> { typedef F type; };
typedef F type;
};
// A helper function to suppress bogus "conditional expression is constant" // A helper function to suppress bogus "conditional expression is constant"
// warnings. // warnings.
inline bool check(bool value) { inline bool check(bool value) { return value; }
return value;
}
// Makes an Arg object from any type. // Makes an Arg object from any type.
template <typename Char> template <typename Char>
class MakeValue : public Arg { class MakeValue : public Arg {
private: private:
// The following two methods are private to disallow formatting of // The following two methods are private to disallow formatting of
// arbitrary pointers. If you want to output a pointer cast it to // arbitrary pointers. If you want to output a pointer cast it to
// "void *" or "const void *". In particular, this forbids formatting // "void *" or "const void *". In particular, this forbids formatting
...@@ -1008,7 +935,7 @@ private: ...@@ -1008,7 +935,7 @@ private:
*static_cast<const T*>(arg)); *static_cast<const T*>(arg));
} }
public: public:
MakeValue() {} MakeValue() {}
#define FMT_MAKE_VALUE_(Type, field, TYPE, rhs) \ #define FMT_MAKE_VALUE_(Type, field, TYPE, rhs) \
...@@ -1059,9 +986,7 @@ public: ...@@ -1059,9 +986,7 @@ public:
MakeValue(typename WCharHelper<wchar_t, Char>::Supported value) { MakeValue(typename WCharHelper<wchar_t, Char>::Supported value) {
int_value = value; int_value = value;
} }
static uint64_t type(wchar_t) { static uint64_t type(wchar_t) { return Arg::CHAR; }
return Arg::CHAR;
}
#define FMT_MAKE_STR_VALUE(Type, TYPE) \ #define FMT_MAKE_STR_VALUE(Type, TYPE) \
MakeValue(Type value) { set_string(value); } \ MakeValue(Type value) { set_string(value); } \
...@@ -1110,14 +1035,10 @@ public: ...@@ -1110,14 +1035,10 @@ public:
// Additional template param `Char_` is needed here because make_type always // Additional template param `Char_` is needed here because make_type always
// uses MakeValue<char>. // uses MakeValue<char>.
template <typename Char_> template <typename Char_>
MakeValue(const NamedArg<Char_> &value) { MakeValue(const NamedArg<Char_> &value) { pointer = &value; }
pointer = &value;
}
template <typename Char_> template <typename Char_>
static uint64_t type(const NamedArg<Char_> &) { static uint64_t type(const NamedArg<Char_> &) { return Arg::NAMED_ARG; }
return Arg::NAMED_ARG;
}
}; };
template <typename Char> template <typename Char>
...@@ -1155,7 +1076,7 @@ struct NamedArg : Arg { ...@@ -1155,7 +1076,7 @@ struct NamedArg : Arg {
// http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
template <typename Impl, typename Result> template <typename Impl, typename Result>
class ArgVisitor { class ArgVisitor {
public: public:
void report_unhandled_arg() {} void report_unhandled_arg() {}
Result visit_unhandled_arg() { Result visit_unhandled_arg() {
...@@ -1249,7 +1170,7 @@ public: ...@@ -1249,7 +1170,7 @@ public:
}; };
class RuntimeError : public std::runtime_error { class RuntimeError : public std::runtime_error {
protected: protected:
RuntimeError() : std::runtime_error("") {} RuntimeError() : std::runtime_error("") {}
}; };
...@@ -1265,7 +1186,7 @@ class ArgMap; ...@@ -1265,7 +1186,7 @@ class ArgMap;
/** An argument list. */ /** An argument list. */
class ArgList { class ArgList {
private: private:
// To reduce compiled code size per formatting function call, types of first // To reduce compiled code size per formatting function call, types of first
// MAX_PACKED_ARGS arguments are passed in the types_ field. // MAX_PACKED_ARGS arguments are passed in the types_ field.
uint64_t types_; uint64_t types_;
...@@ -1289,7 +1210,7 @@ private: ...@@ -1289,7 +1210,7 @@ private:
template <typename Char> template <typename Char>
friend class internal::ArgMap; friend class internal::ArgMap;
public: public:
// Maximum number of arguments with packed types. // Maximum number of arguments with packed types.
enum { MAX_PACKED_ARGS = 16 }; enum { MAX_PACKED_ARGS = 16 };
...@@ -1333,13 +1254,13 @@ namespace internal { ...@@ -1333,13 +1254,13 @@ namespace internal {
template <typename Char> template <typename Char>
class ArgMap { class ArgMap {
private: private:
typedef std::map<fmt::BasicStringRef<Char>, internal::Arg> MapType; typedef std::map<fmt::BasicStringRef<Char>, internal::Arg> MapType;
typedef typename MapType::value_type Pair; typedef typename MapType::value_type Pair;
MapType map_; MapType map_;
public: public:
void init(const ArgList &args); void init(const ArgList &args);
const internal::Arg* find(const fmt::BasicStringRef<Char> &name) const { const internal::Arg* find(const fmt::BasicStringRef<Char> &name) const {
...@@ -1349,17 +1270,15 @@ public: ...@@ -1349,17 +1270,15 @@ public:
}; };
class FormatterBase { class FormatterBase {
private: private:
ArgList args_; ArgList args_;
int next_arg_index_; int next_arg_index_;
// Returns the argument with specified index. // Returns the argument with specified index.
Arg do_get_arg(unsigned arg_index, const char *&error); Arg do_get_arg(unsigned arg_index, const char *&error);
protected: protected:
const ArgList &args() const { const ArgList &args() const { return args_; }
return args_;
}
explicit FormatterBase(const ArgList &args) { explicit FormatterBase(const ArgList &args) {
args_ = args; args_ = args;
...@@ -1385,7 +1304,7 @@ protected: ...@@ -1385,7 +1304,7 @@ protected:
// A printf formatter. // A printf formatter.
template <typename Char> template <typename Char>
class PrintfFormatter : private FormatterBase { class PrintfFormatter : private FormatterBase {
private: private:
void parse_flags(FormatSpec &spec, const Char *&s); void parse_flags(FormatSpec &spec, const Char *&s);
// Returns the argument with specified index or, if arg_index is equal // Returns the argument with specified index or, if arg_index is equal
...@@ -1396,7 +1315,7 @@ private: ...@@ -1396,7 +1315,7 @@ private:
// Parses argument index, flags and width and returns the argument index. // Parses argument index, flags and width and returns the argument index.
unsigned parse_header(const Char *&s, FormatSpec &spec); unsigned parse_header(const Char *&s, FormatSpec &spec);
public: public:
explicit PrintfFormatter(const ArgList &args) : FormatterBase(args) {} explicit PrintfFormatter(const ArgList &args) : FormatterBase(args) {}
void format(BasicWriter<Char> &writer, BasicCStringRef<Char> format_str); void format(BasicWriter<Char> &writer, BasicCStringRef<Char> format_str);
}; };
...@@ -1405,7 +1324,7 @@ public: ...@@ -1405,7 +1324,7 @@ public:
// A formatter. // A formatter.
template <typename Char> template <typename Char>
class BasicFormatter : private internal::FormatterBase { class BasicFormatter : private internal::FormatterBase {
private: private:
BasicWriter<Char> &writer_; BasicWriter<Char> &writer_;
internal::ArgMap<Char> map_; internal::ArgMap<Char> map_;
...@@ -1423,13 +1342,11 @@ private: ...@@ -1423,13 +1342,11 @@ private:
// Parses argument name and returns corresponding argument. // Parses argument name and returns corresponding argument.
internal::Arg parse_arg_name(const Char *&s); internal::Arg parse_arg_name(const Char *&s);
public: public:
BasicFormatter(const ArgList &args, BasicWriter<Char> &w) BasicFormatter(const ArgList &args, BasicWriter<Char> &w)
: FormatterBase(args), writer_(w) {} : FormatterBase(args), writer_(w) {}
BasicWriter<Char> &writer() { BasicWriter<Char> &writer() { return writer_; }
return writer_;
}
void format(BasicCStringRef<Char> format_str); void format(BasicCStringRef<Char> format_str);
...@@ -1452,24 +1369,12 @@ struct EmptySpec {}; ...@@ -1452,24 +1369,12 @@ struct EmptySpec {};
// A type specifier. // A type specifier.
template <char TYPE> template <char TYPE>
struct TypeSpec : EmptySpec { struct TypeSpec : EmptySpec {
Alignment align() const { Alignment align() const { return ALIGN_DEFAULT; }
return ALIGN_DEFAULT; unsigned width() const { return 0; }
} int precision() const { return -1; }
unsigned width() const { bool flag(unsigned) const { return false; }
return 0; char type() const { return TYPE; }
} char fill() const { return ' '; }
int precision() const {
return -1;
}
bool flag(unsigned) const {
return false;
}
char type() const {
return TYPE;
}
char fill() const {
return ' ';
}
}; };
// A width specifier. // A width specifier.
...@@ -1481,12 +1386,8 @@ struct WidthSpec { ...@@ -1481,12 +1386,8 @@ struct WidthSpec {
WidthSpec(unsigned width, wchar_t fill) : width_(width), fill_(fill) {} WidthSpec(unsigned width, wchar_t fill) : width_(width), fill_(fill) {}
unsigned width() const { unsigned width() const { return width_; }
return width_; wchar_t fill() const { return fill_; }
}
wchar_t fill() const {
return fill_;
}
}; };
// An alignment specifier. // An alignment specifier.
...@@ -1496,13 +1397,9 @@ struct AlignSpec : WidthSpec { ...@@ -1496,13 +1397,9 @@ struct AlignSpec : WidthSpec {
AlignSpec(unsigned width, wchar_t fill, Alignment align = ALIGN_DEFAULT) AlignSpec(unsigned width, wchar_t fill, Alignment align = ALIGN_DEFAULT)
: WidthSpec(width, fill), align_(align) {} : WidthSpec(width, fill), align_(align) {}
Alignment align() const { Alignment align() const { return align_; }
return align_;
}
int precision() const { int precision() const { return -1; }
return -1;
}
}; };
// An alignment and type specifier. // An alignment and type specifier.
...@@ -1510,12 +1407,8 @@ template <char TYPE> ...@@ -1510,12 +1407,8 @@ template <char TYPE>
struct AlignTypeSpec : AlignSpec { struct AlignTypeSpec : AlignSpec {
AlignTypeSpec(unsigned width, wchar_t fill) : AlignSpec(width, fill) {} AlignTypeSpec(unsigned width, wchar_t fill) : AlignSpec(width, fill) {}
bool flag(unsigned) const { bool flag(unsigned) const { return false; }
return false; char type() const { return TYPE; }
}
char type() const {
return TYPE;
}
}; };
// A full format specifier. // A full format specifier.
...@@ -1528,86 +1421,76 @@ struct FormatSpec : AlignSpec { ...@@ -1528,86 +1421,76 @@ struct FormatSpec : AlignSpec {
unsigned width = 0, char type = 0, wchar_t fill = ' ') unsigned width = 0, char type = 0, wchar_t fill = ' ')
: AlignSpec(width, fill), flags_(0), precision_(-1), type_(type) {} : AlignSpec(width, fill), flags_(0), precision_(-1), type_(type) {}
bool flag(unsigned f) const { bool flag(unsigned f) const { return (flags_ & f) != 0; }
return (flags_ & f) != 0; int precision() const { return precision_; }
} char type() const { return type_; }
int precision() const {
return precision_;
}
char type() const {
return type_;
}
}; };
// An integer format specifier. // An integer format specifier.
template <typename T, typename SpecT = TypeSpec<0>, typename Char = char> template <typename T, typename SpecT = TypeSpec<0>, typename Char = char>
class IntFormatSpec : public SpecT { class IntFormatSpec : public SpecT {
private: private:
T value_; T value_;
public: public:
IntFormatSpec(T val, const SpecT &spec = SpecT()) IntFormatSpec(T val, const SpecT &spec = SpecT())
: SpecT(spec), value_(val) {} : SpecT(spec), value_(val) {}
T value() const { T value() const { return value_; }
return value_;
}
}; };
// A string format specifier. // A string format specifier.
template <typename Char> template <typename Char>
class StrFormatSpec : public AlignSpec { class StrFormatSpec : public AlignSpec {
private: private:
const Char *str_; const Char *str_;
public: public:
template <typename FillChar> template <typename FillChar>
StrFormatSpec(const Char *str, unsigned width, FillChar fill) StrFormatSpec(const Char *str, unsigned width, FillChar fill)
: AlignSpec(width, fill), str_(str) { : AlignSpec(width, fill), str_(str) {
internal::CharTraits<Char>::convert(FillChar()); internal::CharTraits<Char>::convert(FillChar());
} }
const Char *str() const { const Char *str() const { return str_; }
return str_;
}
}; };
/** /**
Returns an integer format specifier to format the value in base 2. Returns an integer format specifier to format the value in base 2.
*/ */
IntFormatSpec<int, TypeSpec<'b'> > bin(int value); IntFormatSpec<int, TypeSpec<'b'> > bin(int value);
/** /**
Returns an integer format specifier to format the value in base 8. Returns an integer format specifier to format the value in base 8.
*/ */
IntFormatSpec<int, TypeSpec<'o'> > oct(int value); IntFormatSpec<int, TypeSpec<'o'> > oct(int value);
/** /**
Returns an integer format specifier to format the value in base 16 using Returns an integer format specifier to format the value in base 16 using
lower-case letters for the digits above 9. lower-case letters for the digits above 9.
*/ */
IntFormatSpec<int, TypeSpec<'x'> > hex(int value); IntFormatSpec<int, TypeSpec<'x'> > hex(int value);
/** /**
Returns an integer formatter format specifier to format in base 16 using Returns an integer formatter format specifier to format in base 16 using
upper-case letters for the digits above 9. upper-case letters for the digits above 9.
*/ */
IntFormatSpec<int, TypeSpec<'X'> > hexu(int value); IntFormatSpec<int, TypeSpec<'X'> > hexu(int value);
/** /**
\rst \rst
Returns an integer format specifier to pad the formatted argument with the Returns an integer format specifier to pad the formatted argument with the
fill character to the specified width using the default (right) numeric fill character to the specified width using the default (right) numeric
alignment. alignment.
**Example**:: **Example**::
MemoryWriter out; MemoryWriter out;
out << pad(hex(0xcafe), 8, '0'); out << pad(hex(0xcafe), 8, '0');
// out.str() == "0000cafe" // out.str() == "0000cafe"
\endrst \endrst
*/ */
template <char TYPE_CODE, typename Char> template <char TYPE_CODE, typename Char>
IntFormatSpec<int, AlignTypeSpec<TYPE_CODE>, Char> pad( IntFormatSpec<int, AlignTypeSpec<TYPE_CODE>, Char> pad(
int value, unsigned width, Char fill = ' '); int value, unsigned width, Char fill = ' ');
...@@ -1615,26 +1498,26 @@ IntFormatSpec<int, AlignTypeSpec<TYPE_CODE>, Char> pad( ...@@ -1615,26 +1498,26 @@ IntFormatSpec<int, AlignTypeSpec<TYPE_CODE>, Char> pad(
#define FMT_DEFINE_INT_FORMATTERS(TYPE) \ #define FMT_DEFINE_INT_FORMATTERS(TYPE) \
inline IntFormatSpec<TYPE, TypeSpec<'b'> > bin(TYPE value) { \ inline IntFormatSpec<TYPE, TypeSpec<'b'> > bin(TYPE value) { \
return IntFormatSpec<TYPE, TypeSpec<'b'> >(value, TypeSpec<'b'>()); \ return IntFormatSpec<TYPE, TypeSpec<'b'> >(value, TypeSpec<'b'>()); \
} \ } \
\ \
inline IntFormatSpec<TYPE, TypeSpec<'o'> > oct(TYPE value) { \ inline IntFormatSpec<TYPE, TypeSpec<'o'> > oct(TYPE value) { \
return IntFormatSpec<TYPE, TypeSpec<'o'> >(value, TypeSpec<'o'>()); \ return IntFormatSpec<TYPE, TypeSpec<'o'> >(value, TypeSpec<'o'>()); \
} \ } \
\ \
inline IntFormatSpec<TYPE, TypeSpec<'x'> > hex(TYPE value) { \ inline IntFormatSpec<TYPE, TypeSpec<'x'> > hex(TYPE value) { \
return IntFormatSpec<TYPE, TypeSpec<'x'> >(value, TypeSpec<'x'>()); \ return IntFormatSpec<TYPE, TypeSpec<'x'> >(value, TypeSpec<'x'>()); \
} \ } \
\ \
inline IntFormatSpec<TYPE, TypeSpec<'X'> > hexu(TYPE value) { \ inline IntFormatSpec<TYPE, TypeSpec<'X'> > hexu(TYPE value) { \
return IntFormatSpec<TYPE, TypeSpec<'X'> >(value, TypeSpec<'X'>()); \ return IntFormatSpec<TYPE, TypeSpec<'X'> >(value, TypeSpec<'X'>()); \
} \ } \
\ \
template <char TYPE_CODE> \ template <char TYPE_CODE> \
inline IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE> > pad( \ inline IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE> > pad( \
IntFormatSpec<TYPE, TypeSpec<TYPE_CODE> > f, unsigned width) { \ IntFormatSpec<TYPE, TypeSpec<TYPE_CODE> > f, unsigned width) { \
return IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE> >( \ return IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE> >( \
f.value(), AlignTypeSpec<TYPE_CODE>(width, ' ')); \ f.value(), AlignTypeSpec<TYPE_CODE>(width, ' ')); \
} \ } \
\ \
/* For compatibility with older compilers we provide two overloads for pad, */ \ /* For compatibility with older compilers we provide two overloads for pad, */ \
/* one that takes a fill character and one that doesn't. In the future this */ \ /* one that takes a fill character and one that doesn't. In the future this */ \
...@@ -1646,20 +1529,20 @@ inline IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE>, Char> pad( \ ...@@ -1646,20 +1529,20 @@ inline IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE>, Char> pad( \
unsigned width, Char fill) { \ unsigned width, Char fill) { \
return IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE>, Char>( \ return IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE>, Char>( \
f.value(), AlignTypeSpec<TYPE_CODE>(width, fill)); \ f.value(), AlignTypeSpec<TYPE_CODE>(width, fill)); \
} \ } \
\ \
inline IntFormatSpec<TYPE, AlignTypeSpec<0> > pad( \ inline IntFormatSpec<TYPE, AlignTypeSpec<0> > pad( \
TYPE value, unsigned width) { \ TYPE value, unsigned width) { \
return IntFormatSpec<TYPE, AlignTypeSpec<0> >( \ return IntFormatSpec<TYPE, AlignTypeSpec<0> >( \
value, AlignTypeSpec<0>(width, ' ')); \ value, AlignTypeSpec<0>(width, ' ')); \
} \ } \
\ \
template <typename Char> \ template <typename Char> \
inline IntFormatSpec<TYPE, AlignTypeSpec<0>, Char> pad( \ inline IntFormatSpec<TYPE, AlignTypeSpec<0>, Char> pad( \
TYPE value, unsigned width, Char fill) { \ TYPE value, unsigned width, Char fill) { \
return IntFormatSpec<TYPE, AlignTypeSpec<0>, Char>( \ return IntFormatSpec<TYPE, AlignTypeSpec<0>, Char>( \
value, AlignTypeSpec<0>(width, fill)); \ value, AlignTypeSpec<0>(width, fill)); \
} }
FMT_DEFINE_INT_FORMATTERS(int) FMT_DEFINE_INT_FORMATTERS(int)
FMT_DEFINE_INT_FORMATTERS(long) FMT_DEFINE_INT_FORMATTERS(long)
...@@ -1669,17 +1552,17 @@ FMT_DEFINE_INT_FORMATTERS(LongLong) ...@@ -1669,17 +1552,17 @@ FMT_DEFINE_INT_FORMATTERS(LongLong)
FMT_DEFINE_INT_FORMATTERS(ULongLong) FMT_DEFINE_INT_FORMATTERS(ULongLong)
/** /**
\rst \rst
Returns a string formatter that pads the formatted argument with the fill Returns a string formatter that pads the formatted argument with the fill
character to the specified width using the default (left) string alignment. character to the specified width using the default (left) string alignment.
**Example**:: **Example**::
std::string s = str(MemoryWriter() << pad("abc", 8)); std::string s = str(MemoryWriter() << pad("abc", 8));
// s == "abc " // s == "abc "
\endrst \endrst
*/ */
template <typename Char> template <typename Char>
inline StrFormatSpec<Char> pad( inline StrFormatSpec<Char> pad(
const Char *str, unsigned width, Char fill = ' ') { const Char *str, unsigned width, Char fill = ' ') {
...@@ -1711,14 +1594,10 @@ inline StrFormatSpec<wchar_t> pad( ...@@ -1711,14 +1594,10 @@ inline StrFormatSpec<wchar_t> pad(
# define FMT_GEN15(f) FMT_GEN14(f), f(14) # define FMT_GEN15(f) FMT_GEN14(f), f(14)
namespace internal { namespace internal {
inline uint64_t make_type() { inline uint64_t make_type() { return 0; }
return 0;
}
template <typename T> template <typename T>
inline uint64_t make_type(const T &arg) { inline uint64_t make_type(const T &arg) { return MakeValue<char>::type(arg); }
return MakeValue<char>::type(arg);
}
template <unsigned N> template <unsigned N>
struct ArgArray { struct ArgArray {
...@@ -1892,21 +1771,21 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) { ...@@ -1892,21 +1771,21 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8), f(x9, 9) FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8), f(x9, 9)
/** /**
An error returned by an operating system or a language runtime, An error returned by an operating system or a language runtime,
for example a file opening error. for example a file opening error.
*/ */
class SystemError : public internal::RuntimeError { class SystemError : public internal::RuntimeError {
private: private:
void init(int err_code, CStringRef format_str, ArgList args); void init(int err_code, CStringRef format_str, ArgList args);
protected: protected:
int error_code_; int error_code_;
typedef char Char; // For FMT_VARIADIC_CTOR. typedef char Char; // For FMT_VARIADIC_CTOR.
SystemError() {} SystemError() {}
public: public:
/** /**
\rst \rst
Constructs a :class:`fmt::SystemError` object with the description Constructs a :class:`fmt::SystemError` object with the description
...@@ -1937,32 +1816,30 @@ public: ...@@ -1937,32 +1816,30 @@ public:
} }
FMT_VARIADIC_CTOR(SystemError, init, int, CStringRef) FMT_VARIADIC_CTOR(SystemError, init, int, CStringRef)
int error_code() const { int error_code() const { return error_code_; }
return error_code_;
}
}; };
/** /**
\rst \rst
This template provides operations for formatting and writing data into This template provides operations for formatting and writing data into
a character stream. The output is stored in a buffer provided by a subclass a character stream. The output is stored in a buffer provided by a subclass
such as :class:`fmt::BasicMemoryWriter`. such as :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 | BasicWriter<char> | | Writer | BasicWriter<char> |
+---------+----------------------+ +---------+----------------------+
| WWriter | BasicWriter<wchar_t> | | WWriter | BasicWriter<wchar_t> |
+---------+----------------------+ +---------+----------------------+
\endrst \endrst
*/ */
template <typename Char> template <typename Char>
class BasicWriter { class BasicWriter {
private: private:
// Output buffer. // Output buffer.
Buffer<Char> &buffer_; Buffer<Char> &buffer_;
...@@ -1972,13 +1849,9 @@ private: ...@@ -1972,13 +1849,9 @@ private:
#if _SECURE_SCL #if _SECURE_SCL
// Returns pointer value. // Returns pointer value.
static Char *get(CharPtr p) { static Char *get(CharPtr p) { return p.base(); }
return p.base();
}
#else #else
static Char *get(Char *p) { static Char *get(Char *p) { return 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
...@@ -2010,8 +1883,7 @@ private: ...@@ -2010,8 +1883,7 @@ private:
if (internal::is_negative(value)) { if (internal::is_negative(value)) {
abs_value = 0 - abs_value; abs_value = 0 - abs_value;
*write_unsigned_decimal(abs_value, 1) = '-'; *write_unsigned_decimal(abs_value, 1) = '-';
} } else {
else {
write_unsigned_decimal(abs_value, 0); write_unsigned_decimal(abs_value, 0);
} }
} }
...@@ -2068,13 +1940,13 @@ private: ...@@ -2068,13 +1940,13 @@ private:
friend class internal::PrintfArgFormatter<Char>; friend class internal::PrintfArgFormatter<Char>;
protected: protected:
/** /**
Constructs a ``BasicWriter`` object. Constructs a ``BasicWriter`` object.
*/ */
explicit BasicWriter(Buffer<Char> &b) : buffer_(b) {} explicit BasicWriter(Buffer<Char> &b) : buffer_(b) {}
public: public:
/** /**
\rst \rst
Destroys a ``BasicWriter`` object. Destroys a ``BasicWriter`` object.
...@@ -2085,17 +1957,13 @@ public: ...@@ -2085,17 +1957,13 @@ public:
/** /**
Returns the total number of characters written. Returns the total number of characters written.
*/ */
std::size_t size() const { std::size_t size() const { return buffer_.size(); }
return buffer_.size();
}
/** /**
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 { const Char *data() const FMT_NOEXCEPT { return &buffer_[0]; }
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
...@@ -2237,7 +2105,7 @@ public: ...@@ -2237,7 +2105,7 @@ public:
return *this; return *this;
} }
void clear() FMT_NOEXCEPT{ buffer_.clear(); } void clear() FMT_NOEXCEPT { buffer_.clear(); }
}; };
template <typename Char> template <typename Char>
...@@ -2251,15 +2119,12 @@ typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str( ...@@ -2251,15 +2119,12 @@ typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str(
if (spec.align() == ALIGN_RIGHT) { if (spec.align() == ALIGN_RIGHT) {
std::fill_n(out, spec.width() - size, fill); std::fill_n(out, spec.width() - size, fill);
out += spec.width() - size; out += spec.width() - size;
} } else if (spec.align() == ALIGN_CENTER) {
else if (spec.align() == ALIGN_CENTER) {
out = fill_padding(out, spec.width(), size, fill); out = fill_padding(out, spec.width(), size, fill);
} } else {
else {
std::fill_n(out + size, spec.width() - size, fill); std::fill_n(out + size, spec.width() - size, fill);
} }
} } else {
else {
out = grow_buffer(size); out = grow_buffer(size);
} }
std::copy(s, s + size, out); std::copy(s, s + size, out);
...@@ -2268,7 +2133,7 @@ typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str( ...@@ -2268,7 +2133,7 @@ typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str(
template <typename Char> template <typename Char>
typename BasicWriter<Char>::CharPtr typename BasicWriter<Char>::CharPtr
BasicWriter<Char>::fill_padding( BasicWriter<Char>::fill_padding(
CharPtr buffer, unsigned total_size, CharPtr 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;
...@@ -2284,7 +2149,7 @@ BasicWriter<Char>::fill_padding( ...@@ -2284,7 +2149,7 @@ BasicWriter<Char>::fill_padding(
template <typename Char> template <typename Char>
template <typename Spec> template <typename Spec>
typename BasicWriter<Char>::CharPtr typename BasicWriter<Char>::CharPtr
BasicWriter<Char>::prepare_int_buffer( BasicWriter<Char>::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();
...@@ -2325,20 +2190,17 @@ BasicWriter<Char>::prepare_int_buffer( ...@@ -2325,20 +2190,17 @@ BasicWriter<Char>::prepare_int_buffer(
std::copy(prefix, prefix + prefix_size, p); std::copy(prefix, prefix + prefix_size, p);
p += size; p += size;
std::fill(p, end, fill); std::fill(p, end, fill);
} } else if (align == ALIGN_CENTER) {
else if (align == ALIGN_CENTER) {
p = fill_padding(p, width, size, fill); p = fill_padding(p, width, size, fill);
std::copy(prefix, prefix + prefix_size, p); std::copy(prefix, prefix + prefix_size, p);
p += size; p += size;
} } else {
else {
if (align == ALIGN_NUMERIC) { if (align == ALIGN_NUMERIC) {
if (prefix_size != 0) { if (prefix_size != 0) {
p = std::copy(prefix, prefix + prefix_size, p); p = std::copy(prefix, prefix + prefix_size, p);
size -= prefix_size; size -= prefix_size;
} }
} } else {
else {
std::copy(prefix, prefix + prefix_size, end - size); std::copy(prefix, prefix + prefix_size, end - size);
} }
std::fill(p, end - size, fill); std::fill(p, end - size, fill);
...@@ -2358,22 +2220,19 @@ void BasicWriter<Char>::write_int(T value, Spec spec) { ...@@ -2358,22 +2220,19 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
prefix[0] = '-'; prefix[0] = '-';
++prefix_size; ++prefix_size;
abs_value = 0 - abs_value; abs_value = 0 - abs_value;
} } else if (spec.flag(SIGN_FLAG)) {
else if (spec.flag(SIGN_FLAG)) {
prefix[0] = spec.flag(PLUS_FLAG) ? '+' : ' '; prefix[0] = spec.flag(PLUS_FLAG) ? '+' : ' ';
++prefix_size; ++prefix_size;
} }
switch (spec.type()) { switch (spec.type()) {
case 0: case 0: case 'd': {
case 'd': {
unsigned num_digits = internal::count_digits(abs_value); unsigned num_digits = internal::count_digits(abs_value);
CharPtr p = prepare_int_buffer( CharPtr p = prepare_int_buffer(
num_digits, spec, prefix, prefix_size) + 1 - num_digits; num_digits, spec, prefix, prefix_size) + 1 - num_digits;
internal::format_decimal(get(p), abs_value, num_digits); internal::format_decimal(get(p), abs_value, num_digits);
break; break;
} }
case 'x': case 'x': case 'X': {
case 'X': {
UnsignedType n = abs_value; UnsignedType n = abs_value;
if (spec.flag(HASH_FLAG)) { if (spec.flag(HASH_FLAG)) {
prefix[prefix_size++] = '0'; prefix[prefix_size++] = '0';
...@@ -2393,8 +2252,7 @@ void BasicWriter<Char>::write_int(T value, Spec spec) { ...@@ -2393,8 +2252,7 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
} while ((n >>= 4) != 0); } while ((n >>= 4) != 0);
break; break;
} }
case 'b': case 'b': case 'B': {
case 'B': {
UnsignedType n = abs_value; UnsignedType n = abs_value;
if (spec.flag(HASH_FLAG)) { if (spec.flag(HASH_FLAG)) {
prefix[prefix_size++] = '0'; prefix[prefix_size++] = '0';
...@@ -2444,10 +2302,7 @@ void BasicWriter<Char>::write_double( ...@@ -2444,10 +2302,7 @@ void BasicWriter<Char>::write_double(
case 0: case 0:
type = 'g'; type = 'g';
break; break;
case 'e': case 'e': case 'f': case 'g': case 'a':
case 'f':
case 'g':
case 'a':
break; break;
case 'F': case 'F':
#ifdef _MSC_VER #ifdef _MSC_VER
...@@ -2455,9 +2310,7 @@ void BasicWriter<Char>::write_double( ...@@ -2455,9 +2310,7 @@ void BasicWriter<Char>::write_double(
type = 'f'; type = 'f';
#endif #endif
// Fall through. // Fall through.
case 'E': case 'E': case 'G': case 'A':
case 'G':
case 'A':
upper = true; upper = true;
break; break;
default: default:
...@@ -2471,8 +2324,7 @@ void BasicWriter<Char>::write_double( ...@@ -2471,8 +2324,7 @@ void BasicWriter<Char>::write_double(
if (internal::getsign(static_cast<double>(value))) { if (internal::getsign(static_cast<double>(value))) {
sign = '-'; sign = '-';
value = -value; value = -value;
} } else if (spec.flag(SIGN_FLAG)) {
else if (spec.flag(SIGN_FLAG)) {
sign = spec.flag(PLUS_FLAG) ? '+' : ' '; sign = spec.flag(PLUS_FLAG) ? '+' : ' ';
} }
...@@ -2516,7 +2368,7 @@ void BasicWriter<Char>::write_double( ...@@ -2516,7 +2368,7 @@ void BasicWriter<Char>::write_double(
} }
// 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 format[MAX_FORMAT_SIZE];
Char *format_ptr = format; Char *format_ptr = format;
*format_ptr++ = '%'; *format_ptr++ = '%';
...@@ -2525,8 +2377,7 @@ void BasicWriter<Char>::write_double( ...@@ -2525,8 +2377,7 @@ void BasicWriter<Char>::write_double(
*format_ptr++ = '#'; *format_ptr++ = '#';
if (spec.align() == ALIGN_CENTER) { if (spec.align() == ALIGN_CENTER) {
width_for_sprintf = 0; width_for_sprintf = 0;
} } else {
else {
if (spec.align() == ALIGN_LEFT) if (spec.align() == ALIGN_LEFT)
*format_ptr++ = '-'; *format_ptr++ = '-';
if (width != 0) if (width != 0)
...@@ -2563,8 +2414,7 @@ void BasicWriter<Char>::write_double( ...@@ -2563,8 +2414,7 @@ void BasicWriter<Char>::write_double(
*start != ' ') { *start != ' ') {
*(start - 1) = sign; *(start - 1) = sign;
sign = 0; sign = 0;
} } else {
else {
*(start - 1) = fill; *(start - 1) = fill;
} }
++n; ++n;
...@@ -2593,45 +2443,45 @@ void BasicWriter<Char>::write_double( ...@@ -2593,45 +2443,45 @@ void BasicWriter<Char>::write_double(
} }
/** /**
\rst \rst
This class template provides operations for formatting and writing data This class template provides operations for formatting and writing data
into a character stream. The output is stored in a memory buffer that grows into a character stream. The output is stored in a memory buffer that grows
dynamically. dynamically.
You can use one of the following typedefs for common character types You can use one of the following typedefs for common character types
and the standard allocator: and the standard allocator:
+---------------+-----------------------------------------------------+ +---------------+-----------------------------------------------------+
| Type | Definition | | Type | Definition |
+===============+=====================================================+ +===============+=====================================================+
| MemoryWriter | BasicMemoryWriter<char, std::allocator<char>> | | MemoryWriter | BasicMemoryWriter<char, std::allocator<char>> |
+---------------+-----------------------------------------------------+ +---------------+-----------------------------------------------------+
| WMemoryWriter | BasicMemoryWriter<wchar_t, std::allocator<wchar_t>> | | WMemoryWriter | BasicMemoryWriter<wchar_t, std::allocator<wchar_t>> |
+---------------+-----------------------------------------------------+ +---------------+-----------------------------------------------------+
**Example**:: **Example**::
MemoryWriter out; MemoryWriter out;
out << "The answer is " << 42 << "\n"; out << "The answer is " << 42 << "\n";
out.write("({:+f}, {:+f})", -3.14, 3.14); out.write("({:+f}, {:+f})", -3.14, 3.14);
This will write the following output to the ``out`` object: This will write the following output to the ``out`` object:
.. code-block:: none .. code-block:: none
The answer is 42 The answer is 42
(-3.140000, +3.140000) (-3.140000, +3.140000)
The output can be converted to an ``std::string`` with ``out.str()`` or The output can be converted to an ``std::string`` with ``out.str()`` or
accessed as a C string with ``out.c_str()``. accessed as a C string with ``out.c_str()``.
\endrst \endrst
*/ */
template <typename Char, typename Allocator = std::allocator<Char> > template <typename Char, typename Allocator = std::allocator<Char> >
class BasicMemoryWriter : public BasicWriter<Char> { class BasicMemoryWriter : public BasicWriter<Char> {
private: private:
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE, Allocator> buffer_; internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE, Allocator> buffer_;
public: public:
explicit BasicMemoryWriter(const Allocator& alloc = Allocator()) explicit BasicMemoryWriter(const Allocator& alloc = Allocator())
: BasicWriter<Char>(buffer_), buffer_(alloc) {} : BasicWriter<Char>(buffer_), buffer_(alloc) {}
...@@ -2662,31 +2512,31 @@ typedef BasicMemoryWriter<char> MemoryWriter; ...@@ -2662,31 +2512,31 @@ typedef BasicMemoryWriter<char> MemoryWriter;
typedef BasicMemoryWriter<wchar_t> WMemoryWriter; typedef BasicMemoryWriter<wchar_t> WMemoryWriter;
/** /**
\rst \rst
This class template provides operations for formatting and writing data This class template provides operations for formatting and writing data
into a fixed-size array. For writing into a dynamically growing buffer into a fixed-size array. For writing into a dynamically growing buffer
use :class:`fmt::BasicMemoryWriter`. use :class:`fmt::BasicMemoryWriter`.
Any write method will throw ``std::runtime_error`` if the output doesn't fit Any write method will throw ``std::runtime_error`` if the output doesn't fit
into the array. into the array.
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 |
+==============+===========================+ +==============+===========================+
| ArrayWriter | BasicArrayWriter<char> | | ArrayWriter | BasicArrayWriter<char> |
+--------------+---------------------------+ +--------------+---------------------------+
| WArrayWriter | BasicArrayWriter<wchar_t> | | WArrayWriter | BasicArrayWriter<wchar_t> |
+--------------+---------------------------+ +--------------+---------------------------+
\endrst \endrst
*/ */
template <typename Char> template <typename Char>
class BasicArrayWriter : public BasicWriter<Char> { class BasicArrayWriter : public BasicWriter<Char> {
private: private:
internal::FixedBuffer<Char> buffer_; internal::FixedBuffer<Char> buffer_;
public: public:
/** /**
\rst \rst
Constructs a :class:`fmt::BasicArrayWriter` object for *array* of the Constructs a :class:`fmt::BasicArrayWriter` object for *array* of the
...@@ -2703,7 +2553,7 @@ public: ...@@ -2703,7 +2553,7 @@ public:
\endrst \endrst
*/ */
template <std::size_t SIZE> template <std::size_t SIZE>
explicit BasicArrayWriter(Char(&array)[SIZE]) explicit BasicArrayWriter(Char (&array)[SIZE])
: BasicWriter<Char>(buffer_), buffer_(array, SIZE) {} : BasicWriter<Char>(buffer_), buffer_(array, SIZE) {}
}; };
...@@ -2730,10 +2580,10 @@ void report_system_error(int error_code, StringRef message) FMT_NOEXCEPT; ...@@ -2730,10 +2580,10 @@ void report_system_error(int error_code, StringRef message) FMT_NOEXCEPT;
/** A Windows error. */ /** A Windows error. */
class WindowsError : public SystemError { class WindowsError : public SystemError {
private: private:
void init(int error_code, CStringRef format_str, ArgList args); void init(int error_code, CStringRef format_str, ArgList args);
public: public:
/** /**
\rst \rst
Constructs a :class:`fmt::WindowsError` object with the description Constructs a :class:`fmt::WindowsError` object with the description
...@@ -2777,21 +2627,21 @@ void report_windows_error(int error_code, StringRef message) FMT_NOEXCEPT; ...@@ -2777,21 +2627,21 @@ void report_windows_error(int error_code, StringRef message) FMT_NOEXCEPT;
enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE }; enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE };
/** /**
Formats a string and prints it to stdout using ANSI escape sequences Formats a string and prints it to stdout using ANSI escape sequences
to specify color (experimental). to specify color (experimental).
Example: Example:
PrintColored(fmt::RED, "Elapsed time: {0:.2f} seconds") << 1.23; PrintColored(fmt::RED, "Elapsed time: {0:.2f} seconds") << 1.23;
*/ */
void print_colored(Color c, CStringRef format, ArgList args); void print_colored(Color c, CStringRef format, ArgList args);
/** /**
\rst \rst
Formats arguments and returns the result as a string. Formats arguments and returns the result as a string.
**Example**:: **Example**::
std::string message = format("The answer is {}", 42); std::string message = format("The answer is {}", 42);
\endrst \endrst
*/ */
inline std::string format(CStringRef format_str, ArgList args) { inline std::string format(CStringRef format_str, ArgList args) {
MemoryWriter w; MemoryWriter w;
...@@ -2806,36 +2656,36 @@ inline std::wstring format(WCStringRef format_str, ArgList args) { ...@@ -2806,36 +2656,36 @@ inline std::wstring format(WCStringRef format_str, ArgList args) {
} }
/** /**
\rst \rst
Prints formatted data to the file *f*. Prints formatted data to the file *f*.
**Example**:: **Example**::
print(stderr, "Don't {}!", "panic"); print(stderr, "Don't {}!", "panic");
\endrst \endrst
*/ */
void print(std::FILE *f, CStringRef format_str, ArgList args); void print(std::FILE *f, CStringRef format_str, ArgList args);
/** /**
\rst \rst
Prints formatted data to ``stdout``. Prints formatted data to ``stdout``.
**Example**:: **Example**::
print("Elapsed time: {0:.2f} seconds", 1.23); print("Elapsed time: {0:.2f} seconds", 1.23);
\endrst \endrst
*/ */
void print(CStringRef format_str, ArgList args); void print(CStringRef format_str, ArgList args);
/** /**
\rst \rst
Prints formatted data to the stream *os*. Prints formatted data to the stream *os*.
**Example**:: **Example**::
print(cerr, "Don't {}!", "panic"); print(cerr, "Don't {}!", "panic");
\endrst \endrst
*/ */
void print(std::ostream &os, CStringRef format_str, ArgList args); void print(std::ostream &os, CStringRef format_str, ArgList args);
template <typename Char> template <typename Char>
...@@ -2844,13 +2694,13 @@ void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) { ...@@ -2844,13 +2694,13 @@ void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) {
} }
/** /**
\rst \rst
Formats arguments and returns the result as a string. Formats arguments and returns the result as a string.
**Example**:: **Example**::
std::string message = fmt::sprintf("The answer is %d", 42); std::string message = fmt::sprintf("The answer is %d", 42);
\endrst \endrst
*/ */
inline std::string sprintf(CStringRef format, ArgList args) { inline std::string sprintf(CStringRef format, ArgList args) {
MemoryWriter w; MemoryWriter w;
...@@ -2859,37 +2709,37 @@ inline std::string sprintf(CStringRef format, ArgList args) { ...@@ -2859,37 +2709,37 @@ inline std::string sprintf(CStringRef format, ArgList args) {
} }
/** /**
\rst \rst
Prints formatted data to the file *f*. Prints formatted data to the file *f*.
**Example**:: **Example**::
fmt::fprintf(stderr, "Don't %s!", "panic"); fmt::fprintf(stderr, "Don't %s!", "panic");
\endrst \endrst
*/ */
int fprintf(std::FILE *f, CStringRef format, ArgList args); int fprintf(std::FILE *f, CStringRef format, ArgList args);
/** /**
\rst \rst
Prints formatted data to ``stdout``. Prints formatted data to ``stdout``.
**Example**:: **Example**::
fmt::printf("Elapsed time: %.2f seconds", 1.23); fmt::printf("Elapsed time: %.2f seconds", 1.23);
\endrst \endrst
*/ */
inline int printf(CStringRef format, ArgList args) { inline int printf(CStringRef format, ArgList args) {
return fprintf(stdout, format, args); return fprintf(stdout, format, args);
} }
/** /**
Fast integer formatter. Fast integer formatter.
*/ */
class FormatInt { class FormatInt {
private: private:
// Buffer should be large enough to hold all digits (digits10 + 1), // Buffer should be large enough to hold all digits (digits10 + 1),
// a sign and a null character. // a sign and a null character.
enum { BUFFER_SIZE = std::numeric_limits<ULongLong>::digits10 + 3 }; enum {BUFFER_SIZE = std::numeric_limits<ULongLong>::digits10 + 3};
mutable char buffer_[BUFFER_SIZE]; mutable char buffer_[BUFFER_SIZE];
char *str_; char *str_;
...@@ -2925,16 +2775,10 @@ private: ...@@ -2925,16 +2775,10 @@ private:
*--str_ = '-'; *--str_ = '-';
} }
public: public:
explicit FormatInt(int value) { explicit FormatInt(int value) { FormatSigned(value); }
FormatSigned(value); explicit FormatInt(long value) { FormatSigned(value); }
} explicit FormatInt(LongLong value) { FormatSigned(value); }
explicit FormatInt(long value) {
FormatSigned(value);
}
explicit FormatInt(LongLong value) {
FormatSigned(value);
}
explicit FormatInt(unsigned value) : str_(format_decimal(value)) {} explicit FormatInt(unsigned value) : str_(format_decimal(value)) {}
explicit FormatInt(unsigned long value) : str_(format_decimal(value)) {} explicit FormatInt(unsigned long value) : str_(format_decimal(value)) {}
explicit FormatInt(ULongLong value) : str_(format_decimal(value)) {} explicit FormatInt(ULongLong value) : str_(format_decimal(value)) {}
...@@ -2942,17 +2786,13 @@ public: ...@@ -2942,17 +2786,13 @@ public:
/** /**
Returns the number of characters written to the output buffer. Returns the number of characters written to the output buffer.
*/ */
std::size_t size() const { std::size_t size() const { return buffer_ - str_ + BUFFER_SIZE - 1; }
return buffer_ - str_ + BUFFER_SIZE - 1;
}
/** /**
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 { const char *data() const { return str_; }
return str_;
}
/** /**
Returns a pointer to the output buffer content with terminating null Returns a pointer to the output buffer content with terminating null
...@@ -2968,9 +2808,7 @@ public: ...@@ -2968,9 +2808,7 @@ public:
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::string str() const { std::string str() const { return std::string(str_, size()); }
return std::string(str_, size());
}
}; };
// Formats a decimal integer value writing into buffer and returns // Formats a decimal integer value writing into buffer and returns
...@@ -2999,15 +2837,15 @@ inline void format_decimal(char *&buffer, T value) { ...@@ -2999,15 +2837,15 @@ inline void format_decimal(char *&buffer, T value) {
} }
/** /**
\rst \rst
Returns a named argument for formatting functions. Returns a named argument for formatting functions.
**Example**:: **Example**::
print("Elapsed time: {s:.2f} seconds", arg("s", 1.23)); print("Elapsed time: {s:.2f} seconds", arg("s", 1.23));
\endrst \endrst
*/ */
template <typename T> template <typename T>
inline internal::NamedArg<char> arg(StringRef name, const T &arg) { inline internal::NamedArg<char> arg(StringRef name, const T &arg) {
return internal::NamedArg<char>(name, arg); return internal::NamedArg<char>(name, arg);
...@@ -3096,32 +2934,32 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED; ...@@ -3096,32 +2934,32 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
#endif // FMT_USE_VARIADIC_TEMPLATES #endif // FMT_USE_VARIADIC_TEMPLATES
/** /**
\rst \rst
Defines a variadic function with the specified return type, function name Defines a variadic function with the specified return type, function name
and argument types passed as variable arguments to this macro. and argument types passed as variable arguments to this macro.
**Example**:: **Example**::
void print_error(const char *file, int line, const char *format, void print_error(const char *file, int line, const char *format,
fmt::ArgList args) { fmt::ArgList args) {
fmt::print("{}: {}: ", file, line); fmt::print("{}: {}: ", file, line);
fmt::print(format, args); fmt::print(format, args);
} }
FMT_VARIADIC(void, print_error, const char *, int, const char *) FMT_VARIADIC(void, print_error, const char *, int, const char *)
``FMT_VARIADIC`` is used for compatibility with legacy C++ compilers that ``FMT_VARIADIC`` is used for compatibility with legacy C++ compilers that
don't implement variadic templates. You don't have to use this macro if don't implement variadic templates. You don't have to use this macro if
you don't need legacy compiler support and can use variadic templates you don't need legacy compiler support and can use variadic templates
directly:: directly::
template <typename... Args> template <typename... Args>
void print_error(const char *file, int line, const char *format, void print_error(const char *file, int line, const char *format,
const Args & ... args) { const Args & ... args) {
fmt::print("{}: {}: ", file, line); fmt::print("{}: {}: ", file, line);
fmt::print(format, args...); fmt::print(format, args...);
} }
\endrst \endrst
*/ */
#define FMT_VARIADIC(ReturnType, func, ...) \ #define FMT_VARIADIC(ReturnType, func, ...) \
FMT_VARIADIC_(char, ReturnType, func, return func, __VA_ARGS__) FMT_VARIADIC_(char, ReturnType, func, return func, __VA_ARGS__)
...@@ -3133,19 +2971,19 @@ fmt::print(format, args...); ...@@ -3133,19 +2971,19 @@ fmt::print(format, args...);
#define FMT_CAPTURE_ARG_W_(id, index) ::fmt::arg(L###id, id) #define FMT_CAPTURE_ARG_W_(id, index) ::fmt::arg(L###id, id)
/** /**
\rst \rst
Convenient macro to capture the arguments' names and values into several Convenient macro to capture the arguments' names and values into several
``fmt::arg(name, value)``. ``fmt::arg(name, value)``.
**Example**:: **Example**::
int x = 1, y = 2; int x = 1, y = 2;
print("point: ({x}, {y})", FMT_CAPTURE(x, y)); print("point: ({x}, {y})", FMT_CAPTURE(x, y));
// same as: // same as:
// print("point: ({x}, {y})", arg("x", x), arg("y", y)); // print("point: ({x}, {y})", arg("x", x), arg("y", y));
\endrst \endrst
*/ */
#define FMT_CAPTURE(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_, __VA_ARGS__) #define FMT_CAPTURE(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_, __VA_ARGS__)
#define FMT_CAPTURE_W(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_W_, __VA_ARGS__) #define FMT_CAPTURE_W(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_W_, __VA_ARGS__)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment