mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Dep/CppFormat: Update cppformat to cppformat/cppformat@5174b8c
This commit is contained in:
@@ -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/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
---------------
|
||||
|
||||
|
||||
@@ -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>;
|
||||
@@ -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) {
|
||||
@@ -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) {
|
||||
@@ -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
|
||||
@@ -19,7 +19,7 @@
|
||||
#ifndef TRINITYCORE_STRING_FORMAT_H
|
||||
#define TRINITYCORE_STRING_FORMAT_H
|
||||
|
||||
#include "format.h"
|
||||
#include "cppformat/format.h"
|
||||
|
||||
namespace Trinity
|
||||
{
|
||||
|
||||
@@ -85,7 +85,7 @@ target_link_libraries(authserver
|
||||
shared
|
||||
database
|
||||
common
|
||||
format
|
||||
cppformat
|
||||
${MYSQL_LIBRARY}
|
||||
${OPENSSL_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
|
||||
@@ -140,7 +140,7 @@ target_link_libraries(worldserver
|
||||
g3dlib
|
||||
gsoap
|
||||
Detour
|
||||
format
|
||||
cppformat
|
||||
${JEMALLOC_LIBRARY}
|
||||
${READLINE_LIBRARY}
|
||||
${TERMCAP_LIBRARY}
|
||||
|
||||
@@ -37,7 +37,7 @@ add_executable(mapextractor
|
||||
|
||||
target_link_libraries(mapextractor
|
||||
common
|
||||
format
|
||||
cppformat
|
||||
g3dlib
|
||||
mpq
|
||||
${BZIP2_LIBRARIES}
|
||||
|
||||
@@ -49,7 +49,7 @@ target_link_libraries(mmaps_generator
|
||||
g3dlib
|
||||
Recast
|
||||
Detour
|
||||
format
|
||||
cppformat
|
||||
${BZIP2_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
|
||||
Reference in New Issue
Block a user