updated to latest cppformat

This commit is contained in:
gabime 2015-11-26 14:50:44 +02:00
parent cbc8ba7203
commit 7b3fc4ba97
2 changed files with 2987 additions and 2620 deletions

View File

@ -1,29 +1,29 @@
/*
Formatting library for C++
Formatting library for C++
Copyright (c) 2012 - 2015, Victor Zverovich
All rights reserved.
Copyright (c) 2012 - 2015, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
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
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
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
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
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
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
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
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "format.h"
@ -34,6 +34,7 @@
#include <climits>
#include <cmath>
#include <cstdarg>
#include <cstddef> // for std::ptrdiff_t
#if defined(_WIN32) && defined(__MINGW32__)
# include <cstring>
@ -133,7 +134,9 @@ struct IntChecker {
unsigned max = INT_MAX;
return value <= max;
}
static bool fits_in_int(bool) { return true; }
static bool fits_in_int(bool) {
return true;
}
};
template <>
@ -142,12 +145,14 @@ struct IntChecker<true> {
static bool fits_in_int(T value) {
return value >= INT_MIN && value <= INT_MAX;
}
static bool fits_in_int(int) { return true; }
static bool fits_in_int(int) {
return true;
}
};
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.
// Sets buffer to point to a string describing the error code.
@ -159,7 +164,7 @@ typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
// other - failure
// Buffer should be at least of size 1.
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");
class StrError {
@ -218,7 +223,7 @@ int safe_strerror(
}
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
// INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
// bad_alloc.
@ -236,7 +241,7 @@ void format_error_code(fmt::Writer &out, int error_code,
}
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;
func(full_message, error_code, message);
// Use Writer::data instead of Writer::c_str to avoid potential memory
@ -247,9 +252,11 @@ void report_error(FormatFunc func,
// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
class IsZeroInt : public fmt::internal::ArgVisitor<IsZeroInt, bool> {
public:
public:
template <typename T>
bool visit_any_int(T value) { return value == 0; }
bool visit_any_int(T value) {
return value == 0;
}
};
// Parses an unsigned integer advancing s to the end of the parsed input.
@ -299,12 +306,12 @@ void check_sign(const Char *&s, const Arg &arg) {
// Checks if an argument is a valid printf width specifier and sets
// left alignment if it is negative.
class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
private:
private:
fmt::FormatSpec &spec_;
FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
public:
public:
explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
void report_unhandled_arg() {
@ -327,7 +334,7 @@ class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
class PrecisionHandler :
public fmt::internal::ArgVisitor<PrecisionHandler, int> {
public:
public:
void report_unhandled_arg() {
FMT_THROW(fmt::FormatError("precision is not integer"));
}
@ -343,16 +350,21 @@ class PrecisionHandler :
// Converts an integer argument to an integral type T for printf.
template <typename T>
class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
private:
private:
fmt::internal::Arg &arg_;
wchar_t type_;
FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
public:
public:
ArgConverter(fmt::internal::Arg &arg, wchar_t type)
: arg_(arg), type_(type) {}
void visit_bool(bool value) {
if (type_ != 's')
visit_any_int(value);
}
template <typename U>
void visit_any_int(U value) {
bool is_signed = type_ == 'd' || type_ == 'i';
@ -362,17 +374,20 @@ class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
if (is_signed) {
arg_.type = Arg::INT;
arg_.int_value = static_cast<int>(static_cast<T>(value));
} else {
}
else {
arg_.type = Arg::UINT;
arg_.uint_value = static_cast<unsigned>(
static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value));
}
} else {
}
else {
if (is_signed) {
arg_.type = Arg::LONG_LONG;
arg_.long_long_value =
static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
} else {
}
else {
arg_.type = Arg::ULONG_LONG;
arg_.ulong_long_value =
static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
@ -383,12 +398,12 @@ class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
// Converts an integer argument to char for printf.
class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
private:
private:
fmt::internal::Arg &arg_;
FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
public:
public:
explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
template <typename T>
@ -403,34 +418,55 @@ namespace internal {
template <typename Impl, typename Char>
class BasicArgFormatter : public ArgVisitor<Impl, void> {
private:
private:
BasicWriter<Char> &writer_;
FormatSpec &spec_;
FMT_DISALLOW_COPY_AND_ASSIGN(BasicArgFormatter);
protected:
BasicWriter<Char> &writer() { return writer_; }
const FormatSpec &spec() const { return spec_; }
void write_pointer(const void *p) {
spec_.flags_ = HASH_FLAG;
spec_.type_ = 'x';
writer_.write_int(reinterpret_cast<uintptr_t>(p), spec_);
}
public:
protected:
BasicWriter<Char> &writer() {
return writer_;
}
FormatSpec &spec() {
return spec_;
}
void write(bool value) {
const char *str_value = value ? "true" : "false";
Arg::StringValue<char> str = { str_value, strlen(str_value) };
writer_.write_str(str, spec_);
}
void write(const char *value) {
Arg::StringValue<char> str = { value, value != 0 ? strlen(value) : 0 };
writer_.write_str(str, spec_);
}
public:
BasicArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
: writer_(w), spec_(s) {}
template <typename T>
void visit_any_int(T value) { writer_.write_int(value, spec_); }
void visit_any_int(T value) {
writer_.write_int(value, spec_);
}
template <typename T>
void visit_any_double(T value) { writer_.write_double(value, spec_); }
void visit_any_double(T value) {
writer_.write_double(value, spec_);
}
void visit_bool(bool value) {
if (spec_.type_) {
writer_.write_int(value, spec_);
return;
}
const char *str_value = value ? "true" : "false";
Arg::StringValue<char> str = { str_value, strlen(str_value) };
writer_.write_str(str, spec_);
if (spec_.type_)
return visit_any_int(value);
write(value);
}
void visit_char(int value) {
@ -450,18 +486,27 @@ class BasicArgFormatter : public ArgVisitor<Impl, void> {
if (spec_.align_ == ALIGN_RIGHT) {
std::fill_n(out, spec_.width_ - CHAR_WIDTH, fill);
out += spec_.width_ - CHAR_WIDTH;
} else if (spec_.align_ == ALIGN_CENTER) {
}
else if (spec_.align_ == ALIGN_CENTER) {
out = writer_.fill_padding(out, spec_.width_,
internal::check(CHAR_WIDTH), fill);
} else {
}
else {
std::fill_n(out + CHAR_WIDTH, spec_.width_ - CHAR_WIDTH, fill);
}
} else {
}
else {
out = writer_.grow_buffer(CHAR_WIDTH);
}
*out = internal::CharTraits<Char>::cast(value);
}
void visit_cstring(const char *value) {
if (spec_.type_ == 'p')
return write_pointer(value);
write(value);
}
void visit_string(Arg::StringValue<char> value) {
writer_.write_str(value, spec_);
}
@ -475,20 +520,18 @@ class BasicArgFormatter : public ArgVisitor<Impl, void> {
void visit_pointer(const void *value) {
if (spec_.type_ && spec_.type_ != 'p')
report_unknown_type(spec_.type_, "pointer");
spec_.flags_ = HASH_FLAG;
spec_.type_ = 'x';
writer_.write_int(reinterpret_cast<uintptr_t>(value), spec_);
write_pointer(value);
}
};
// An argument formatter.
template <typename Char>
class ArgFormatter : public BasicArgFormatter<ArgFormatter<Char>, Char> {
private:
private:
BasicFormatter<Char> &formatter_;
const Char *format_;
public:
public:
ArgFormatter(BasicFormatter<Char> &f, FormatSpec &s, const Char *fmt)
: BasicArgFormatter<ArgFormatter<Char>, Char>(f.writer(), s),
formatter_(f), format_(fmt) {}
@ -501,10 +544,26 @@ class ArgFormatter : public BasicArgFormatter<ArgFormatter<Char>, Char> {
template <typename Char>
class PrintfArgFormatter :
public BasicArgFormatter<PrintfArgFormatter<Char>, Char> {
public:
void write_null_pointer() {
this->spec().type_ = 0;
this->write("(nil)");
}
typedef BasicArgFormatter<PrintfArgFormatter<Char>, Char> Base;
public:
PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
: BasicArgFormatter<PrintfArgFormatter<Char>, Char>(w, s) {}
void visit_bool(bool value) {
FormatSpec &fmt_spec = this->spec();
if (fmt_spec.type_ != 's')
return this->visit_any_int(value);
fmt_spec.type_ = 0;
this->write(value);
}
void visit_char(int value) {
const FormatSpec &fmt_spec = this->spec();
BasicWriter<Char> &w = this->writer();
@ -518,18 +577,36 @@ class PrintfArgFormatter :
if (fmt_spec.align_ != ALIGN_LEFT) {
std::fill_n(out, fmt_spec.width_ - 1, fill);
out += fmt_spec.width_ - 1;
} else {
}
else {
std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
}
} else {
}
else {
out = w.grow_buffer(1);
}
*out = static_cast<Char>(value);
}
void visit_cstring(const char *value) {
if (value)
Base::visit_cstring(value);
else if (this->spec().type_ == 'p')
write_null_pointer();
else
this->write("(null)");
}
void visit_pointer(const void *value) {
if (value)
return Base::visit_pointer(value);
this->spec().type_ = 0;
write_null_pointer();
}
void visit_custom(Arg::CustomValue c) {
BasicFormatter<Char> formatter(ArgList(), this->writer());
const Char format_str[] = {'}', 0};
const Char format_str[] = { '}', 0 };
const Char *format = format_str;
c.format(&formatter, c.value, &format);
}
@ -672,18 +749,22 @@ FMT_FUNC void fmt::WindowsError::init(
FMT_FUNC void fmt::internal::format_windows_error(
fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT {
fmt::StringRef message) FMT_NOEXCEPT{
class String {
private:
LPWSTR str_;
public:
String() : str_() {}
~String() { LocalFree(str_); }
LPWSTR *ptr() { return &str_; }
~String() {
LocalFree(str_);
}
LPWSTR *ptr() {
return &str_;
}
LPCWSTR c_str() const { return str_; }
};
FMT_TRY {
FMT_TRY{
String system_message;
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
@ -696,15 +777,15 @@ FMT_FUNC void fmt::internal::format_windows_error(
}
}
} FMT_CATCH(...) {}
format_error_code(out, error_code, message);
fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
}
#endif // FMT_USE_WINDOWS_H
FMT_FUNC void fmt::internal::format_system_error(
fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT {
FMT_TRY {
fmt::StringRef message) FMT_NOEXCEPT{
FMT_TRY{
MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer;
buffer.resize(INLINE_BUFFER_SIZE);
for (;;) {
@ -719,7 +800,7 @@ FMT_FUNC void fmt::internal::format_system_error(
buffer.resize(buffer.size() * 2);
}
} FMT_CATCH(...) {}
format_error_code(out, error_code, message);
fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
}
template <typename Char>
@ -741,7 +822,8 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
map_.insert(Pair(named_arg->name, *named_arg));
break;
default:
/*nothing*/;
/*nothing*/
;
}
}
return;
@ -762,7 +844,8 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
map_.insert(Pair(named_arg->name, *named_arg));
break;
default:
/*nothing*/;
/*nothing*/
;
}
}
}
@ -787,8 +870,6 @@ void fmt::BasicWriter<Char>::write_str(
FMT_THROW(FormatError("string pointer is null"));
return;
}
if (*str_value)
str_size = std::char_traits<StrChar>::length(str_value);
}
std::size_t precision = spec.precision_;
if (spec.precision_ >= 0 && precision < str_size)
@ -846,7 +927,8 @@ FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
case Arg::NAMED_ARG:
arg = *static_cast<const internal::Arg*>(arg.pointer);
default:
/*nothing*/;
/*nothing*/
;
}
return arg;
}
@ -924,7 +1006,8 @@ unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
if (*s == '$') { // value is an argument index
++s;
arg_index = value;
} else {
}
else {
if (c == '0')
spec.fill_ = '0';
if (value != 0) {
@ -939,7 +1022,8 @@ unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
// Parse width.
if (*s >= '0' && *s <= '9') {
spec.width_ = parse_nonnegative_int(s);
} else if (*s == '*') {
}
else if (*s == '*') {
++s;
spec.width_ = WidthHandler(spec).visit(get_arg(s));
}
@ -972,7 +1056,8 @@ void fmt::internal::PrintfFormatter<Char>::format(
++s;
if ('0' <= *s && *s <= '9') {
spec.precision_ = parse_nonnegative_int(s);
} else if (*s == '*') {
}
else if (*s == '*') {
++s;
spec.precision_ = PrecisionHandler().visit(get_arg(s));
}
@ -1006,10 +1091,10 @@ void fmt::internal::PrintfFormatter<Char>::format(
ArgConverter<intmax_t>(arg, *s).visit(arg);
break;
case 'z':
ArgConverter<size_t>(arg, *s).visit(arg);
ArgConverter<std::size_t>(arg, *s).visit(arg);
break;
case 't':
ArgConverter<ptrdiff_t>(arg, *s).visit(arg);
ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg);
break;
case 'L':
// printf produces garbage when 'L' is omitted for long double, no
@ -1027,7 +1112,8 @@ void fmt::internal::PrintfFormatter<Char>::format(
if (arg.type <= Arg::LAST_INTEGER_TYPE) {
// Normalize type.
switch (spec.type_) {
case 'i': case 'u':
case 'i':
case 'u':
spec.type_ = 'd';
break;
case 'c':
@ -1082,7 +1168,8 @@ const Char *fmt::BasicFormatter<Char>::format(
FMT_THROW(FormatError("invalid fill character '{'"));
s += 2;
spec.fill_ = c;
} else ++s;
}
else ++s;
if (spec.align_ == ALIGN_NUMERIC)
require_numeric_argument(arg, '=');
break;
@ -1123,7 +1210,8 @@ const Char *fmt::BasicFormatter<Char>::format(
// Parse width.
if ('0' <= *s && *s <= '9') {
spec.width_ = parse_nonnegative_int(s);
} else if (*s == '{') {
}
else if (*s == '{') {
++s;
Arg width_arg = is_name_start(*s) ?
parse_arg_name(s) : parse_arg_index(s);
@ -1161,7 +1249,8 @@ const Char *fmt::BasicFormatter<Char>::format(
spec.precision_ = 0;
if ('0' <= *s && *s <= '9') {
spec.precision_ = parse_nonnegative_int(s);
} else if (*s == '{') {
}
else if (*s == '{') {
++s;
Arg precision_arg =
is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s);
@ -1191,7 +1280,8 @@ const Char *fmt::BasicFormatter<Char>::format(
if (value > INT_MAX)
FMT_THROW(FormatError("number is too big"));
spec.precision_ = static_cast<int>(value);
} else {
}
else {
FMT_THROW(FormatError("missing precision specifier"));
}
if (arg.type <= Arg::LAST_INTEGER_TYPE || arg.type == Arg::POINTER) {
@ -1236,14 +1326,16 @@ void fmt::BasicFormatter<Char>::format(BasicCStringRef<Char> format_str) {
}
FMT_FUNC void fmt::report_system_error(
int error_code, fmt::StringRef message) FMT_NOEXCEPT {
report_error(internal::format_system_error, error_code, message);
int error_code, fmt::StringRef message) FMT_NOEXCEPT{
// 'fmt::' is for bcc32.
fmt::report_error(internal::format_system_error, error_code, message);
}
#if FMT_USE_WINDOWS_H
FMT_FUNC void fmt::report_windows_error(
int error_code, fmt::StringRef message) FMT_NOEXCEPT {
report_error(internal::format_windows_error, error_code, message);
int error_code, fmt::StringRef message) FMT_NOEXCEPT{
// 'fmt::' is for bcc32.
fmt::report_error(internal::format_windows_error, error_code, message);
}
#endif

File diff suppressed because it is too large Load Diff