diff --git a/fmt/format.cc b/fmt/format.cc index f5481fbb..de969dc8 100644 --- a/fmt/format.cc +++ b/fmt/format.cc @@ -83,7 +83,10 @@ static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) { namespace fmt { -FMT_FUNC internal::RuntimeError::~RuntimeError() FMT_DTOR_NOEXCEPT {} +namespace internal { +FMT_FUNC RuntimeError::~RuntimeError() FMT_DTOR_NOEXCEPT {} +} // namespace internal + FMT_FUNC FormatError::~FormatError() FMT_DTOR_NOEXCEPT {} FMT_FUNC SystemError::~SystemError() FMT_DTOR_NOEXCEPT {} @@ -231,8 +234,9 @@ FMT_FUNC void SystemError::init( base = std::runtime_error(w.str()); } +namespace internal { template -int internal::CharTraits::format_float( +int CharTraits::format_float( char *buffer, std::size_t size, const char *format, unsigned width, int precision, T value) { if (width == 0) { @@ -246,7 +250,7 @@ int internal::CharTraits::format_float( } template -int internal::CharTraits::format_float( +int CharTraits::format_float( wchar_t *buffer, std::size_t size, const wchar_t *format, unsigned width, int precision, T value) { if (width == 0) { @@ -260,7 +264,7 @@ int internal::CharTraits::format_float( } template -const char internal::BasicData::DIGITS[] = +const char BasicData::DIGITS[] = "0001020304050607080910111213141516171819" "2021222324252627282930313233343536373839" "4041424344454647484950515253545556575859" @@ -279,12 +283,12 @@ const char internal::BasicData::DIGITS[] = factor * 1000000000 template -const uint32_t internal::BasicData::POWERS_OF_10_32[] = { +const uint32_t BasicData::POWERS_OF_10_32[] = { 0, FMT_POWERS_OF_10(1) }; template -const uint64_t internal::BasicData::POWERS_OF_10_64[] = { +const uint64_t BasicData::POWERS_OF_10_64[] = { 0, FMT_POWERS_OF_10(1), FMT_POWERS_OF_10(ULongLong(1000000000)), @@ -293,7 +297,7 @@ const uint64_t internal::BasicData::POWERS_OF_10_64[] = { ULongLong(1000000000) * ULongLong(1000000000) * 10 }; -FMT_FUNC void internal::report_unknown_type(char code, const char *type) { +FMT_FUNC void report_unknown_type(char code, const char *type) { (void)type; if (std::isprint(static_cast(code))) { FMT_THROW(FormatError( @@ -306,7 +310,7 @@ FMT_FUNC void internal::report_unknown_type(char code, const char *type) { #if FMT_USE_WINDOWS_H -FMT_FUNC internal::UTF8ToUTF16::UTF8ToUTF16(StringRef s) { +FMT_FUNC UTF8ToUTF16::UTF8ToUTF16(StringRef s) { 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)); @@ -323,14 +327,14 @@ FMT_FUNC internal::UTF8ToUTF16::UTF8ToUTF16(StringRef s) { buffer_[length] = 0; } -FMT_FUNC internal::UTF16ToUTF8::UTF16ToUTF8(WStringRef s) { +FMT_FUNC UTF16ToUTF8::UTF16ToUTF8(WStringRef s) { if (int error_code = convert(s)) { FMT_THROW(WindowsError(error_code, "cannot convert string from UTF-16 to UTF-8")); } } -FMT_FUNC int internal::UTF16ToUTF8::convert(WStringRef s) { +FMT_FUNC int UTF16ToUTF8::convert(WStringRef s) { if (s.size() > INT_MAX) return ERROR_INVALID_PARAMETER; int s_size = static_cast(s.size()); @@ -346,6 +350,7 @@ FMT_FUNC int internal::UTF16ToUTF8::convert(WStringRef s) { buffer_[length] = 0; return 0; } +} // namespace internal FMT_FUNC void WindowsError::init( int err_code, CStringRef format_str, ArgList args) { @@ -356,7 +361,8 @@ FMT_FUNC void WindowsError::init( base = std::runtime_error(w.str()); } -FMT_FUNC void internal::format_windows_error( +namespace internal { +FMT_FUNC void format_windows_error( Writer &out, int error_code, StringRef message) FMT_NOEXCEPT { FMT_TRY { MemoryBuffer buffer; @@ -384,7 +390,7 @@ FMT_FUNC void internal::format_windows_error( } #endif // FMT_USE_WINDOWS_H - +} // namespace internal FMT_FUNC void format_system_error( Writer &out, int error_code, StringRef message) FMT_NOEXCEPT { FMT_TRY { @@ -404,38 +410,37 @@ FMT_FUNC void format_system_error( } FMT_CATCH(...) {} fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32. } +} // namespace fmt template -void internal::FixedBuffer::grow(std::size_t) { +void fmt::internal::FixedBuffer::grow(std::size_t) { FMT_THROW(std::runtime_error("buffer overflow")); } -FMT_FUNC internal::Arg internal::FormatterBase::do_get_arg( +FMT_FUNC fmt::internal::Arg fmt::internal::FormatterBase::do_get_arg( unsigned arg_index, const char *&error) { - internal::Arg arg = args_[arg_index]; + fmt::internal::Arg arg = args_[arg_index]; switch (arg.type) { - case internal::Arg::NONE: + case fmt::internal::Arg::NONE: error = "argument index out of range"; break; - case internal::Arg::NAMED_ARG: - arg = *static_cast(arg.pointer); + case fmt::internal::Arg::NAMED_ARG: + arg = *static_cast(arg.pointer); break; default: /*nothing*/; } return arg; } - +namespace fmt { FMT_FUNC void report_system_error( - int error_code, fmt::StringRef message) FMT_NOEXCEPT { - // 'fmt::' is for bcc32. + int error_code, StringRef message) FMT_NOEXCEPT { report_error(format_system_error, error_code, message); } #if FMT_USE_WINDOWS_H FMT_FUNC void report_windows_error( - int error_code, fmt::StringRef message) FMT_NOEXCEPT { - // 'fmt::' is for bcc32. + int error_code, StringRef message) FMT_NOEXCEPT { report_error(internal::format_windows_error, error_code, message); } #endif @@ -463,28 +468,29 @@ FMT_FUNC void print_colored(Color c, CStringRef format, ArgList args) { template struct internal::BasicData; // Explicit instantiations for char. +namespace internal { +template void FixedBuffer::grow(std::size_t); -template void internal::FixedBuffer::grow(std::size_t); - -template FMT_API int internal::CharTraits::format_float( +template FMT_API int CharTraits::format_float( char *buffer, std::size_t size, const char *format, unsigned width, int precision, double value); -template FMT_API int internal::CharTraits::format_float( +template FMT_API int CharTraits::format_float( char *buffer, std::size_t size, const char *format, unsigned width, int precision, long double value); // Explicit instantiations for wchar_t. -template void internal::FixedBuffer::grow(std::size_t); +template void FixedBuffer::grow(std::size_t); -template FMT_API int internal::CharTraits::format_float( +template FMT_API int CharTraits::format_float( wchar_t *buffer, std::size_t size, const wchar_t *format, unsigned width, int precision, double value); -template FMT_API int internal::CharTraits::format_float( +template FMT_API int CharTraits::format_float( wchar_t *buffer, std::size_t size, const wchar_t *format, unsigned width, int precision, long double value); +} //namespace internal #endif // FMT_HEADER_ONLY diff --git a/fmt/format.h b/fmt/format.h index fce1511b..22820265 100644 --- a/fmt/format.h +++ b/fmt/format.h @@ -130,6 +130,11 @@ typedef __int64 intmax_t; # define FMT_HAS_GXX_CXX11 0 #endif +#ifdef __BORLANDC__ +#pragma warn -8072 // disable "suspicious pointer arithmetic" warning on access of the digits array +#pragma warn -8004 // disable "assigned value that is never used" warning +#endif + #if defined(__INTEL_COMPILER) # define FMT_ICC_VERSION __INTEL_COMPILER #elif defined(__ICL) @@ -1328,6 +1333,7 @@ template struct LConvCheck { LConvCheck(int) {} }; +#ifndef __BORLANDC__ // Returns the thousands separator for the current locale. // We check if ``lconv`` contains ``thousands_sep`` because on Android // ``lconv`` is stubbed as an empty struct. @@ -1336,6 +1342,7 @@ inline StringRef thousands_sep( LConv *lc, LConvCheck = 0) { return lc->thousands_sep; } +#endif inline fmt::StringRef thousands_sep(...) { return ""; } @@ -2138,6 +2145,8 @@ class ArgFormatterBase : public ArgVisitor { // workaround MSVC two-phase lookup issue typedef internal::Arg Arg; + typedef Char CharType; + typedef BasicWriter WriterType; protected: BasicWriter &writer() { return writer_; } @@ -2182,8 +2191,8 @@ class ArgFormatterBase : public ArgVisitor { } if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0) FMT_THROW(FormatError("invalid format specifier for char")); - typedef typename BasicWriter::CharPtr CharPtr; - Char fill = internal::CharTraits::cast(spec_.fill()); + typedef typename WriterType::CharPtr CharPtr; + CharType fill = internal::CharTraits::cast(spec_.fill()); CharPtr out = CharPtr(); const unsigned CHAR_SIZE = 1; if (spec_.width_ > CHAR_SIZE) { @@ -2201,7 +2210,7 @@ class ArgFormatterBase : public ArgVisitor { } else { out = writer_.grow_buffer(CHAR_SIZE); } - *out = internal::CharTraits::cast(value); + *out = internal::CharTraits::cast(value); } void visit_cstring(const char *value) { @@ -2403,6 +2412,7 @@ inline uint64_t make_type(const T &arg) { return MakeValue< BasicFormatter >::type(arg); } +#ifndef __BORLANDC__ template struct ArgArray; @@ -2432,6 +2442,25 @@ struct ArgArray { template static Arg make(const T &value) { return MakeArg(value); } }; +#else +template +struct ArgArray { + typedef Value Type[N > 0 ? N : 1]; + + template + static Value make(const T & value) { +#ifdef __clang__ + Value result = MakeValue(value); + // Workaround a bug in Apple LLVM version 4.2 (clang-425.0.28) of clang: + // https://github.com/fmtlib/fmt/issues/276 + (void)result.custom.format; + return result; +#else + return MakeValue(value); +#endif + } +}; +#endif #if FMT_USE_VARIADIC_TEMPLATES template @@ -2469,74 +2498,6 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) { # define FMT_ASSIGN_wchar_t(n) \ arr[n] = fmt::internal::MakeValue< fmt::BasicFormatter >(v##n) -#if FMT_USE_VARIADIC_TEMPLATES -// Defines a variadic function returning void. -# define FMT_VARIADIC_VOID(func, arg_type) \ - template \ - void func(arg_type arg0, const Args & ... args) { \ - typedef fmt::internal::ArgArray ArgArray; \ - typename ArgArray::Type array{ \ - ArgArray::template make >(args)...}; \ - func(arg0, fmt::ArgList(fmt::internal::make_type(args...), array)); \ - } - -// Defines a variadic constructor. -# define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \ - template \ - ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \ - typedef fmt::internal::ArgArray ArgArray; \ - typename ArgArray::Type array{ \ - ArgArray::template make >(args)...}; \ - func(arg0, arg1, fmt::ArgList(fmt::internal::make_type(args...), array)); \ - } - -#else - -# define FMT_MAKE_REF(n) \ - fmt::internal::MakeValue< fmt::BasicFormatter >(v##n) -# define FMT_MAKE_REF2(n) v##n - -// Defines a wrapper for a function taking one argument of type arg_type -// and n additional arguments of arbitrary types. -# define FMT_WRAP1(func, arg_type, n) \ - template \ - inline void func(arg_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \ - const fmt::internal::ArgArray::Type array = {FMT_GEN(n, FMT_MAKE_REF)}; \ - func(arg1, fmt::ArgList( \ - fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), array)); \ - } - -// Emulates a variadic function returning void on a pre-C++11 compiler. -# define FMT_VARIADIC_VOID(func, arg_type) \ - inline void func(arg_type arg) { func(arg, fmt::ArgList()); } \ - FMT_WRAP1(func, arg_type, 1) FMT_WRAP1(func, arg_type, 2) \ - FMT_WRAP1(func, arg_type, 3) FMT_WRAP1(func, arg_type, 4) \ - FMT_WRAP1(func, arg_type, 5) FMT_WRAP1(func, arg_type, 6) \ - FMT_WRAP1(func, arg_type, 7) FMT_WRAP1(func, arg_type, 8) \ - FMT_WRAP1(func, arg_type, 9) FMT_WRAP1(func, arg_type, 10) - -# define FMT_CTOR(ctor, func, arg0_type, arg1_type, n) \ - template \ - ctor(arg0_type arg0, arg1_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \ - const fmt::internal::ArgArray::Type array = {FMT_GEN(n, FMT_MAKE_REF)}; \ - func(arg0, arg1, fmt::ArgList( \ - fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), array)); \ - } - -// Emulates a variadic constructor on a pre-C++11 compiler. -# define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 1) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 2) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 3) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 4) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 5) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 6) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 7) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 8) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 9) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 10) -#endif - // Generates a comma-separated list with results of applying f to pairs // (argument, index). #define FMT_FOR_EACH1(f, x0) f(x0, 0) @@ -2559,6 +2520,147 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) { #define FMT_FOR_EACH10(f, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) \ FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8), f(x9, 9) +// This is used to work around VC++ bugs in handling variadic macros. +#define FMT_EXPAND(args) args + +// Returns the number of arguments. +// Based on https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s. +#define FMT_NARG(...) FMT_NARG_(__VA_ARGS__, FMT_RSEQ_N()) +#define FMT_NARG_(...) FMT_EXPAND(FMT_ARG_N(__VA_ARGS__)) +#define FMT_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N +#define FMT_RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 + +#define FMT_FOR_EACH_(N, f, ...) \ + FMT_EXPAND(FMT_CONCAT(FMT_FOR_EACH, N)(f, __VA_ARGS__)) +#define FMT_FOR_EACH(f, ...) \ + FMT_EXPAND(FMT_FOR_EACH_(FMT_NARG(__VA_ARGS__), f, __VA_ARGS__)) + +#define FMT_ADD_ARG_NAME(type, index) type arg##index +#define FMT_GET_ARG_NAME(type, index) arg##index + +#if FMT_USE_VARIADIC_TEMPLATES +# define FMT_VARIADIC_(Const, Char, ReturnType, func, call, ...) \ + template \ + ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \ + const Args & ... args) Const { \ + typedef fmt::internal::ArgArray ArgArray; \ + typename ArgArray::Type array{ \ + ArgArray::template make >(args)...}; \ + call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \ + fmt::ArgList(fmt::internal::make_type(args...), array)); \ + } +# define FMT_VARIADIC_VAR_ARG(Const, Char, ReturnType, func, call, ...) \ + FMT_VARIADIC_(Const, Char, ReturnType, func, call, __VA_ARGS__) + +#else +# define FMT_MAKE_REF(n) \ + fmt::internal::MakeValue< fmt::BasicFormatter >(v##n) +# define FMT_MAKE_REF2(n) v##n +// Defines a wrapper for a function taking __VA_ARGS__ arguments +// and n additional arguments of arbitrary types. +# define FMT_WRAP(Const, Char, ReturnType, func, call, n, ...) \ + template \ + inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \ + FMT_GEN(n, FMT_MAKE_ARG)) Const { \ + fmt::internal::ArgArray::Type arr; \ + FMT_GEN(n, FMT_ASSIGN_##Char); \ + call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList( \ + fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), arr)); \ + } +# define FMT_VARIADIC_ZERO_ARG(Const, Char, ReturnType, func, call, ...) \ + inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) Const { \ + call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList()); \ + } +# define FMT_VARIADIC_VAR_ARG(Const, Char, ReturnType, func, call, ...)\ + FMT_WRAP(Const, Char, ReturnType, func, call, 1, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 2, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 3, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 4, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 5, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 6, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 7, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 8, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 9, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 10, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 11, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 12, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 13, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 14, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 15, __VA_ARGS__) + +# define FMT_VARIADIC_(Const, Char, ReturnType, func, call, ...) \ + FMT_VARIADIC_ZERO_ARG(Const, Char, ReturnType, func, call, __VA_ARGS__) \ + FMT_VARIADIC_VAR_ARG(Const, Char, ReturnType, func, call, __VA_ARGS__) + +#endif // FMT_USE_VARIADIC_TEMPLATES + +/** + \rst + Defines a variadic function with the specified return type, function name + and argument types passed as variable arguments to this macro. + + **Example**:: + + void print_error(const char *file, int line, const char *format, + fmt::ArgList args) { + fmt::print("{}: {}: ", file, line); + fmt::print(format, args); + } + FMT_VARIADIC(void, print_error, const char *, int, const char *) + + ``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 + you don't need legacy compiler support and can use variadic templates + directly:: + + template + void print_error(const char *file, int line, const char *format, + const Args & ... args) { + fmt::print("{}: {}: ", file, line); + fmt::print(format, args...); + } + \endrst + */ +#define FMT_VARIADIC(ReturnType, func, ...) \ + FMT_VARIADIC_(, char, ReturnType, func, return func, __VA_ARGS__) + +#define FMT_VARIADIC_CONST(ReturnType, func, ...) \ + FMT_VARIADIC_(const, char, ReturnType, func, return func, __VA_ARGS__) + +#define FMT_VARIADIC_W(ReturnType, func, ...) \ + FMT_VARIADIC_(, wchar_t, ReturnType, func, return func, __VA_ARGS__) + +#define FMT_VARIADIC_CONST_W(ReturnType, func, ...) \ + FMT_VARIADIC_(const, wchar_t, ReturnType, func, return func, __VA_ARGS__) + +#define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \ + FMT_VARIADIC_VAR_ARG(, char, , ctor, func, arg0_type, arg1_type) + +#define FMT_VARIADIC_VOID(func, arg_type) \ + FMT_VARIADIC(void,func, arg_type) + +#define FMT_CAPTURE_ARG_(id, index) ::fmt::arg(#id, id) + +#define FMT_CAPTURE_ARG_W_(id, index) ::fmt::arg(L## #id, id) + +/** + \rst + Convenient macro to capture the arguments' names and values into several + ``fmt::arg(name, value)``. + + **Example**:: + + int x = 1, y = 2; + print("point: ({x}, {y})", FMT_CAPTURE(x, y)); + // same as: + // print("point: ({x}, {y})", arg("x", x), arg("y", y)); + + \endrst + */ +#define FMT_CAPTURE(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_, __VA_ARGS__) + +#define FMT_CAPTURE_W(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_W_, __VA_ARGS__) + /** An error returned by an operating system or a language runtime, for example a file opening error. @@ -3653,130 +3755,6 @@ void arg(WStringRef, const internal::NamedArg&) FMT_DELETED_OR_UNDEFINED; # pragma GCC system_header #endif -// This is used to work around VC++ bugs in handling variadic macros. -#define FMT_EXPAND(args) args - -// Returns the number of arguments. -// Based on https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s. -#define FMT_NARG(...) FMT_NARG_(__VA_ARGS__, FMT_RSEQ_N()) -#define FMT_NARG_(...) FMT_EXPAND(FMT_ARG_N(__VA_ARGS__)) -#define FMT_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N -#define FMT_RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 - -#define FMT_FOR_EACH_(N, f, ...) \ - FMT_EXPAND(FMT_CONCAT(FMT_FOR_EACH, N)(f, __VA_ARGS__)) -#define FMT_FOR_EACH(f, ...) \ - FMT_EXPAND(FMT_FOR_EACH_(FMT_NARG(__VA_ARGS__), f, __VA_ARGS__)) - -#define FMT_ADD_ARG_NAME(type, index) type arg##index -#define FMT_GET_ARG_NAME(type, index) arg##index - -#if FMT_USE_VARIADIC_TEMPLATES -# define FMT_VARIADIC_(Const, Char, ReturnType, func, call, ...) \ - template \ - ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \ - const Args & ... args) Const { \ - typedef fmt::internal::ArgArray ArgArray; \ - typename ArgArray::Type array{ \ - ArgArray::template make >(args)...}; \ - call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \ - fmt::ArgList(fmt::internal::make_type(args...), array)); \ - } -#else -// Defines a wrapper for a function taking __VA_ARGS__ arguments -// and n additional arguments of arbitrary types. -# define FMT_WRAP(Const, Char, ReturnType, func, call, n, ...) \ - template \ - inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \ - FMT_GEN(n, FMT_MAKE_ARG)) Const { \ - fmt::internal::ArgArray::Type arr; \ - FMT_GEN(n, FMT_ASSIGN_##Char); \ - call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList( \ - fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), arr)); \ - } - -# define FMT_VARIADIC_(Const, Char, ReturnType, func, call, ...) \ - inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) Const { \ - call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList()); \ - } \ - FMT_WRAP(Const, Char, ReturnType, func, call, 1, __VA_ARGS__) \ - FMT_WRAP(Const, Char, ReturnType, func, call, 2, __VA_ARGS__) \ - FMT_WRAP(Const, Char, ReturnType, func, call, 3, __VA_ARGS__) \ - FMT_WRAP(Const, Char, ReturnType, func, call, 4, __VA_ARGS__) \ - FMT_WRAP(Const, Char, ReturnType, func, call, 5, __VA_ARGS__) \ - FMT_WRAP(Const, Char, ReturnType, func, call, 6, __VA_ARGS__) \ - FMT_WRAP(Const, Char, ReturnType, func, call, 7, __VA_ARGS__) \ - FMT_WRAP(Const, Char, ReturnType, func, call, 8, __VA_ARGS__) \ - FMT_WRAP(Const, Char, ReturnType, func, call, 9, __VA_ARGS__) \ - FMT_WRAP(Const, Char, ReturnType, func, call, 10, __VA_ARGS__) \ - FMT_WRAP(Const, Char, ReturnType, func, call, 11, __VA_ARGS__) \ - FMT_WRAP(Const, Char, ReturnType, func, call, 12, __VA_ARGS__) \ - FMT_WRAP(Const, Char, ReturnType, func, call, 13, __VA_ARGS__) \ - FMT_WRAP(Const, Char, ReturnType, func, call, 14, __VA_ARGS__) \ - FMT_WRAP(Const, Char, ReturnType, func, call, 15, __VA_ARGS__) -#endif // FMT_USE_VARIADIC_TEMPLATES - -/** - \rst - Defines a variadic function with the specified return type, function name - and argument types passed as variable arguments to this macro. - - **Example**:: - - void print_error(const char *file, int line, const char *format, - fmt::ArgList args) { - fmt::print("{}: {}: ", file, line); - fmt::print(format, args); - } - FMT_VARIADIC(void, print_error, const char *, int, const char *) - - ``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 - you don't need legacy compiler support and can use variadic templates - directly:: - - template - void print_error(const char *file, int line, const char *format, - const Args & ... args) { - fmt::print("{}: {}: ", file, line); - fmt::print(format, args...); - } - \endrst - */ -#define FMT_VARIADIC(ReturnType, func, ...) \ - FMT_VARIADIC_(, char, ReturnType, func, return func, __VA_ARGS__) - -#define FMT_VARIADIC_CONST(ReturnType, func, ...) \ - FMT_VARIADIC_(const, char, ReturnType, func, return func, __VA_ARGS__) - -#define FMT_VARIADIC_W(ReturnType, func, ...) \ - FMT_VARIADIC_(, wchar_t, ReturnType, func, return func, __VA_ARGS__) - -#define FMT_VARIADIC_CONST_W(ReturnType, func, ...) \ - FMT_VARIADIC_(const, wchar_t, ReturnType, func, return func, __VA_ARGS__) - -#define FMT_CAPTURE_ARG_(id, index) ::fmt::arg(#id, id) - -#define FMT_CAPTURE_ARG_W_(id, index) ::fmt::arg(L###id, id) - -/** - \rst - Convenient macro to capture the arguments' names and values into several - ``fmt::arg(name, value)``. - - **Example**:: - - int x = 1, y = 2; - print("point: ({x}, {y})", FMT_CAPTURE(x, y)); - // same as: - // print("point: ({x}, {y})", arg("x", x), arg("y", y)); - - \endrst - */ -#define FMT_CAPTURE(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_, __VA_ARGS__) - -#define FMT_CAPTURE_W(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_W_, __VA_ARGS__) - namespace fmt { FMT_VARIADIC(std::string, format, CStringRef) FMT_VARIADIC_W(std::wstring, format, WCStringRef) @@ -4213,4 +4191,9 @@ operator"" _a(const wchar_t *s, std::size_t) { return {s}; } # define FMT_FUNC #endif +#ifdef __BORLANDC__ +#pragma warn .8072 // restore "suspicious pointer arithmetic" warning on access of the digits array +#pragma warn .8004 // restore "assigned value that is never used" warning +#endif + #endif // FMT_FORMAT_H_ diff --git a/fmt/posix.cc b/fmt/posix.cc index 356668c1..e7b57769 100644 --- a/fmt/posix.cc +++ b/fmt/posix.cc @@ -26,10 +26,13 @@ # endif # include # include - -# define O_CREAT _O_CREAT -# define O_TRUNC _O_TRUNC - +#include +# ifndef O_CREAT +# define O_CREAT _O_CREAT +# endif +# ifndef O_TRUNC +# define O_TRUNC _O_TRUNC +# endif # ifndef S_IRUSR # define S_IRUSR _S_IREAD # endif @@ -56,7 +59,7 @@ typedef int RWResult; // On Windows the count argument to read and write is unsigned, so convert // it from size_t preventing integer overflow. inline unsigned convert_rwcount(std::size_t count) { - return count <= UINT_MAX ? static_cast(count) : UINT_MAX; + return static_cast(std::min(count, UINT_MAX)); } #else // Return type of read and write functions. @@ -99,7 +102,7 @@ int fmt::BufferedFile::fileno() const { fmt::File::File(fmt::CStringRef path, int oflag) { int mode = S_IRUSR | S_IWUSR; -#if defined(_WIN32) && !defined(__MINGW32__) +#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__BORLANDC__) fd_ = -1; FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode)); #else diff --git a/fmt/posix.h b/fmt/posix.h index 88512de5..c3ce964a 100644 --- a/fmt/posix.h +++ b/fmt/posix.h @@ -46,6 +46,10 @@ # ifdef _WIN32 // Fix warnings about deprecated symbols. # define FMT_POSIX_CALL(call) ::_##call +# if defined(__BORLANDC__) && !defined(_dup2) +// for some reason the borland headers do define _dup but not _dup2 +# define _dup2 dup2 +# endif # else # define FMT_POSIX_CALL(call) ::call # endif diff --git a/fmt/printf.h b/fmt/printf.h index 46205a78..736d9d39 100644 --- a/fmt/printf.h +++ b/fmt/printf.h @@ -333,7 +333,7 @@ class PrintfFormatter : private internal::FormatterBase { \endrst */ explicit PrintfFormatter(const ArgList &al, BasicWriter &w) - : FormatterBase(al), writer_(w) {} + : internal::FormatterBase(al), writer_(w) {} /** Formats stored arguments and writes the output to the writer. */ void format(BasicCStringRef format_str); @@ -371,7 +371,7 @@ internal::Arg PrintfFormatter::get_arg(const Char *s, (void)s; const char *error = FMT_NULL; internal::Arg arg = arg_index == std::numeric_limits::max() ? - next_arg(error) : FormatterBase::get_arg(arg_index - 1, error); + next_arg(error) : internal::FormatterBase::get_arg(arg_index - 1, error); if (error) FMT_THROW(FormatError(!*s ? "invalid format string" : error)); return arg; diff --git a/support/appveyor-build.py b/support/appveyor-build.py index 3b747f3c..a5dbbb3e 100755 --- a/support/appveyor-build.py +++ b/support/appveyor-build.py @@ -8,7 +8,7 @@ build = os.environ['BUILD'] config = os.environ['CONFIGURATION'] platform = os.environ.get('PLATFORM') path = os.environ['PATH'] -cmake_command = ['cmake', '-DFMT_PEDANTIC=ON', '-DCMAKE_BUILD_TYPE=' + config] +cmake_command = ['cmake', '-DFMT_PEDANTIC=ON', '-DCMAKE_BUILD_TYPE=' + config, '.'] if build == 'mingw': cmake_command.append('-GMinGW Makefiles') build_command = ['mingw32-make', '-j4'] diff --git a/test/macro-test.cc b/test/macro-test.cc index f6763eae..ea2fbfd6 100644 --- a/test/macro-test.cc +++ b/test/macro-test.cc @@ -76,13 +76,6 @@ int result; MAKE_TEST(test_func) typedef char Char; -FMT_WRAP1(test_func, const char *, 1) - -TEST(UtilTest, Wrap1) { - result = 0; - test_func("", 42); - EXPECT_EQ(42, result); -} MAKE_TEST(test_variadic_void) FMT_VARIADIC_VOID(test_variadic_void, const char *)