Dep/CppFormat: Update cppformat to cppformat/cppformat@5174b8c

This commit is contained in:
Naios
2016-03-12 14:30:11 +01:00
parent 912514c198
commit f52495c66b
12 changed files with 463 additions and 300 deletions

View File

@@ -14,7 +14,7 @@ bzip2 (a freely available, patent free, high-quality data compressor)
cppformat (type safe format library)
https://github.com/cppformat/cppformat
Version: 5c76d107cbaf5e851bd66b6c563e4fc7c90be7ad
Version: 5174b8ca281426af604b85fdf53be8a748b33f56
G3D (a commercial-grade C++ 3D engine available as Open Source (BSD License)
http://g3d.sourceforge.net/

View File

@@ -1,7 +1,7 @@
include(CheckCXXCompilerFlag)
include(CheckSymbolExists)
set(FMT_SOURCES format.cc format.h)
set(FMT_SOURCES cppformat/format.cc cppformat/format.h)
# Use variadic templates
add_definitions(-DFMT_VARIADIC_TEMPLATES=1)
@@ -20,10 +20,10 @@ endif ()
if (HAVE_OPEN)
add_definitions(-DFMT_USE_FILE_DESCRIPTORS=1)
set(FMT_SOURCES ${FMT_SOURCES} posix.cc posix.h)
set(FMT_SOURCES ${FMT_SOURCES} cppformat/posix.cc cppformat/posix.h)
endif ()
add_library(format STATIC ${FMT_SOURCES})
add_library(cppformat STATIC ${FMT_SOURCES})
if (CMAKE_COMPILER_IS_GNUCXX)
set_target_properties(format PROPERTIES COMPILE_FLAGS

View File

@@ -28,9 +28,9 @@ Features
* Format API with `format string syntax
<http://cppformat.github.io/latest/syntax.html>`_
similar to the one used by `str.format
<http://docs.python.org/2/library/stdtypes.html#str.format>`_ in Python.
<https://docs.python.org/2/library/stdtypes.html#str.format>`_ in Python.
* Safe `printf implementation
<http://cppformat.github.io/latest/reference.html#printf-formatting-functions>`_
<http://cppformat.github.io/latest/api.html#printf-formatting-functions>`_
including the POSIX extension for positional arguments.
* Support for user-defined types.
* High speed: performance of the format API is close to that of
@@ -103,10 +103,10 @@ An object of any user-defined type for which there is an overloaded
// s == "The date is 2012-12-9"
You can use the `FMT_VARIADIC
<http://cppformat.github.io/latest/reference.html#utilities>`_
<http://cppformat.github.io/latest/api.html#utilities>`_
macro to create your own functions similar to `format
<http://cppformat.github.io/latest/reference.html#format>`_ and
`print <http://cppformat.github.io/latest/reference.html#print>`_
<http://cppformat.github.io/latest/api.html#format>`_ and
`print <http://cppformat.github.io/latest/api.html#print>`_
which take arbitrary arguments:
.. code:: c++
@@ -132,13 +132,17 @@ Projects using this library
* `AMPL/MP <https://github.com/ampl/mp>`_:
An open-source library for mathematical programming
* `HarpyWar/pvpgn <https://github.com/HarpyWar/pvpgn>`_:
* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_:
Player vs Player Gaming Network with tweaks
* `KBEngine <http://www.kbengine.org/>`_: An open-source MMOG server engine
* `KBEngine <http://kbengine.org/>`_: An open-source MMOG server engine
* `Keypirinha <http://keypirinha.com/>`_: A semantic launcher for Windows
* `Lifeline <https://github.com/peter-clark/lifeline>`_: A 2D game
* `MongoDB Smasher <https://github.com/duckie/mongo_smasher>`_: A small tool to generate randomized datasets
* `PenUltima Online (POL) <http://www.polserver.com/>`_:
An MMO server, compatible with most Ultima Online clients
@@ -148,7 +152,7 @@ Projects using this library
* `redis-cerberus <https://github.com/HunanTV/redis-cerberus>`_: A Redis cluster proxy
* `Saddy <https://code.google.com/p/saddy/>`_:
* `Saddy <https://github.com/mamontov-cpp/saddy-graphics-engine-2d>`_:
Small crossplatform 2D graphic engine
* `Salesforce Analytics Cloud <http://www.salesforce.com/analytics-cloud/overview/>`_:
@@ -188,7 +192,7 @@ doesn't support user-defined types. Printf also has safety issues although
they are mostly solved with `__attribute__ ((format (printf, ...))
<http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_ in GCC.
There is a POSIX extension that adds positional arguments required for
`i18n <http://en.wikipedia.org/wiki/Internationalization_and_localization>`_
`i18n <https://en.wikipedia.org/wiki/Internationalization_and_localization>`_
to printf but it is not a part of C99 and may not be available on some
platforms.
@@ -376,18 +380,13 @@ C++ Format is distributed under the BSD `license
The `Format String Syntax
<http://cppformat.github.io/latest/syntax.html>`_
section in the documentation is based on the one from Python `string module
documentation <http://docs.python.org/3/library/string.html#module-string>`_
documentation <https://docs.python.org/3/library/string.html#module-string>`_
adapted for the current library. For this reason the documentation is
distributed under the Python Software Foundation license available in
`doc/python-license.txt
<https://raw.github.com/cppformat/cppformat/master/doc/python-license.txt>`_.
It only applies if you distribute the documentation of C++ Format.
Links
-----
`API changes/compatibility report <http://upstream-tracker.org/versions/cppformat.html>`_
Acknowledgments
---------------

View File

@@ -207,10 +207,15 @@ void format_error_code(fmt::Writer &out, int error_code,
out.clear();
static const char SEP[] = ": ";
static const char ERROR_STR[] = "error ";
fmt::internal::IntTraits<int>::MainType ec_value = error_code;
// Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
error_code_size += fmt::internal::count_digits(ec_value);
typedef fmt::internal::IntTraits<int>::MainType MainType;
MainType abs_value = static_cast<MainType>(error_code);
if (internal::is_negative(error_code)) {
abs_value = 0 - abs_value;
++error_code_size;
}
error_code_size += fmt::internal::count_digits(abs_value);
if (message.size() <= fmt::internal::INLINE_BUFFER_SIZE - error_code_size)
out << message << SEP;
out << ERROR_STR << error_code;
@@ -252,7 +257,7 @@ class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
template <typename T>
unsigned visit_any_int(T value) {
typedef typename fmt::internal::IntTraits<T>::MainType UnsignedType;
UnsignedType width = value;
UnsignedType width = static_cast<UnsignedType>(value);
if (fmt::internal::is_negative(value)) {
spec_.align_ = fmt::ALIGN_LEFT;
width = 0 - width;
@@ -278,8 +283,21 @@ class PrecisionHandler :
}
};
// Converts an integer argument to an integral type T for printf.
template <typename T, typename U>
struct is_same {
enum { value = 0 };
};
template <typename T>
struct is_same<T, T> {
enum { value = 1 };
};
// An argument visitor that converts an integer argument to T for printf,
// if T is an integral type. If T is void, the argument is converted to
// corresponding signed or unsigned type depending on the type specifier:
// 'd' and 'i' - signed, other - unsigned)
template <typename T = void>
class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
private:
fmt::internal::Arg &arg_;
@@ -300,21 +318,25 @@ class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
void visit_any_int(U value) {
bool is_signed = type_ == 'd' || type_ == 'i';
using fmt::internal::Arg;
if (sizeof(T) <= sizeof(int)) {
typedef typename fmt::internal::Conditional<
is_same<T, void>::value, U, T>::type TargetType;
if (sizeof(TargetType) <= sizeof(int)) {
// Extra casts are used to silence warnings.
if (is_signed) {
arg_.type = Arg::INT;
arg_.int_value = static_cast<int>(static_cast<T>(value));
arg_.int_value = static_cast<int>(static_cast<TargetType>(value));
} else {
arg_.type = Arg::UINT;
arg_.uint_value = static_cast<unsigned>(
static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value));
typedef typename fmt::internal::MakeUnsigned<TargetType>::Type Unsigned;
arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value));
}
} else {
if (is_signed) {
arg_.type = Arg::LONG_LONG;
arg_.long_long_value =
static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
// glibc's printf doesn't sign extend arguments of smaller types:
// std::printf("%lld", -42); // prints "4294967254"
// but we don't have to do the same because it's a UB.
arg_.long_long_value = static_cast<fmt::LongLong>(value);
} else {
arg_.type = Arg::ULONG_LONG;
arg_.ulong_long_value =
@@ -340,6 +362,21 @@ class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
arg_.int_value = static_cast<char>(value);
}
};
// Write the content of w to os.
void write(std::ostream &os, fmt::Writer &w) {
const char *data = w.data();
typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize;
UnsignedStreamSize size = w.size();
UnsignedStreamSize max_size =
internal::to_unsigned((std::numeric_limits<std::streamsize>::max)());
do {
UnsignedStreamSize n = size <= max_size ? size : max_size;
os.write(data, static_cast<std::streamsize>(n));
data += n;
size -= n;
} while (size != 0);
}
} // namespace
namespace internal {
@@ -551,27 +588,25 @@ 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 {
class String {
private:
LPWSTR str_;
public:
String() : str_() {}
~String() { LocalFree(str_); }
LPWSTR *ptr() { return &str_; }
LPCWSTR c_str() const { return str_; }
};
FMT_TRY {
String system_message;
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) {
UTF16ToUTF8 utf8_message;
if (utf8_message.convert(system_message.c_str()) == ERROR_SUCCESS) {
out << message << ": " << utf8_message;
return;
MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer;
buffer.resize(INLINE_BUFFER_SIZE);
for (;;) {
wchar_t *system_message = &buffer[0];
int result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
system_message, static_cast<uint32_t>(buffer.size()), 0);
if (result != 0) {
UTF16ToUTF8 utf8_message;
if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
out << message << ": " << utf8_message;
return;
}
break;
}
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
break; // Can't get error message, report error code instead.
buffer.resize(buffer.size() * 2);
}
} FMT_CATCH(...) {}
fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
@@ -616,7 +651,7 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
return;
case internal::Arg::NAMED_ARG:
named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
map_.insert(Pair(named_arg->name, *named_arg));
map_.push_back(Pair(named_arg->name, *named_arg));
break;
default:
/*nothing*/;
@@ -628,7 +663,7 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
internal::Arg::Type arg_type = args.type(i);
if (arg_type == internal::Arg::NAMED_ARG) {
named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
map_.insert(Pair(named_arg->name, *named_arg));
map_.push_back(Pair(named_arg->name, *named_arg));
}
}
for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
@@ -637,7 +672,7 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
return;
case internal::Arg::NAMED_ARG:
named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
map_.insert(Pair(named_arg->name, *named_arg));
map_.push_back(Pair(named_arg->name, *named_arg));
break;
default:
/*nothing*/;
@@ -659,6 +694,7 @@ FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
break;
case Arg::NAMED_ARG:
arg = *static_cast<const internal::Arg*>(arg.pointer);
break;
default:
/*nothing*/;
}
@@ -763,7 +799,7 @@ void fmt::internal::PrintfFormatter<Char>::format(
if (*s == '.') {
++s;
if ('0' <= *s && *s <= '9') {
spec.precision_ = parse_nonnegative_int(s);
spec.precision_ = static_cast<int>(parse_nonnegative_int(s));
} else if (*s == '*') {
++s;
spec.precision_ = PrecisionHandler().visit(get_arg(s));
@@ -772,7 +808,7 @@ void fmt::internal::PrintfFormatter<Char>::format(
Arg arg = get_arg(s, arg_index);
if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
spec.flags_ &= ~HASH_FLAG;
spec.flags_ &= ~to_unsigned<int>(HASH_FLAG);
if (spec.fill_ == '0') {
if (arg.type <= Arg::LAST_NUMERIC_TYPE)
spec.align_ = ALIGN_NUMERIC;
@@ -809,7 +845,7 @@ void fmt::internal::PrintfFormatter<Char>::format(
break;
default:
--s;
ArgConverter<int>(arg, *s).visit(arg);
ArgConverter<void>(arg, *s).visit(arg);
}
// Parse type.
@@ -861,10 +897,11 @@ FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) {
print(stdout, format_str, args);
}
FMT_FUNC void fmt::print(std::ostream &os, CStringRef format_str, ArgList args) {
FMT_FUNC void fmt::print(std::ostream &os, CStringRef format_str,
ArgList args) {
MemoryWriter w;
w.write(format_str, args);
os.write(w.data(), w.size());
write(os, w);
}
FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) {
@@ -882,6 +919,13 @@ FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) {
return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
}
FMT_FUNC int fmt::fprintf(std::ostream &os, CStringRef format, ArgList args) {
MemoryWriter w;
printf(w, format, args);
write(os, w);
return static_cast<int>(w.size());
}
#ifndef FMT_HEADER_ONLY
template struct fmt::internal::BasicData<void>;

View File

@@ -28,14 +28,6 @@
#ifndef FMT_FORMAT_H_
#define FMT_FORMAT_H_
#if defined _MSC_VER && _MSC_VER <= 1500
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef long long intmax_t;
#else
#include <stdint.h>
#endif
#include <cassert>
#include <cmath>
#include <cstdio>
@@ -44,7 +36,8 @@ typedef long long intmax_t;
#include <memory>
#include <stdexcept>
#include <string>
#include <map>
#include <vector>
#include <utility>
#ifndef FMT_USE_IOSTREAMS
# define FMT_USE_IOSTREAMS 1
@@ -64,40 +57,23 @@ typedef long long intmax_t;
# include <iterator>
#endif
#ifdef _MSC_VER
# include <intrin.h> // _BitScanReverse, _BitScanReverse64
#if defined(_MSC_VER) && _MSC_VER <= 1500
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
typedef __int64 intmax_t;
#else
#include <stdint.h>
#endif
namespace fmt {
namespace internal {
# pragma intrinsic(_BitScanReverse)
inline uint32_t clz(uint32_t x) {
unsigned long r = 0;
_BitScanReverse(&r, x);
return 31 - r;
}
# define FMT_BUILTIN_CLZ(n) fmt::internal::clz(n)
# ifdef _WIN64
# pragma intrinsic(_BitScanReverse64)
#if !defined(FMT_HEADER_ONLY) && defined(_WIN32)
# ifdef FMT_EXPORT
# define FMT_API __declspec(dllexport)
# elif defined(FMT_SHARED)
# define FMT_API __declspec(dllimport)
# endif
inline uint32_t clzll(uint64_t x) {
unsigned long r = 0;
# ifdef _WIN64
_BitScanReverse64(&r, x);
# else
// Scan the high 32 bits.
if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))
return 63 - (r + 32);
// Scan the low 32 bits.
_BitScanReverse(&r, static_cast<uint32_t>(x));
# endif
return 63 - r;
}
# define FMT_BUILTIN_CLZLL(n) fmt::internal::clzll(n)
}
}
#endif
#ifndef FMT_API
# define FMT_API
#endif
#ifdef __GNUC__
@@ -174,21 +150,6 @@ inline uint32_t clzll(uint64_t x) {
# include <utility> // for std::move
#endif
// Define FMT_USE_NOEXCEPT to make C++ Format use noexcept (C++11 feature).
#ifndef FMT_USE_NOEXCEPT
# define FMT_USE_NOEXCEPT 0
#endif
#ifndef FMT_NOEXCEPT
# if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
_MSC_VER >= 1900
# define FMT_NOEXCEPT noexcept
# else
# define FMT_NOEXCEPT throw()
# endif
#endif
// Check if exceptions are disabled.
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
# define FMT_EXCEPTIONS 0
@@ -208,6 +169,25 @@ inline uint32_t clzll(uint64_t x) {
# endif
#endif
// Define FMT_USE_NOEXCEPT to make C++ Format use noexcept (C++11 feature).
#ifndef FMT_USE_NOEXCEPT
# define FMT_USE_NOEXCEPT 0
#endif
#ifndef FMT_NOEXCEPT
# if FMT_EXCEPTIONS
# if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
_MSC_VER >= 1900
# define FMT_NOEXCEPT noexcept
# else
# define FMT_NOEXCEPT throw()
# endif
# else
# define FMT_NOEXCEPT
# endif
#endif
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
#ifndef FMT_USE_DELETED_FUNCTIONS
@@ -241,6 +221,67 @@ inline uint32_t clzll(uint64_t x) {
# define FMT_ASSERT(condition, message) assert((condition) && message)
#endif
#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz)
# define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
#endif
#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll)
# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
#endif
// Some compilers masquerade as both MSVC and GCC-likes or
// otherwise support __builtin_clz and __builtin_clzll, so
// only define FMT_BUILTIN_CLZ using the MSVC intrinsics
// if the clz and clzll builtins are not available.
#if defined(_MSC_VER) && !defined(FMT_BUILTIN_CLZLL)
# include <intrin.h> // _BitScanReverse, _BitScanReverse64
namespace fmt {
namespace internal {
# pragma intrinsic(_BitScanReverse)
inline uint32_t clz(uint32_t x) {
unsigned long r = 0;
_BitScanReverse(&r, x);
assert(x != 0);
// Static analysis complains about using uninitialized data
// "r", but the only way that can happen is if "x" is 0,
// which the callers guarantee to not happen.
# pragma warning(suppress: 6102)
return 31 - r;
}
# define FMT_BUILTIN_CLZ(n) fmt::internal::clz(n)
# ifdef _WIN64
# pragma intrinsic(_BitScanReverse64)
# endif
inline uint32_t clzll(uint64_t x) {
unsigned long r = 0;
# ifdef _WIN64
_BitScanReverse64(&r, x);
# else
// Scan the high 32 bits.
if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))
return 63 - (r + 32);
// Scan the low 32 bits.
_BitScanReverse(&r, static_cast<uint32_t>(x));
# endif
assert(x != 0);
// Static analysis complains about using uninitialized data
// "r", but the only way that can happen is if "x" is 0,
// which the callers guarantee to not happen.
# pragma warning(suppress: 6102)
return 63 - r;
}
# define FMT_BUILTIN_CLZLL(n) fmt::internal::clzll(n)
}
}
#endif
namespace fmt {
namespace internal {
struct DummyInt {
@@ -396,7 +437,7 @@ class BasicStringRef {
return std::basic_string<Char>(data_, size_);
}
/** Returns the pointer to a C string. */
/** Returns a pointer to the string data. */
const Char *data() const { return data_; }
/** Returns the string size. */
@@ -492,6 +533,29 @@ class FormatError : public std::runtime_error {
};
namespace internal {
// MakeUnsigned<T>::Type gives an unsigned type corresponding to integer type T.
template <typename T>
struct MakeUnsigned { typedef T Type; };
#define FMT_SPECIALIZE_MAKE_UNSIGNED(T, U) \
template <> \
struct MakeUnsigned<T> { typedef U Type; }
FMT_SPECIALIZE_MAKE_UNSIGNED(char, unsigned char);
FMT_SPECIALIZE_MAKE_UNSIGNED(signed char, unsigned char);
FMT_SPECIALIZE_MAKE_UNSIGNED(short, unsigned short);
FMT_SPECIALIZE_MAKE_UNSIGNED(int, unsigned);
FMT_SPECIALIZE_MAKE_UNSIGNED(long, unsigned long);
FMT_SPECIALIZE_MAKE_UNSIGNED(LongLong, ULongLong);
// Casts nonnegative integer to unsigned.
template <typename Int>
inline typename MakeUnsigned<Int>::Type to_unsigned(Int value) {
FMT_ASSERT(value >= 0, "negative value");
return static_cast<typename MakeUnsigned<Int>::Type>(value);
}
// The number of characters to store in the MemoryBuffer object itself
// to avoid dynamic memory allocation.
enum { INLINE_BUFFER_SIZE = 500 };
@@ -581,8 +645,7 @@ class Buffer {
template <typename T>
template <typename U>
void Buffer<T>::append(const U *begin, const U *end) {
assert(begin <= end);
std::size_t new_size = size_ + (end - begin);
std::size_t new_size = size_ + internal::to_unsigned(end - begin);
if (new_size > capacity_)
grow(new_size);
std::uninitialized_copy(begin, end,
@@ -592,8 +655,8 @@ void Buffer<T>::append(const U *begin, const U *end) {
namespace internal {
// A memory buffer for POD types with the first SIZE elements stored in
// the object itself.
// A memory buffer for trivially copyable/constructible types with the first SIZE
// elements stored in the object itself.
template <typename T, std::size_t SIZE, typename Allocator = std::allocator<T> >
class MemoryBuffer : private Allocator, public Buffer<T> {
private:
@@ -676,7 +739,7 @@ class FixedBuffer : public fmt::Buffer<Char> {
FixedBuffer(Char *array, std::size_t size) : fmt::Buffer<Char>(array, size) {}
protected:
void grow(std::size_t size);
FMT_API void grow(std::size_t size);
};
template <typename Char>
@@ -704,7 +767,7 @@ class CharTraits<char> : public BasicCharTraits<char> {
// Formats a floating-point number.
template <typename T>
static int format_float(char *buffer, std::size_t size,
FMT_API static int format_float(char *buffer, std::size_t size,
const char *format, unsigned width, int precision, T value);
};
@@ -715,7 +778,7 @@ class CharTraits<wchar_t> : public BasicCharTraits<wchar_t> {
static wchar_t convert(wchar_t value) { return value; }
template <typename T>
static int format_float(wchar_t *buffer, std::size_t size,
FMT_API static int format_float(wchar_t *buffer, std::size_t size,
const wchar_t *format, unsigned width, int precision, T value);
};
@@ -754,27 +817,12 @@ struct IntTraits {
TypeSelector<std::numeric_limits<T>::digits <= 32>::Type MainType;
};
// MakeUnsigned<T>::Type gives an unsigned type corresponding to integer type T.
template <typename T>
struct MakeUnsigned { typedef T Type; };
#define FMT_SPECIALIZE_MAKE_UNSIGNED(T, U) \
template <> \
struct MakeUnsigned<T> { typedef U Type; }
FMT_SPECIALIZE_MAKE_UNSIGNED(char, unsigned char);
FMT_SPECIALIZE_MAKE_UNSIGNED(signed char, unsigned char);
FMT_SPECIALIZE_MAKE_UNSIGNED(short, unsigned short);
FMT_SPECIALIZE_MAKE_UNSIGNED(int, unsigned);
FMT_SPECIALIZE_MAKE_UNSIGNED(long, unsigned long);
FMT_SPECIALIZE_MAKE_UNSIGNED(LongLong, ULongLong);
void report_unknown_type(char code, const char *type);
FMT_API void report_unknown_type(char code, const char *type);
// Static data is placed in this class template to allow header-only
// configuration.
template <typename T = void>
struct BasicData {
struct FMT_API BasicData {
static const uint32_t POWERS_OF_10_32[];
static const uint64_t POWERS_OF_10_64[];
static const char DIGITS[];
@@ -782,22 +830,14 @@ struct BasicData {
typedef BasicData<> Data;
#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz)
# define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
#endif
#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll)
# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
#endif
#ifdef FMT_BUILTIN_CLZLL
// Returns the number of decimal digits in n. Leading zeros are not counted
// except for n == 0 in which case count_digits returns 1.
inline unsigned count_digits(uint64_t n) {
// Based on http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
// and the benchmark https://github.com/localvoid/cxx-benchmark-count-digits.
unsigned t = (64 - FMT_BUILTIN_CLZLL(n | 1)) * 1233 >> 12;
return t - (n < Data::POWERS_OF_10_64[t]) + 1;
int t = (64 - FMT_BUILTIN_CLZLL(n | 1)) * 1233 >> 12;
return to_unsigned(t) - (n < Data::POWERS_OF_10_64[t]) + 1;
}
#else
// Fallback version of count_digits used when __builtin_clz is not available.
@@ -820,8 +860,8 @@ inline unsigned count_digits(uint64_t n) {
#ifdef FMT_BUILTIN_CLZ
// Optional version of count_digits for better performance on 32-bit platforms.
inline unsigned count_digits(uint32_t n) {
uint32_t t = (32 - FMT_BUILTIN_CLZ(n | 1)) * 1233 >> 12;
return t - (n < Data::POWERS_OF_10_32[t]) + 1;
int t = (32 - FMT_BUILTIN_CLZ(n | 1)) * 1233 >> 12;
return to_unsigned(t) - (n < Data::POWERS_OF_10_32[t]) + 1;
}
#endif
@@ -863,7 +903,7 @@ class UTF8ToUTF16 {
MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer_;
public:
explicit UTF8ToUTF16(StringRef s);
FMT_API explicit UTF8ToUTF16(StringRef s);
operator WStringRef() const { return WStringRef(&buffer_[0], size()); }
size_t size() const { return buffer_.size() - 1; }
const wchar_t *c_str() const { return &buffer_[0]; }
@@ -878,7 +918,7 @@ class UTF16ToUTF8 {
public:
UTF16ToUTF8() {}
explicit UTF16ToUTF8(WStringRef s);
FMT_API explicit UTF16ToUTF8(WStringRef s);
operator StringRef() const { return StringRef(&buffer_[0], size()); }
size_t size() const { return buffer_.size() - 1; }
const char *c_str() const { return &buffer_[0]; }
@@ -887,15 +927,15 @@ class UTF16ToUTF8 {
// Performs conversion returning a system error code instead of
// throwing exception on conversion error. This method may still throw
// in case of memory allocation error.
int convert(WStringRef s);
FMT_API int convert(WStringRef s);
};
void format_windows_error(fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT;
FMT_API void format_windows_error(fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT;
#endif
void format_system_error(fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT;
FMT_API void format_system_error(fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT;
// A formatting argument value.
struct Value {
@@ -938,8 +978,8 @@ struct Value {
};
};
// A formatting argument. It is a POD type to allow storage in
// internal::MemoryBuffer.
// A formatting argument. It is a trivially copyable/constructible type to
// allow storage in internal::MemoryBuffer.
struct Arg : Value {
Type type;
};
@@ -976,6 +1016,7 @@ template <typename T>
T &get();
struct DummyStream : std::ostream {
DummyStream(); // Suppress a bogus warning in MSVC.
// Hide all operator<< overloads from std::ostream.
void operator<<(Null<>);
};
@@ -1199,17 +1240,27 @@ class MakeValue : public Arg {
static uint64_t type(const NamedArg<Char_> &) { return Arg::NAMED_ARG; }
};
template <typename Formatter>
class MakeArg : public Arg {
public:
MakeArg() {
type = Arg::NONE;
}
template <typename T>
MakeArg(const T &value)
: Arg(MakeValue<Formatter>(value)) {
type = static_cast<Arg::Type>(MakeValue<Formatter>::type(value));
}
};
template <typename Char>
struct NamedArg : Arg {
BasicStringRef<Char> name;
typedef internal::MakeValue< BasicFormatter<Char> > MakeValue;
template <typename T>
NamedArg(BasicStringRef<Char> argname, const T &value)
: Arg(MakeValue(value)), name(argname) {
type = static_cast<Arg::Type>(MakeValue::type(value));
}
: Arg(MakeArg< BasicFormatter<Char> >(value)), name(argname) {}
};
#define FMT_DISPATCH(call) static_cast<Impl*>(this)->call
@@ -1631,17 +1682,22 @@ namespace internal {
template <typename Char>
class ArgMap {
private:
typedef std::map<fmt::BasicStringRef<Char>, internal::Arg> MapType;
typedef std::vector<std::pair<fmt::BasicStringRef<Char>, internal::Arg> > MapType;
typedef typename MapType::value_type Pair;
MapType map_;
public:
void init(const ArgList &args);
FMT_API void init(const ArgList &args);
const internal::Arg* find(const fmt::BasicStringRef<Char> &name) const {
typename MapType::const_iterator it = map_.find(name);
return it != map_.end() ? &it->second : 0;
// The list is unsorted, so just return the first matching name.
for (typename MapType::const_iterator it = map_.begin(), end = map_.end();
it != end; ++it) {
if (it->first == name)
return &it->second;
}
return 0;
}
};
@@ -1767,7 +1823,7 @@ class FormatterBase {
int next_arg_index_;
// Returns the argument with specified index.
Arg do_get_arg(unsigned arg_index, const char *&error);
FMT_API Arg do_get_arg(unsigned arg_index, const char *&error);
protected:
const ArgList &args() const { return args_; }
@@ -1780,7 +1836,7 @@ class FormatterBase {
// Returns the next argument.
Arg next_arg(const char *&error) {
if (next_arg_index_ >= 0)
return do_get_arg(next_arg_index_++, error);
return do_get_arg(internal::to_unsigned(next_arg_index_++), error);
error = "cannot switch from manual to automatic argument indexing";
return Arg();
}
@@ -1803,7 +1859,7 @@ class FormatterBase {
template <typename Char>
void write(BasicWriter<Char> &w, const Char *start, const Char *end) {
if (start != end)
w << BasicStringRef<Char>(start, end - start);
w << BasicStringRef<Char>(start, internal::to_unsigned(end - start));
}
};
@@ -1823,14 +1879,16 @@ class PrintfFormatter : private FormatterBase {
public:
explicit PrintfFormatter(const ArgList &args) : FormatterBase(args) {}
void format(BasicWriter<Char> &writer, BasicCStringRef<Char> format_str);
FMT_API void format(BasicWriter<Char> &writer,
BasicCStringRef<Char> format_str);
};
} // namespace internal
// A formatter.
/** This template formats data and writes the output to a writer. */
template <typename CharType>
class BasicFormatter : private internal::FormatterBase {
public:
/** The character type for the output. */
typedef CharType Char;
private:
@@ -1852,13 +1910,23 @@ class BasicFormatter : private internal::FormatterBase {
internal::Arg parse_arg_name(const Char *&s);
public:
/**
\rst
Constructs a ``BasicFormatter`` object. References to the arguments and
the writer are stored in the formatter object so make sure they have
appropriate lifetimes.
\endrst
*/
BasicFormatter(const ArgList &args, BasicWriter<Char> &w)
: internal::FormatterBase(args), writer_(w) {}
/** Returns a reference to the writer associated with this formatter. */
BasicWriter<Char> &writer() { return writer_; }
/** Formats stored arguments and writes the output to the writer. */
void format(BasicCStringRef<Char> format_str);
// Formats a single argument and advances format_str, a format string pointer.
const Char *format(const Char *&format_str, const internal::Arg &arg);
};
@@ -1889,16 +1957,29 @@ inline uint64_t make_type(const T &arg) {
return MakeValue< BasicFormatter<char> >::type(arg);
}
template <unsigned N>
struct ArgArray {
// Computes the argument array size by adding 1 to N, which is the number of
// arguments, if N is zero, because array of zero size is invalid, or if N
// is greater than ArgList::MAX_PACKED_ARGS to accommodate for an extra
// argument that marks the end of the list.
enum { SIZE = N + (N == 0 || N >= ArgList::MAX_PACKED_ARGS ? 1 : 0) };
template <unsigned N, bool/*IsPacked*/= (N < ArgList::MAX_PACKED_ARGS)>
struct ArgArray;
typedef typename Conditional<
(N < ArgList::MAX_PACKED_ARGS), Value, Arg>::type Type[SIZE];
template <unsigned N>
struct ArgArray<N, true/*IsPacked*/> {
typedef Value Type[N > 0 ? N : 1];
template <typename Formatter, typename T>
static Value make(const T &value) {
Value result = MakeValue<Formatter>(value);
// Workaround a bug in Apple LLVM version 4.2 (clang-425.0.28) of clang:
// https://github.com/cppformat/cppformat/issues/276
(void)result.custom.format;
return result;
}
};
template <unsigned N>
struct ArgArray<N, false/*IsPacked*/> {
typedef Arg Type[N + 1]; // +1 for the list end Arg::NONE
template <typename Formatter, typename T>
static Arg make(const T &value) { return MakeArg<Formatter>(value); }
};
#if FMT_USE_VARIADIC_TEMPLATES
@@ -1907,47 +1988,6 @@ inline uint64_t make_type(const Arg &first, const Args & ... tail) {
return make_type(first) | (make_type(tail...) << 4);
}
inline void do_set_types(Arg *) {}
template <typename T, typename... Args>
inline void do_set_types(Arg *args, const T &arg, const Args & ... tail) {
args->type = static_cast<Arg::Type>(
MakeValue< BasicFormatter<char> >::type(arg));
do_set_types(args + 1, tail...);
}
template <typename... Args>
inline void set_types(Arg *array, const Args & ... args) {
if (check(sizeof...(Args) > ArgList::MAX_PACKED_ARGS))
do_set_types(array, args...);
array[sizeof...(Args)].type = Arg::NONE;
}
template <typename... Args>
inline void set_types(Value *, const Args & ...) {
// Do nothing as types are passed separately from values.
}
template <typename Formatter, typename Value>
inline void store_args(Value *) {}
template <typename Formatter, typename Arg, typename T, typename... Args>
inline void store_args(Arg *args, const T &arg, const Args & ... tail) {
// Assign only the Value subobject of Arg and don't overwrite type (if any)
// that is assigned by set_types.
Value &value = *args;
value = MakeValue<Formatter>(arg);
store_args<Formatter>(args + 1, tail...);
}
template <typename Formatter, typename... Args>
ArgList make_arg_list(typename ArgArray<sizeof...(Args)>::Type array,
const Args & ... args) {
if (check(sizeof...(Args) >= ArgList::MAX_PACKED_ARGS))
set_types(array, args...);
store_args<Formatter>(array, args...);
return ArgList(make_type(args...), array);
}
#else
struct ArgType {
@@ -1985,7 +2025,7 @@ class FormatBuf : public std::basic_streambuf<Char> {
int_type overflow(int_type ch = traits_type::eof()) {
if (!traits_type::eq_int_type(ch, traits_type::eof())) {
size_t size = this->pptr() - start_;
size_t size = this->size();
buffer_.resize(size);
buffer_.reserve(size * 2);
@@ -1997,7 +2037,7 @@ class FormatBuf : public std::basic_streambuf<Char> {
}
size_t size() const {
return this->pptr() - start_;
return to_unsigned(this->pptr() - start_);
}
};
} // namespace internal
@@ -2015,18 +2055,20 @@ class FormatBuf : public std::basic_streambuf<Char> {
# define FMT_VARIADIC_VOID(func, arg_type) \
template <typename... Args> \
void func(arg_type arg0, const Args & ... args) { \
typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \
func(arg0, fmt::internal::make_arg_list< \
fmt::BasicFormatter<Char> >(array, args...)); \
typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \
typename ArgArray::Type array{ \
ArgArray::template make<fmt::BasicFormatter<Char> >(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 <typename... Args> \
ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \
typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \
func(arg0, arg1, fmt::internal::make_arg_list< \
fmt::BasicFormatter<Char> >(array, args...)); \
typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \
typename ArgArray::Type array{ \
ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \
func(arg0, arg1, fmt::ArgList(fmt::internal::make_type(args...), array)); \
}
#else
@@ -2207,7 +2249,8 @@ class BasicWriter {
// Writes a decimal integer.
template <typename Int>
void write_decimal(Int value) {
typename internal::IntTraits<Int>::MainType abs_value = value;
typedef typename internal::IntTraits<Int>::MainType MainType;
MainType abs_value = static_cast<MainType>(value);
if (internal::is_negative(value)) {
abs_value = 0 - abs_value;
*write_unsigned_decimal(abs_value, 1) = '-';
@@ -2474,9 +2517,9 @@ void BasicWriter<Char>::write_str(
return;
}
}
std::size_t precision = spec.precision_;
std::size_t precision = static_cast<std::size_t>(spec.precision_);
if (spec.precision_ >= 0 && precision < str_size)
str_size = spec.precision_;
str_size = precision;
write_str(str_value, str_size, spec);
}
@@ -2510,7 +2553,8 @@ typename BasicWriter<Char>::CharPtr
// is specified.
if (prefix_size > 0 && prefix[prefix_size - 1] == '0')
--prefix_size;
unsigned number_size = prefix_size + spec.precision();
unsigned number_size =
prefix_size + internal::to_unsigned(spec.precision());
AlignSpec subspec(number_size, '0', ALIGN_NUMERIC);
if (number_size >= width)
return prepare_int_buffer(num_digits, subspec, prefix, prefix_size);
@@ -2564,7 +2608,7 @@ template <typename T, typename Spec>
void BasicWriter<Char>::write_int(T value, Spec spec) {
unsigned prefix_size = 0;
typedef typename internal::IntTraits<T>::MainType UnsignedType;
UnsignedType abs_value = value;
UnsignedType abs_value = static_cast<UnsignedType>(value);
char prefix[4] = "";
if (internal::is_negative(value)) {
prefix[0] = '-';
@@ -2643,8 +2687,7 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
template <typename Char>
template <typename T>
void BasicWriter<Char>::write_double(
T value, const FormatSpec &spec) {
void BasicWriter<Char>::write_double(T value, const FormatSpec &spec) {
// Check type.
char type = spec.type();
bool upper = false;
@@ -2744,6 +2787,8 @@ void BasicWriter<Char>::write_double(
// Format using snprintf.
Char fill = internal::CharTraits<Char>::cast(spec.fill());
unsigned n = 0;
Char *start = 0;
for (;;) {
std::size_t buffer_size = buffer_.capacity() - offset;
#ifdef _MSC_VER
@@ -2755,41 +2800,44 @@ void BasicWriter<Char>::write_double(
buffer_size = buffer_.capacity() - offset;
}
#endif
Char *start = &buffer_[offset];
int n = internal::CharTraits<Char>::format_float(
start = &buffer_[offset];
int result = internal::CharTraits<Char>::format_float(
start, buffer_size, format, width_for_sprintf, spec.precision(), value);
if (n >= 0 && offset + n < buffer_.capacity()) {
if (sign) {
if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) ||
*start != ' ') {
*(start - 1) = sign;
sign = 0;
} else {
*(start - 1) = fill;
}
++n;
}
if (spec.align() == ALIGN_CENTER &&
spec.width() > static_cast<unsigned>(n)) {
width = spec.width();
CharPtr p = grow_buffer(width);
std::memmove(get(p) + (width - n) / 2, get(p), n * sizeof(Char));
fill_padding(p, spec.width(), n, fill);
return;
}
if (spec.fill() != ' ' || sign) {
while (*start == ' ')
*start++ = fill;
if (sign)
*(start - 1) = sign;
}
grow_buffer(n);
return;
if (result >= 0) {
n = internal::to_unsigned(result);
if (offset + n < buffer_.capacity())
break; // The buffer is large enough - continue with formatting.
buffer_.reserve(offset + n + 1);
} else {
// If result is negative we ask to increase the capacity by at least 1,
// but as std::vector, the buffer grows exponentially.
buffer_.reserve(buffer_.capacity() + 1);
}
// If n is negative we ask to increase the capacity by at least 1,
// but as std::vector, the buffer grows exponentially.
buffer_.reserve(n >= 0 ? offset + n + 1 : buffer_.capacity() + 1);
}
if (sign) {
if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) ||
*start != ' ') {
*(start - 1) = sign;
sign = 0;
} else {
*(start - 1) = fill;
}
++n;
}
if (spec.align() == ALIGN_CENTER && spec.width() > n) {
width = spec.width();
CharPtr p = grow_buffer(width);
std::memmove(get(p) + (width - n) / 2, get(p), n * sizeof(Char));
fill_padding(p, spec.width(), n, fill);
return;
}
if (spec.fill() != ' ' || sign) {
while (*start == ' ')
*start++ = fill;
if (sign)
*(start - 1) = sign;
}
grow_buffer(n);
}
/**
@@ -2920,22 +2968,21 @@ void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value) {
output << value;
BasicStringRef<Char> str(&buffer[0], format_buf.size());
typedef internal::MakeValue< BasicFormatter<Char> > MakeValue;
internal::Arg arg = MakeValue(str);
arg.type = static_cast<internal::Arg::Type>(MakeValue::type(str));
format_str = f.format(format_str, arg);
typedef internal::MakeArg< BasicFormatter<Char> > MakeArg;
format_str = f.format(format_str, MakeArg(str));
}
// Reports a system error without throwing an exception.
// Can be used to report errors from destructors.
void report_system_error(int error_code, StringRef message) FMT_NOEXCEPT;
FMT_API void report_system_error(int error_code,
StringRef message) FMT_NOEXCEPT;
#if FMT_USE_WINDOWS_H
/** A Windows error. */
class WindowsError : public SystemError {
private:
void init(int error_code, CStringRef format_str, ArgList args);
FMT_API void init(int error_code, CStringRef format_str, ArgList args);
public:
/**
@@ -2974,7 +3021,8 @@ class WindowsError : public SystemError {
// Reports a Windows error without throwing an exception.
// Can be used to report errors from destructors.
void report_windows_error(int error_code, StringRef message) FMT_NOEXCEPT;
FMT_API void report_windows_error(int error_code,
StringRef message) FMT_NOEXCEPT;
#endif
@@ -2986,7 +3034,7 @@ enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE };
Example:
print_colored(fmt::RED, "Elapsed time: {0:.2f} seconds", 1.23);
*/
void print_colored(Color c, CStringRef format, ArgList args);
FMT_API void print_colored(Color c, CStringRef format, ArgList args);
/**
\rst
@@ -3018,7 +3066,7 @@ inline std::wstring format(WCStringRef format_str, ArgList args) {
print(stderr, "Don't {}!", "panic");
\endrst
*/
void print(std::FILE *f, CStringRef format_str, ArgList args);
FMT_API void print(std::FILE *f, CStringRef format_str, ArgList args);
/**
\rst
@@ -3029,7 +3077,7 @@ void print(std::FILE *f, CStringRef format_str, ArgList args);
print("Elapsed time: {0:.2f} seconds", 1.23);
\endrst
*/
void print(CStringRef format_str, ArgList args);
FMT_API void print(CStringRef format_str, ArgList args);
template <typename Char>
void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) {
@@ -3066,7 +3114,7 @@ inline std::wstring sprintf(WCStringRef format, ArgList args) {
fmt::fprintf(stderr, "Don't %s!", "panic");
\endrst
*/
int fprintf(std::FILE *f, CStringRef format, ArgList args);
FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args);
/**
\rst
@@ -3132,10 +3180,10 @@ class FormatInt {
explicit FormatInt(unsigned long value) : str_(format_decimal(value)) {}
explicit FormatInt(ULongLong value) : str_(format_decimal(value)) {}
/**
Returns the number of characters written to the output buffer.
*/
std::size_t size() const { return buffer_ - str_ + BUFFER_SIZE - 1; }
/** Returns the number of characters written to the output buffer. */
std::size_t size() const {
return internal::to_unsigned(buffer_ - str_ + BUFFER_SIZE - 1);
}
/**
Returns a pointer to the output buffer content. No terminating null
@@ -3165,7 +3213,8 @@ class FormatInt {
// write a terminating null character.
template <typename T>
inline void format_decimal(char *&buffer, T value) {
typename internal::IntTraits<T>::MainType abs_value = value;
typedef typename internal::IntTraits<T>::MainType MainType;
MainType abs_value = static_cast<MainType>(value);
if (internal::is_negative(value)) {
*buffer++ = '-';
abs_value = 0 - abs_value;
@@ -3245,10 +3294,11 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
template <typename... Args> \
ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
const Args & ... args) { \
typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \
typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \
typename ArgArray::Type array{ \
ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
fmt::internal::make_arg_list< \
fmt::BasicFormatter<Char> >(array, args...)); \
fmt::ArgList(fmt::internal::make_type(args...), array)); \
}
#else
// Defines a wrapper for a function taking __VA_ARGS__ arguments
@@ -3361,8 +3411,20 @@ FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef)
print(cerr, "Don't {}!", "panic");
\endrst
*/
void print(std::ostream &os, CStringRef format_str, ArgList args);
FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args);
FMT_VARIADIC(void, print, std::ostream &, CStringRef)
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
fprintf(cerr, "Don't %s!", "panic");
\endrst
*/
FMT_API int fprintf(std::ostream &os, CStringRef format_str, ArgList args);
FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
#endif
namespace internal {
@@ -3374,7 +3436,7 @@ inline bool is_name_start(Char c) {
// Parses an unsigned integer advancing s to the end of the parsed input.
// This function assumes that the first character of s is a digit.
template <typename Char>
int parse_nonnegative_int(const Char *&s) {
unsigned parse_nonnegative_int(const Char *&s) {
assert('0' <= *s && *s <= '9');
unsigned value = 0;
do {
@@ -3453,7 +3515,6 @@ inline internal::Arg BasicFormatter<Char>::parse_arg_name(const Char *&s) {
return arg;
}
// Should be after FormatSpec
template <typename Char>
const Char *BasicFormatter<Char>::format(
const Char *&format_str, const internal::Arg &arg) {

View File

@@ -173,7 +173,7 @@ std::size_t fmt::File::read(void *buffer, std::size_t count) {
FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
if (result < 0)
throw SystemError(errno, "cannot read from file");
return result;
return internal::to_unsigned(result);
}
std::size_t fmt::File::write(const void *buffer, std::size_t count) {
@@ -181,7 +181,7 @@ std::size_t fmt::File::write(const void *buffer, std::size_t count) {
FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count))));
if (result < 0)
throw SystemError(errno, "cannot write to file");
return result;
return internal::to_unsigned(result);
}
fmt::File fmt::File::dup(int fd) {

View File

@@ -34,11 +34,17 @@
#endif
#include <errno.h>
#include <fcntl.h> // for O_RDONLY
#include <fcntl.h> // for O_RDONLY
#include <locale.h> // for locale_t
#include <stdio.h>
#include <stdlib.h> // for strtod_l
#include <cstddef>
#ifdef __APPLE__
# include <xlocale.h> // for LC_NUMERIC_MASK on OS X
#endif
#include "format.h"
#ifndef FMT_POSIX
@@ -299,7 +305,8 @@ class File {
// Closes the file.
void close();
// Returns the file size.
// Returns the file size. The size has signed type for consistency with
// stat::st_size.
LongLong size() const;
// Attempts to read count bytes from the file into the specified buffer.
@@ -331,6 +338,58 @@ class File {
// Returns the memory page size.
long getpagesize();
#if defined(LC_NUMERIC_MASK) || defined(_MSC_VER)
# define FMT_LOCALE
#endif
#ifdef FMT_LOCALE
// A "C" numeric locale.
class Locale {
private:
# ifdef _MSC_VER
typedef _locale_t locale_t;
enum { LC_NUMERIC_MASK = LC_NUMERIC };
static locale_t newlocale(int category_mask, const char *locale, locale_t) {
return _create_locale(category_mask, locale);
}
static void freelocale(locale_t locale) {
_free_locale(locale);
}
static double strtod_l(const char *nptr, char **endptr, _locale_t locale) {
return _strtod_l(nptr, endptr, locale);
}
# endif
locale_t locale_;
FMT_DISALLOW_COPY_AND_ASSIGN(Locale);
public:
typedef locale_t Type;
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", NULL)) {
if (!locale_)
throw fmt::SystemError(errno, "cannot create locale");
}
~Locale() { freelocale(locale_); }
Type get() const { return locale_; }
// Converts string to floating-point number and advances str past the end
// of the parsed input.
double strtod(const char *&str) const {
char *end = 0;
double result = strtod_l(str, &end, locale_);
str = end;
return result;
}
};
#endif // FMT_LOCALE
} // namespace fmt
#if !FMT_USE_RVALUE_REFERENCES

View File

@@ -19,7 +19,7 @@
#ifndef TRINITYCORE_STRING_FORMAT_H
#define TRINITYCORE_STRING_FORMAT_H
#include "format.h"
#include "cppformat/format.h"
namespace Trinity
{

View File

@@ -85,7 +85,7 @@ target_link_libraries(authserver
shared
database
common
format
cppformat
${MYSQL_LIBRARY}
${OPENSSL_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}

View File

@@ -140,7 +140,7 @@ target_link_libraries(worldserver
g3dlib
gsoap
Detour
format
cppformat
${JEMALLOC_LIBRARY}
${READLINE_LIBRARY}
${TERMCAP_LIBRARY}

View File

@@ -37,7 +37,7 @@ add_executable(mapextractor
target_link_libraries(mapextractor
common
format
cppformat
g3dlib
mpq
${BZIP2_LIBRARIES}

View File

@@ -49,7 +49,7 @@ target_link_libraries(mmaps_generator
g3dlib
Recast
Detour
format
cppformat
${BZIP2_LIBRARIES}
${ZLIB_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}