diff --git a/cbp/Module.cbp b/cbp/Module.cbp
index a2028a33..d76ad3ef 100644
--- a/cbp/Module.cbp
+++ b/cbp/Module.cbp
@@ -400,6 +400,7 @@
+
diff --git a/external/Common/posix.cc b/external/Common/posix.cc
new file mode 100644
index 00000000..c6c2ae2c
--- /dev/null
+++ b/external/Common/posix.cc
@@ -0,0 +1,256 @@
+/*
+ A C++ interface to POSIX functions.
+
+ Copyright (c) 2014 - 2015, Victor Zverovich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Disable bogus MSVC warnings.
+#ifndef _CRT_SECURE_NO_WARNINGS
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "posix.h"
+
+#include
+#include
+#include
+
+#ifndef _WIN32
+# include
+#else
+# include
+# include
+
+# define O_CREAT _O_CREAT
+# define O_TRUNC _O_TRUNC
+
+# ifndef S_IRUSR
+# define S_IRUSR _S_IREAD
+# endif
+
+# ifndef S_IWUSR
+# define S_IWUSR _S_IWRITE
+# endif
+
+# ifdef __MINGW32__
+# define _SH_DENYNO 0x40
+# endif
+
+#endif // _WIN32
+
+#ifdef fileno
+# undef fileno
+#endif
+
+namespace {
+#ifdef _WIN32
+// Return type of read and write functions.
+typedef int RWResult;
+
+// On Windows the count argument to read and write is unsigned, so convert
+// it from size_t preventing integer overflow.
+inline unsigned convert_rwcount(std::size_t count) {
+ return count <= UINT_MAX ? static_cast(count) : UINT_MAX;
+}
+#else
+// Return type of read and write functions.
+typedef ssize_t RWResult;
+
+inline std::size_t convert_rwcount(std::size_t count) { return count; }
+#endif
+}
+
+fmt::BufferedFile::~BufferedFile() FMT_NOEXCEPT {
+ if (file_ && FMT_SYSTEM(fclose(file_)) != 0)
+ fmt::report_system_error(errno, "cannot close file");
+}
+
+fmt::BufferedFile::BufferedFile(
+ fmt::CStringRef filename, fmt::CStringRef mode) {
+ FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), 0);
+ if (!file_)
+ throw SystemError(errno, "cannot open file {}", filename);
+}
+
+void fmt::BufferedFile::close() {
+ if (!file_)
+ return;
+ int result = FMT_SYSTEM(fclose(file_));
+ file_ = 0;
+ if (result != 0)
+ throw SystemError(errno, "cannot close file");
+}
+
+// A macro used to prevent expansion of fileno on broken versions of MinGW.
+#define FMT_ARGS
+
+int fmt::BufferedFile::fileno() const {
+ int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_));
+ if (fd == -1)
+ throw SystemError(errno, "cannot get file descriptor");
+ return fd;
+}
+
+fmt::File::File(fmt::CStringRef path, int oflag) {
+ int mode = S_IRUSR | S_IWUSR;
+#if defined(_WIN32) && !defined(__MINGW32__)
+ fd_ = -1;
+ FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode));
+#else
+ FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode)));
+#endif
+ if (fd_ == -1)
+ throw SystemError(errno, "cannot open file {}", path);
+}
+
+fmt::File::~File() FMT_NOEXCEPT {
+ // Don't retry close in case of EINTR!
+ // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
+ if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0)
+ fmt::report_system_error(errno, "cannot close file");
+}
+
+void fmt::File::close() {
+ if (fd_ == -1)
+ return;
+ // Don't retry close in case of EINTR!
+ // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
+ int result = FMT_POSIX_CALL(close(fd_));
+ fd_ = -1;
+ if (result != 0)
+ throw SystemError(errno, "cannot close file");
+}
+
+fmt::LongLong fmt::File::size() const {
+#ifdef _WIN32
+ // Use GetFileSize instead of GetFileSizeEx for the case when _WIN32_WINNT
+ // is less than 0x0500 as is the case with some default MinGW builds.
+ // Both functions support large file sizes.
+ DWORD size_upper = 0;
+ HANDLE handle = reinterpret_cast(_get_osfhandle(fd_));
+ DWORD size_lower = FMT_SYSTEM(GetFileSize(handle, &size_upper));
+ if (size_lower == INVALID_FILE_SIZE) {
+ DWORD error = GetLastError();
+ if (error != NO_ERROR)
+ throw WindowsError(GetLastError(), "cannot get file size");
+ }
+ fmt::ULongLong long_size = size_upper;
+ return (long_size << sizeof(DWORD) * CHAR_BIT) | size_lower;
+#else
+ typedef struct stat Stat;
+ Stat file_stat = Stat();
+ if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1)
+ throw SystemError(errno, "cannot get file attributes");
+ FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(file_stat.st_size),
+ "return type of File::size is not large enough");
+ return file_stat.st_size;
+#endif
+}
+
+std::size_t fmt::File::read(void *buffer, std::size_t count) {
+ RWResult result = 0;
+ FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
+ if (result < 0)
+ throw SystemError(errno, "cannot read from file");
+ return internal::to_unsigned(result);
+}
+
+std::size_t fmt::File::write(const void *buffer, std::size_t count) {
+ RWResult result = 0;
+ FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count))));
+ if (result < 0)
+ throw SystemError(errno, "cannot write to file");
+ return internal::to_unsigned(result);
+}
+
+fmt::File fmt::File::dup(int fd) {
+ // Don't retry as dup doesn't return EINTR.
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
+ int new_fd = FMT_POSIX_CALL(dup(fd));
+ if (new_fd == -1)
+ throw SystemError(errno, "cannot duplicate file descriptor {}", fd);
+ return File(new_fd);
+}
+
+void fmt::File::dup2(int fd) {
+ int result = 0;
+ FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
+ if (result == -1) {
+ throw SystemError(errno,
+ "cannot duplicate file descriptor {} to {}", fd_, fd);
+ }
+}
+
+void fmt::File::dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT {
+ int result = 0;
+ FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
+ if (result == -1)
+ ec = ErrorCode(errno);
+}
+
+void fmt::File::pipe(File &read_end, File &write_end) {
+ // Close the descriptors first to make sure that assignments don't throw
+ // and there are no leaks.
+ read_end.close();
+ write_end.close();
+ int fds[2] = {};
+#ifdef _WIN32
+ // Make the default pipe capacity same as on Linux 2.6.11+.
+ enum { DEFAULT_CAPACITY = 65536 };
+ int result = FMT_POSIX_CALL(pipe(fds, DEFAULT_CAPACITY, _O_BINARY));
+#else
+ // Don't retry as the pipe function doesn't return EINTR.
+ // http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html
+ int result = FMT_POSIX_CALL(pipe(fds));
+#endif
+ if (result != 0)
+ throw SystemError(errno, "cannot create pipe");
+ // The following assignments don't throw because read_fd and write_fd
+ // are closed.
+ read_end = File(fds[0]);
+ write_end = File(fds[1]);
+}
+
+fmt::BufferedFile fmt::File::fdopen(const char *mode) {
+ // Don't retry as fdopen doesn't return EINTR.
+ FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode));
+ if (!f)
+ throw SystemError(errno, "cannot associate stream with file descriptor");
+ BufferedFile file(f);
+ fd_ = -1;
+ return file;
+}
+
+long fmt::getpagesize() {
+#ifdef _WIN32
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ return si.dwPageSize;
+#else
+ long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE));
+ if (size < 0)
+ throw SystemError(errno, "cannot get memory page size");
+ return size;
+#endif
+}
diff --git a/external/Common/posix.h b/external/Common/posix.h
new file mode 100644
index 00000000..bfbd3851
--- /dev/null
+++ b/external/Common/posix.h
@@ -0,0 +1,403 @@
+/*
+ A C++ interface to POSIX functions.
+
+ Copyright (c) 2014 - 2015, Victor Zverovich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FMT_POSIX_H_
+#define FMT_POSIX_H_
+
+#ifdef __MINGW32__
+// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
+# undef __STRICT_ANSI__
+#endif
+
+#include
+#include // for O_RDONLY
+#include // for locale_t
+#include
+#include // for strtod_l
+
+#include
+
+#ifdef __APPLE__
+# include // for LC_NUMERIC_MASK on OS X
+#endif
+
+#include "format.h"
+
+#ifndef FMT_POSIX
+# if defined(_WIN32) && !defined(__MINGW32__)
+// Fix warnings about deprecated symbols.
+# define FMT_POSIX(call) _##call
+# else
+# define FMT_POSIX(call) call
+# endif
+#endif
+
+// Calls to system functions are wrapped in FMT_SYSTEM for testability.
+#ifdef FMT_SYSTEM
+# define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
+#else
+# define FMT_SYSTEM(call) call
+# ifdef _WIN32
+// Fix warnings about deprecated symbols.
+# define FMT_POSIX_CALL(call) ::_##call
+# else
+# define FMT_POSIX_CALL(call) ::call
+# endif
+#endif
+
+#if FMT_GCC_VERSION >= 407
+# define FMT_UNUSED __attribute__((unused))
+#else
+# define FMT_UNUSED
+#endif
+
+#ifndef FMT_USE_STATIC_ASSERT
+# define FMT_USE_STATIC_ASSERT 0
+#endif
+
+#if FMT_USE_STATIC_ASSERT || FMT_HAS_FEATURE(cxx_static_assert) || \
+ (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600
+# define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message)
+#else
+# define FMT_CONCAT_(a, b) FMT_CONCAT(a, b)
+# define FMT_STATIC_ASSERT(cond, message) \
+ typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED
+#endif
+
+// Retries the expression while it evaluates to error_result and errno
+// equals to EINTR.
+#ifndef _WIN32
+# define FMT_RETRY_VAL(result, expression, error_result) \
+ do { \
+ result = (expression); \
+ } while (result == error_result && errno == EINTR)
+#else
+# define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
+#endif
+
+#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
+
+namespace fmt {
+
+// An error code.
+class ErrorCode {
+ private:
+ int value_;
+
+ public:
+ explicit ErrorCode(int value = 0) FMT_NOEXCEPT : value_(value) {}
+
+ int get() const FMT_NOEXCEPT { return value_; }
+};
+
+// A buffered file.
+class BufferedFile {
+ private:
+ FILE *file_;
+
+ friend class File;
+
+ explicit BufferedFile(FILE *f) : file_(f) {}
+
+ public:
+ // Constructs a BufferedFile object which doesn't represent any file.
+ BufferedFile() FMT_NOEXCEPT : file_(0) {}
+
+ // Destroys the object closing the file it represents if any.
+ ~BufferedFile() FMT_NOEXCEPT;
+
+#if !FMT_USE_RVALUE_REFERENCES
+ // Emulate a move constructor and a move assignment operator if rvalue
+ // references are not supported.
+
+ private:
+ // A proxy object to emulate a move constructor.
+ // It is private to make it impossible call operator Proxy directly.
+ struct Proxy {
+ FILE *file;
+ };
+
+public:
+ // A "move constructor" for moving from a temporary.
+ BufferedFile(Proxy p) FMT_NOEXCEPT : file_(p.file) {}
+
+ // A "move constructor" for for moving from an lvalue.
+ BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) {
+ f.file_ = 0;
+ }
+
+ // A "move assignment operator" for moving from a temporary.
+ BufferedFile &operator=(Proxy p) {
+ close();
+ file_ = p.file;
+ return *this;
+ }
+
+ // A "move assignment operator" for moving from an lvalue.
+ BufferedFile &operator=(BufferedFile &other) {
+ close();
+ file_ = other.file_;
+ other.file_ = 0;
+ return *this;
+ }
+
+ // Returns a proxy object for moving from a temporary:
+ // BufferedFile file = BufferedFile(...);
+ operator Proxy() FMT_NOEXCEPT {
+ Proxy p = {file_};
+ file_ = 0;
+ return p;
+ }
+
+#else
+ private:
+ FMT_DISALLOW_COPY_AND_ASSIGN(BufferedFile);
+
+ public:
+ BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) {
+ other.file_ = 0;
+ }
+
+ BufferedFile& operator=(BufferedFile &&other) {
+ close();
+ file_ = other.file_;
+ other.file_ = 0;
+ return *this;
+ }
+#endif
+
+ // Opens a file.
+ BufferedFile(CStringRef filename, CStringRef mode);
+
+ // Closes the file.
+ void close();
+
+ // Returns the pointer to a FILE object representing this file.
+ FILE *get() const FMT_NOEXCEPT { return file_; }
+
+ // We place parentheses around fileno to workaround a bug in some versions
+ // of MinGW that define fileno as a macro.
+ int (fileno)() const;
+
+ void print(CStringRef format_str, const ArgList &args) {
+ fmt::print(file_, format_str, args);
+ }
+ FMT_VARIADIC(void, print, CStringRef)
+};
+
+// A file. Closed file is represented by a File object with descriptor -1.
+// Methods that are not declared with FMT_NOEXCEPT may throw
+// fmt::SystemError in case of failure. Note that some errors such as
+// closing the file multiple times will cause a crash on Windows rather
+// than an exception. You can get standard behavior by overriding the
+// invalid parameter handler with _set_invalid_parameter_handler.
+class File {
+ private:
+ int fd_; // File descriptor.
+
+ // Constructs a File object with a given descriptor.
+ explicit File(int fd) : fd_(fd) {}
+
+ public:
+ // Possible values for the oflag argument to the constructor.
+ enum {
+ RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
+ WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
+ RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing.
+ };
+
+ // Constructs a File object which doesn't represent any file.
+ File() FMT_NOEXCEPT : fd_(-1) {}
+
+ // Opens a file and constructs a File object representing this file.
+ File(CStringRef path, int oflag);
+
+#if !FMT_USE_RVALUE_REFERENCES
+ // Emulate a move constructor and a move assignment operator if rvalue
+ // references are not supported.
+
+ private:
+ // A proxy object to emulate a move constructor.
+ // It is private to make it impossible call operator Proxy directly.
+ struct Proxy {
+ int fd;
+ };
+
+ public:
+ // A "move constructor" for moving from a temporary.
+ File(Proxy p) FMT_NOEXCEPT : fd_(p.fd) {}
+
+ // A "move constructor" for for moving from an lvalue.
+ File(File &other) FMT_NOEXCEPT : fd_(other.fd_) {
+ other.fd_ = -1;
+ }
+
+ // A "move assignment operator" for moving from a temporary.
+ File &operator=(Proxy p) {
+ close();
+ fd_ = p.fd;
+ return *this;
+ }
+
+ // A "move assignment operator" for moving from an lvalue.
+ File &operator=(File &other) {
+ close();
+ fd_ = other.fd_;
+ other.fd_ = -1;
+ return *this;
+ }
+
+ // Returns a proxy object for moving from a temporary:
+ // File file = File(...);
+ operator Proxy() FMT_NOEXCEPT {
+ Proxy p = {fd_};
+ fd_ = -1;
+ return p;
+ }
+
+#else
+ private:
+ FMT_DISALLOW_COPY_AND_ASSIGN(File);
+
+ public:
+ File(File &&other) FMT_NOEXCEPT : fd_(other.fd_) {
+ other.fd_ = -1;
+ }
+
+ File& operator=(File &&other) {
+ close();
+ fd_ = other.fd_;
+ other.fd_ = -1;
+ return *this;
+ }
+#endif
+
+ // Destroys the object closing the file it represents if any.
+ ~File() FMT_NOEXCEPT;
+
+ // Returns the file descriptor.
+ int descriptor() const FMT_NOEXCEPT { return fd_; }
+
+ // Closes the file.
+ void close();
+
+ // 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.
+ std::size_t read(void *buffer, std::size_t count);
+
+ // Attempts to write count bytes from the specified buffer to the file.
+ std::size_t write(const void *buffer, std::size_t count);
+
+ // Duplicates a file descriptor with the dup function and returns
+ // the duplicate as a file object.
+ static File dup(int fd);
+
+ // Makes fd be the copy of this file descriptor, closing fd first if
+ // necessary.
+ void dup2(int fd);
+
+ // Makes fd be the copy of this file descriptor, closing fd first if
+ // necessary.
+ void dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT;
+
+ // Creates a pipe setting up read_end and write_end file objects for reading
+ // and writing respectively.
+ static void pipe(File &read_end, File &write_end);
+
+ // Creates a BufferedFile object associated with this file and detaches
+ // this File object from the file.
+ BufferedFile fdopen(const char *mode);
+};
+
+// 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
+namespace std {
+// For compatibility with C++98.
+inline fmt::BufferedFile &move(fmt::BufferedFile &f) { return f; }
+inline fmt::File &move(fmt::File &f) { return f; }
+}
+#endif
+
+#endif // FMT_POSIX_H_
diff --git a/external/CppFormat/ChangeLog.rst b/external/CppFormat/ChangeLog.rst
new file mode 100644
index 00000000..89d5af8e
--- /dev/null
+++ b/external/CppFormat/ChangeLog.rst
@@ -0,0 +1,335 @@
+1.1.0 - 2015-03-06
+------------------
+
+* Added ``BasicArrayWriter``, a class template that provides operations for
+ formatting and writing data into a fixed-size array
+ (`#105 `_ and
+ `#122 `_):
+
+ .. code:: c++
+
+ char buffer[100];
+ fmt::ArrayWriter w(buffer);
+ w.write("The answer is {}", 42);
+
+* Added `0 A.D. `_ and `PenUltima Online (POL)
+ `_ to the list of notable projects using C++ Format.
+
+* C++ Format now uses MSVC intrinsics for better formatting performance
+ (`#115 `_,
+ `#116 `_,
+ `#118 `_ and
+ `#121 `_).
+ Previously these optimizations where only used on GCC and Clang.
+ Thanks to `@CarterLi `_ and
+ `@objectx `_.
+
+* CMake install target (`#119 `_).
+ Thanks to `@TrentHouliston `_.
+
+ You can now install C++ Format with ``make install`` command.
+
+* Improved `Biicode `_ support
+ (`#98 `_ and
+ `#104 `_). Thanks to
+ `@MariadeAnton `_ and
+ `@franramirez688 `_.
+
+* Improved support for bulding with `Android NDK
+ `_
+ (`#107 `_).
+ Thanks to `@newnon `_.
+
+ The `android-ndk-example `_
+ repository provides and example of using C++ Format with Android NDK:
+
+ .. image:: https://raw.githubusercontent.com/cppformat/android-ndk-example/
+ master/screenshot.png
+
+* Improved documentation of ``SystemError`` and ``WindowsError``
+ (`#54 `_).
+
+* Various code improvements
+ (`#110 `_,
+ `#111 `_
+ `#112 `_).
+ Thanks to `@CarterLi `_.
+
+* Improved compile-time errors when formatting wide into narrow strings
+ (`#117 `_).
+
+* Fixed ``BasicWriter::write`` without formatting arguments when C++11 support
+ is disabled (`#109 `_).
+
+* Fixed header-only build on OS X with GCC 4.9
+ (`#124 `_).
+
+* Fixed packaging issues (`#94 `_).
+
+* Fixed warnings in GCC, MSVC and Xcode/Clang
+ (`#95 `_,
+ `#96 `_ and
+ `#114 `_).
+
+* Added `changelog `_
+ (`#103 `_).
+
+1.0.0 - 2015-02-05
+------------------
+
+* Add support for a header-only configuration when ``FMT_HEADER_ONLY`` is
+ defined before including ``format.h``:
+
+ .. code:: c++
+
+ #define FMT_HEADER_ONLY
+ #include "format.h"
+
+* Compute string length in the constructor of ``BasicStringRef``
+ instead of the ``size`` method
+ (`#79 `_).
+ This eliminates size computation for string literals on reasonable optimizing
+ compilers.
+
+* Fix formatting of types with overloaded ``operator <<`` for ``std::wostream``
+ (`#86 `_):
+
+ .. code:: c++
+
+ fmt::format(L"The date is {0}", Date(2012, 12, 9));
+
+* Fix linkage of tests on Arch Linux
+ (`#89 `_).
+
+* Allow precision specifier for non-float arguments
+ (`#90 `_):
+
+ .. code:: c++
+
+ fmt::print("{:.3}\n", "Carpet"); // prints "Car"
+
+* Fix build on Android NDK
+ (`#93 `_)
+
+* Improvements to documentation build procedure.
+
+* Remove ``FMT_SHARED`` CMake variable in favor of standard `BUILD_SHARED_LIBS
+ `_.
+
+* Fix error handling in ``fmt::fprintf``.
+
+* Fix a number of warnings.
+
+0.12.0 - 2014-10-25
+-------------------
+
+* [Breaking] Improved separation between formatting and buffer management.
+ ``Writer`` is now a base class that cannot be instantiated directly.
+ The new ``MemoryWriter`` class implements the default buffer management
+ with small allocations done on stack. So ``fmt::Writer`` should be replaced
+ with ``fmt::MemoryWriter`` in variable declarations.
+
+ Old code:
+
+ .. code:: c++
+
+ fmt::Writer w;
+
+ New code:
+
+ .. code:: c++
+
+ fmt::MemoryWriter w;
+
+ If you pass ``fmt::Writer`` by reference, you can continue to do so:
+
+ .. code:: c++
+
+ void f(fmt::Writer &w);
+
+ This doesn't affect the formatting API.
+
+* Support for custom memory allocators
+ (`#69 `_)
+
+* Formatting functions now accept `signed char` and `unsigned char` strings as
+ arguments (`#73 `_):
+
+ .. code:: c++
+
+ auto s = format("GLSL version: {}", glGetString(GL_VERSION));
+
+* Reduced code bloat. According to the new `benchmark results
+ `_,
+ cppformat is close to ``printf`` and by the order of magnitude better than
+ Boost Format in terms of compiled code size.
+
+* Improved appearance of the documentation on mobile by using the `Sphinx
+ Bootstrap theme `_:
+
+ .. |old| image:: https://cloud.githubusercontent.com/assets/576385/4792130/
+ cd256436-5de3-11e4-9a62-c077d0c2b003.png
+
+ .. |new| image:: https://cloud.githubusercontent.com/assets/576385/4792131/
+ cd29896c-5de3-11e4-8f59-cac952942bf0.png
+
+ +-------+-------+
+ | Old | New |
+ +-------+-------+
+ | |old| | |new| |
+ +-------+-------+
+
+0.11.0 - 2014-08-21
+-------------------
+
+* Safe printf implementation with a POSIX extension for positional arguments:
+
+ .. code:: c++
+
+ fmt::printf("Elapsed time: %.2f seconds", 1.23);
+ fmt::printf("%1$s, %3$d %2$s", weekday, month, day);
+
+* Arguments of ``char`` type can now be formatted as integers
+ (Issue `#55 `_):
+
+ .. code:: c++
+
+ fmt::format("0x{0:02X}", 'a');
+
+* Deprecated parts of the API removed.
+
+* The library is now built and tested on MinGW with Appveyor in addition to
+ existing test platforms Linux/GCC, OS X/Clang, Windows/MSVC.
+
+0.10.0 - 2014-07-01
+-------------------
+
+**Improved API**
+
+* All formatting methods are now implemented as variadic functions instead
+ of using ``operator<<`` for feeding arbitrary arguments into a temporary
+ formatter object. This works both with C++11 where variadic templates are
+ used and with older standards where variadic functions are emulated by
+ providing lightweight wrapper functions defined with the ``FMT_VARIADIC``
+ macro. You can use this macro for defining your own portable variadic
+ functions:
+
+ .. code:: c++
+
+ void report_error(const char *format, const fmt::ArgList &args) {
+ fmt::print("Error: {}");
+ fmt::print(format, args);
+ }
+ FMT_VARIADIC(void, report_error, const char *)
+
+ report_error("file not found: {}", path);
+
+ Apart from a more natural syntax, this also improves performance as there
+ is no need to construct temporary formatter objects and control arguments'
+ lifetimes. Because the wrapper functions are very ligthweight, this doesn't
+ cause code bloat even in pre-C++11 mode.
+
+* Simplified common case of formatting an ``std::string``. Now it requires a
+ single function call:
+
+ .. code:: c++
+
+ std::string s = format("The answer is {}.", 42);
+
+ Previously it required 2 function calls:
+
+ .. code:: c++
+
+ std::string s = str(Format("The answer is {}.") << 42);
+
+ Instead of unsafe ``c_str`` function, ``fmt::Writer`` should be used directly
+ to bypass creation of ``std::string``:
+
+ .. code:: c++
+
+ fmt::Writer w;
+ w.write("The answer is {}.", 42);
+ w.c_str(); // returns a C string
+
+ This doesn't do dynamic memory allocation for small strings and is less error
+ prone as the lifetime of the string is the same as for ``std::string::c_str``
+ which is well understood (hopefully).
+
+* Improved consistency in naming functions that are a part of the public API.
+ Now all public functions are lowercase following the standard library
+ conventions. Previously it was a combination of lowercase and
+ CapitalizedWords.
+ Issue `#50 `_.
+
+* Old functions are marked as deprecated and will be removed in the next
+ release.
+
+**Other Changes**
+
+* Experimental support for printf format specifications (work in progress):
+
+ .. code:: c++
+
+ fmt::printf("The answer is %d.", 42);
+ std::string s = fmt::sprintf("Look, a %s!", "string");
+
+* Support for hexadecimal floating point format specifiers ``a`` and ``A``:
+
+ .. code:: c++
+
+ print("{:a}", -42.0); // Prints -0x1.5p+5
+ print("{:A}", -42.0); // Prints -0X1.5P+5
+
+* CMake option ``FMT_SHARED`` that specifies whether to build format as a
+ shared library (off by default).
+
+0.9.0 - 2014-05-13
+------------------
+
+* More efficient implementation of variadic formatting functions.
+
+* ``Writer::Format`` now has a variadic overload:
+
+ .. code:: c++
+
+ Writer out;
+ out.Format("Look, I'm {}!", "variadic");
+
+* For efficiency and consistency with other overloads, variadic overload of
+ the ``Format`` function now returns ``Writer`` instead of ``std::string``.
+ Use the ``str`` function to convert it to ``std::string``:
+
+ .. code:: c++
+
+ std::string s = str(Format("Look, I'm {}!", "variadic"));
+
+* Replaced formatter actions with output sinks: ``NoAction`` -> ``NullSink``,
+ ``Write`` -> ``FileSink``, ``ColorWriter`` -> ``ANSITerminalSink``.
+ This improves naming consistency and shouldn't affect client code unless
+ these classes are used directly which should be rarely needed.
+
+* Added ``ThrowSystemError`` function that formats a message and throws
+ ``SystemError`` containing the formatted message and system-specific error
+ description. For example, the following code
+
+ .. code:: c++
+
+ FILE *f = fopen(filename, "r");
+ if (!f)
+ ThrowSystemError(errno, "Failed to open file '{}'") << filename;
+
+ will throw ``SystemError`` exception with description
+ "Failed to open file '': No such file or directory" if file
+ doesn't exist.
+
+* Support for AppVeyor continuous integration platform.
+
+* ``Format`` now throws ``SystemError`` in case of I/O errors.
+
+* Improve test infrastructure. Print functions are now tested by redirecting
+ the output to a pipe.
+
+0.8.0 - 2014-04-14
+------------------
+
+* Initial release
diff --git a/external/CppFormat/LICENSE.rst b/external/CppFormat/LICENSE.rst
new file mode 100644
index 00000000..b1c96ca0
--- /dev/null
+++ b/external/CppFormat/LICENSE.rst
@@ -0,0 +1,23 @@
+Copyright (c) 2012 - 2015, Victor Zverovich
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/external/CppFormat/README.rst b/external/CppFormat/README.rst
new file mode 100644
index 00000000..29f43348
--- /dev/null
+++ b/external/CppFormat/README.rst
@@ -0,0 +1,409 @@
+C++ Format
+==========
+
+.. image:: https://travis-ci.org/cppformat/cppformat.png?branch=master
+ :target: https://travis-ci.org/cppformat/cppformat
+
+.. image:: https://ci.appveyor.com/api/projects/status/qk0bhyhqp1ekpat8
+ :target: https://ci.appveyor.com/project/vitaut/cppformat
+
+.. image:: https://webapi.biicode.com/v1/badges/vitaut/vitaut/cppformat/master?dummy
+ :target: https://www.biicode.com/vitaut/cppformat
+
+.. image:: https://badges.gitter.im/Join%20Chat.svg
+ :alt: Join the chat at https://gitter.im/cppformat/cppformat
+ :target: https://gitter.im/cppformat/cppformat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
+
+C++ Format is an open-source formatting library for C++.
+It can be used as a safe alternative to printf or as a fast
+alternative to IOStreams.
+
+`Documentation `_
+
+Features
+--------
+
+* Two APIs: faster concatenation-based write API and slower (but still
+ very fast) replacement-based format API with positional arguments for
+ localization.
+* Write API similar to the one used by IOStreams but stateless allowing
+ faster implementation.
+* Format API with `format string syntax
+ `_
+ similar to the one used by `str.format
+ `_ in Python.
+* Safe `printf implementation
+ `_
+ including the POSIX extension for positional arguments.
+* Support for user-defined types.
+* High speed: performance of the format API is close to that of
+ glibc's `printf `_
+ and better than performance of IOStreams. See `Speed tests`_ and
+ `Fast integer to string conversion in C++
+ `_.
+* Small code size both in terms of source code (format consists of a single
+ header file and a single source file) and compiled code.
+ See `Compile time and code bloat`_.
+* Reliability: the library has an extensive set of `unit tests
+ `_.
+* Safety: the library is fully type safe, errors in format strings are
+ reported using exceptions, automatic memory management prevents buffer
+ overflow errors.
+* Ease of use: small self-contained code base, no external dependencies,
+ permissive BSD `license
+ `_
+* `Portability `_ with consistent output
+ across platforms and support for older compilers.
+* Clean warning-free codebase even on high warning levels
+ (-Wall -Wextra -pedantic).
+* Support for wide strings.
+* Optional header-only configuration enabled with the ``FMT_HEADER_ONLY`` macro.
+
+See the `documentation `_ for more details.
+
+Examples
+--------
+
+This prints ``Hello, world!`` to stdout:
+
+.. code:: c++
+
+ fmt::print("Hello, {}!", "world"); // uses Python-like format string syntax
+ fmt::printf("Hello, %s!", "world"); // uses printf format string syntax
+
+Arguments can be accessed by position and arguments' indices can be repeated:
+
+.. code:: c++
+
+ std::string s = fmt::format("{0}{1}{0}", "abra", "cad");
+ // s == "abracadabra"
+
+C++ Format can be used as a safe portable replacement for ``itoa``:
+
+.. code:: c++
+
+ fmt::MemoryWriter w;
+ w << 42; // replaces itoa(42, buffer, 10)
+ w << fmt::hex(42); // replaces itoa(42, buffer, 16)
+ // access the string using w.str() or w.c_str()
+
+An object of any user-defined type for which there is an overloaded
+:code:`std::ostream` insertion operator (``operator<<``) can be formatted:
+
+.. code:: c++
+
+ class Date {
+ int year_, month_, day_;
+ public:
+ Date(int year, int month, int day) : year_(year), month_(month), day_(day) {}
+
+ friend std::ostream &operator<<(std::ostream &os, const Date &d) {
+ return os << d.year_ << '-' << d.month_ << '-' << d.day_;
+ }
+ };
+
+ std::string s = fmt::format("The date is {}", Date(2012, 12, 9));
+ // s == "The date is 2012-12-9"
+
+You can use the `FMT_VARIADIC
+`_
+macro to create your own functions similar to `format
+`_ and
+`print `_
+which take arbitrary arguments:
+
+.. code:: c++
+
+ // Prints formatted error message.
+ void report_error(const char *format, fmt::ArgList args) {
+ fmt::print("Error: ");
+ fmt::print(format, args);
+ }
+ FMT_VARIADIC(void, report_error, const char *)
+
+ report_error("file not found: {}", path);
+
+Note that you only need to define one function that takes ``fmt::ArgList``
+argument. ``FMT_VARIADIC`` automatically defines necessary wrappers that
+accept variable number of arguments.
+
+Projects using this library
+---------------------------
+
+* `0 A.D. `_: A free, open-source, cross-platform real-time strategy game
+
+* `AMPL/MP `_:
+ An open-source library for mathematical programming
+
+* `HarpyWar/pvpgn `_:
+ Player vs Player Gaming Network with tweaks
+
+* `KBEngine `_: An open-source MMOG server engine
+
+* `Lifeline `_: A 2D game
+
+* `PenUltima Online (POL) `_:
+ An MMO server, compatible with most Ultima Online clients
+
+* `quasardb `_: A distributed, high-performance, associative database
+
+* `readpe `_: Read Portable Executable
+
+* `Saddy `_:
+ Small crossplatform 2D graphic engine
+
+* `Salesforce Analytics Cloud `_:
+ Business intelligence software
+
+* `spdlog `_: Super fast C++ logging library
+
+* `TrinityCore `_: Open-source MMORPG framework
+
+`More... `_
+
+If you are aware of other projects using this library, please let me know
+by `email `_ or by submitting an
+`issue `_.
+
+Motivation
+----------
+
+So why yet another formatting library?
+
+There are plenty of methods for doing this task, from standard ones like
+the printf family of function and IOStreams to Boost Format library and
+FastFormat. The reason for creating a new library is that every existing
+solution that I found either had serious issues or didn't provide
+all the features I needed.
+
+Printf
+~~~~~~
+
+The good thing about printf is that it is pretty fast and readily available
+being a part of the C standard library. The main drawback is that it
+doesn't support user-defined types. Printf also has safety issues although
+they are mostly solved with `__attribute__ ((format (printf, ...))
+`_ in GCC.
+There is a POSIX extension that adds positional arguments required for
+`i18n `_
+to printf but it is not a part of C99 and may not be available on some
+platforms.
+
+IOStreams
+~~~~~~~~~
+
+The main issue with IOStreams is best illustrated with an example:
+
+.. code:: c++
+
+ std::cout << std::setprecision(2) << std::fixed << 1.23456 << "\n";
+
+which is a lot of typing compared to printf:
+
+.. code:: c++
+
+ printf("%.2f\n", 1.23456);
+
+Matthew Wilson, the author of FastFormat, referred to this situation with
+IOStreams as "chevron hell". IOStreams doesn't support positional arguments
+by design.
+
+The good part is that IOStreams supports user-defined types and is safe
+although error reporting is awkward.
+
+Boost Format library
+~~~~~~~~~~~~~~~~~~~~
+
+This is a very powerful library which supports both printf-like format
+strings and positional arguments. The main its drawback is performance.
+According to various benchmarks it is much slower than other methods
+considered here. Boost Format also has excessive build times and severe
+code bloat issues (see `Benchmarks`_).
+
+FastFormat
+~~~~~~~~~~
+
+This is an interesting library which is fast, safe and has positional
+arguments. However it has significant limitations, citing its author:
+
+ Three features that have no hope of being accommodated within the
+ current design are:
+
+ * Leading zeros (or any other non-space padding)
+ * Octal/hexadecimal encoding
+ * Runtime width/alignment specification
+
+It is also quite big and has a heavy dependency, STLSoft, which might be
+too restrictive for using it in some projects.
+
+Loki SafeFormat
+~~~~~~~~~~~~~~~
+
+SafeFormat is a formatting library which uses printf-like format strings
+and is type safe. It doesn't support user-defined types or positional
+arguments. It makes unconventional use of ``operator()`` for passing
+format arguments.
+
+Tinyformat
+~~~~~~~~~~
+
+This library supports printf-like format strings and is very small and
+fast. Unfortunately it doesn't support positional arguments and wrapping
+it in C++98 is somewhat difficult. Also its performance and code compactness
+are limited by IOStreams.
+
+Boost Spirit.Karma
+~~~~~~~~~~~~~~~~~~
+
+This is not really a formatting library but I decided to include it here
+for completeness. As IOStreams it suffers from the problem of mixing
+verbatim text with arguments. The library is pretty fast, but slower
+on integer formatting than ``fmt::Writer`` on Karma's own benchmark,
+see `Fast integer to string conversion in C++
+`_.
+
+Benchmarks
+----------
+
+Speed tests
+~~~~~~~~~~~
+
+The following speed tests results were generated by building
+``tinyformat_test.cpp`` on Ubuntu GNU/Linux 14.04.1 with
+``g++-4.8.2 -O3 -DSPEED_TEST -DHAVE_FORMAT``, and taking the best of three
+runs. In the test, the format string ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"`` or
+equivalent is filled 2000000 times with output sent to ``/dev/null``; for
+further details see the `source
+`_.
+
+================= ============= ===========
+Library Method Run Time, s
+================= ============= ===========
+EGLIBC 2.19 printf 1.30
+libstdc++ 4.8.2 std::ostream 1.85
+C++ Format 1.0 fmt::print 1.42
+tinyformat 2.0.1 tfm::printf 2.25
+Boost Format 1.54 boost::format 9.94
+================= ============= ===========
+
+As you can see ``boost::format`` is much slower than the alternative methods; this
+is confirmed by `other tests `_.
+Tinyformat is quite good coming close to IOStreams. Unfortunately tinyformat
+cannot be faster than the IOStreams because it uses them internally.
+Performance of cppformat is close to that of printf, being `faster than printf on integer
+formatting `_,
+but slower on floating-point formatting which dominates this benchmark.
+
+Compile time and code bloat
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The script `bloat-test.py
+`_
+from `format-benchmark `_
+tests compile time and code bloat for nontrivial projects.
+It generates 100 translation units and uses ``printf()`` or its alternative
+five times in each to simulate a medium sized project. The resulting
+executable size and compile time (g++-4.8.1, Ubuntu GNU/Linux 13.10,
+best of three) is shown in the following tables.
+
+**Optimized build (-O3)**
+
+============ =============== ==================== ==================
+Method Compile Time, s Executable size, KiB Stripped size, KiB
+============ =============== ==================== ==================
+printf 2.6 41 30
+IOStreams 19.4 92 70
+C++ Format 46.8 46 34
+tinyformat 64.6 418 386
+Boost Format 222.8 990 923
+============ =============== ==================== ==================
+
+As you can see, C++ Format has two times less overhead in terms of resulting
+code size compared to IOStreams and comes pretty close to ``printf``.
+Boost Format has by far the largest overheads.
+
+**Non-optimized build**
+
+============ =============== ==================== ==================
+Method Compile Time, s Executable size, KiB Stripped size, KiB
+============ =============== ==================== ==================
+printf 2.1 41 30
+IOStreams 19.7 86 62
+C++ Format 47.9 108 86
+tinyformat 27.7 234 190
+Boost Format 122.6 884 763
+============ =============== ==================== ==================
+
+``libc``, ``libstdc++`` and ``libformat`` are all linked as shared
+libraries to compare formatting function overhead only. Boost Format
+and tinyformat are header-only libraries so they don't provide any
+linkage options.
+
+Running the tests
+~~~~~~~~~~~~~~~~~
+
+Please refer to `Building the library`__ for the instructions on how to build
+the library and run the unit tests.
+
+__ http://cppformat.github.io/latest/usage.html#building-the-library
+
+Benchmarks reside in a separate repository,
+`format-benchmarks `_,
+so to run the benchmarks you first need to clone this repository and
+generate Makefiles with CMake::
+
+ $ git clone --recursive https://github.com/cppformat/format-benchmark.git
+ $ cd format-benchmark
+ $ cmake .
+
+Then you can run the speed test::
+
+ $ make speed-test
+
+or the bloat test::
+
+ $ make bloat-test
+
+License
+-------
+
+C++ Format is distributed under the BSD `license
+`_.
+
+The `Format String Syntax
+`_
+section in the documentation is based on the one from Python `string module
+documentation `_
+adapted for the current library. For this reason the documentation is
+distributed under the Python Software Foundation license available in
+`doc/python-license.txt
+`_.
+It only applies if you distribute the documentation of C++ Format.
+
+Links
+-----
+
+`API changes/compatibility report `_
+
+Acknowledgments
+---------------
+
+The benchmark section of this readme file and the performance tests are taken
+from the excellent `tinyformat `_ library
+written by Chris Foster. Boost Format library is acknowledged transitively
+since it had some influence on tinyformat.
+Some ideas used in the implementation are borrowed from `Loki
+`_ SafeFormat and `Diagnostic API
+`_ in
+`Clang `_.
+Format string syntax and the documentation are based on Python's `str.format
+`_.
+Thanks `Doug Turnbull `_ for his valuable
+comments and contribution to the design of the type-safe API and
+`Gregory Czajkowski `_ for implementing binary
+formatting. Thanks `Ruslan Baratov `_ for comprehensive
+`comparison of integer formatting algorithms `_
+and useful comments regarding performance, `Boris Kaul `_ for
+`C++ counting digits benchmark `_.
+Thanks to `CarterLi `_ for contributing various
+improvements to the code.
diff --git a/external/CppFormat/format.cc b/external/CppFormat/format.cc
new file mode 100644
index 00000000..daccd68f
--- /dev/null
+++ b/external/CppFormat/format.cc
@@ -0,0 +1,971 @@
+/*
+ Formatting library for C++
+
+ Copyright (c) 2012 - 2015, Victor Zverovich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "format.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include // for std::ptrdiff_t
+
+#if defined(_WIN32) && defined(__MINGW32__)
+# include
+#endif
+
+#if FMT_USE_WINDOWS_H
+# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
+# include
+# else
+# define NOMINMAX
+# include
+# undef NOMINMAX
+# endif
+#endif
+
+using fmt::internal::Arg;
+
+#if FMT_EXCEPTIONS
+# define FMT_TRY try
+# define FMT_CATCH(x) catch (x)
+#else
+# define FMT_TRY if (true)
+# define FMT_CATCH(x) if (false)
+#endif
+
+#ifdef FMT_HEADER_ONLY
+# define FMT_FUNC inline
+#else
+# define FMT_FUNC
+#endif
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4127) // conditional expression is constant
+# pragma warning(disable: 4702) // unreachable code
+// Disable deprecation warning for strerror. The latter is not called but
+// MSVC fails to detect it.
+# pragma warning(disable: 4996)
+#endif
+
+// Dummy implementations of strerror_r and strerror_s called if corresponding
+// system functions are not available.
+static inline fmt::internal::Null<> strerror_r(int, char *, ...) {
+ return fmt::internal::Null<>();
+}
+static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
+ return fmt::internal::Null<>();
+}
+
+namespace fmt {
+namespace {
+
+#ifndef _MSC_VER
+# define FMT_SNPRINTF snprintf
+#else // _MSC_VER
+inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
+ va_end(args);
+ return result;
+}
+# define FMT_SNPRINTF fmt_snprintf
+#endif // _MSC_VER
+
+#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
+# define FMT_SWPRINTF snwprintf
+#else
+# define FMT_SWPRINTF swprintf
+#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
+
+// Checks if a value fits in int - used to avoid warnings about comparing
+// signed and unsigned integers.
+template
+struct IntChecker {
+ template
+ static bool fits_in_int(T value) {
+ unsigned max = INT_MAX;
+ return value <= max;
+ }
+ static bool fits_in_int(bool) { return true; }
+};
+
+template <>
+struct IntChecker {
+ template
+ static bool fits_in_int(T value) {
+ return value >= INT_MIN && value <= INT_MAX;
+ }
+ static bool fits_in_int(int) { return true; }
+};
+
+const char RESET_COLOR[] = "\x1b[0m";
+
+typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
+
+// Portable thread-safe version of strerror.
+// Sets buffer to point to a string describing the error code.
+// This can be either a pointer to a string stored in buffer,
+// or a pointer to some static immutable string.
+// Returns one of the following values:
+// 0 - success
+// ERANGE - buffer is not large enough to store the error message
+// other - failure
+// Buffer should be at least of size 1.
+int safe_strerror(
+ int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
+ FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer");
+
+ class StrError {
+ private:
+ int error_code_;
+ char *&buffer_;
+ std::size_t buffer_size_;
+
+ // A noop assignment operator to avoid bogus warnings.
+ void operator=(const StrError &) {}
+
+ // Handle the result of XSI-compliant version of strerror_r.
+ int handle(int result) {
+ // glibc versions before 2.13 return result in errno.
+ return result == -1 ? errno : result;
+ }
+
+ // Handle the result of GNU-specific version of strerror_r.
+ int handle(char *message) {
+ // If the buffer is full then the message is probably truncated.
+ if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
+ return ERANGE;
+ buffer_ = message;
+ return 0;
+ }
+
+ // Handle the case when strerror_r is not available.
+ int handle(fmt::internal::Null<>) {
+ return fallback(strerror_s(buffer_, buffer_size_, error_code_));
+ }
+
+ // Fallback to strerror_s when strerror_r is not available.
+ int fallback(int result) {
+ // If the buffer is full then the message is probably truncated.
+ return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
+ ERANGE : result;
+ }
+
+ // Fallback to strerror if strerror_r and strerror_s are not available.
+ int fallback(fmt::internal::Null<>) {
+ errno = 0;
+ buffer_ = strerror(error_code_);
+ return errno;
+ }
+
+ public:
+ StrError(int err_code, char *&buf, std::size_t buf_size)
+ : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
+
+ int run() {
+ strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r.
+ return handle(strerror_r(error_code_, buffer_, buffer_size_));
+ }
+ };
+ return StrError(error_code, buffer, buffer_size).run();
+}
+
+void format_error_code(fmt::Writer &out, int error_code,
+ fmt::StringRef message) FMT_NOEXCEPT {
+ // Report error code making sure that the output fits into
+ // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
+ // bad_alloc.
+ out.clear();
+ static const char SEP[] = ": ";
+ static const char ERROR_STR[] = "error ";
+ // 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;
+ typedef fmt::internal::IntTraits::MainType MainType;
+ MainType abs_value = static_cast(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;
+ assert(out.size() <= fmt::internal::INLINE_BUFFER_SIZE);
+}
+
+void report_error(FormatFunc func,
+ int error_code, fmt::StringRef message) FMT_NOEXCEPT {
+ fmt::MemoryWriter full_message;
+ func(full_message, error_code, message);
+ // Use Writer::data instead of Writer::c_str to avoid potential memory
+ // allocation.
+ std::fwrite(full_message.data(), full_message.size(), 1, stderr);
+ std::fputc('\n', stderr);
+}
+
+// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
+class IsZeroInt : public fmt::internal::ArgVisitor {
+ public:
+ template
+ bool visit_any_int(T value) { return value == 0; }
+};
+
+// Checks if an argument is a valid printf width specifier and sets
+// left alignment if it is negative.
+class WidthHandler : public fmt::internal::ArgVisitor {
+ private:
+ fmt::FormatSpec &spec_;
+
+ FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
+
+ public:
+ explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
+
+ void report_unhandled_arg() {
+ FMT_THROW(fmt::FormatError("width is not integer"));
+ }
+
+ template
+ unsigned visit_any_int(T value) {
+ typedef typename fmt::internal::IntTraits::MainType UnsignedType;
+ UnsignedType width = static_cast(value);
+ if (fmt::internal::is_negative(value)) {
+ spec_.align_ = fmt::ALIGN_LEFT;
+ width = 0 - width;
+ }
+ if (width > INT_MAX)
+ FMT_THROW(fmt::FormatError("number is too big"));
+ return static_cast(width);
+ }
+};
+
+class PrecisionHandler :
+ public fmt::internal::ArgVisitor {
+ public:
+ void report_unhandled_arg() {
+ FMT_THROW(fmt::FormatError("precision is not integer"));
+ }
+
+ template
+ int visit_any_int(T value) {
+ if (!IntChecker::is_signed>::fits_in_int(value))
+ FMT_THROW(fmt::FormatError("number is too big"));
+ return static_cast(value);
+ }
+};
+
+template
+struct is_same {
+ enum { value = 0 };
+};
+
+template
+struct is_same {
+ 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
+class ArgConverter : public fmt::internal::ArgVisitor, void> {
+ private:
+ fmt::internal::Arg &arg_;
+ wchar_t type_;
+
+ FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
+
+ public:
+ ArgConverter(fmt::internal::Arg &arg, wchar_t type)
+ : arg_(arg), type_(type) {}
+
+ void visit_bool(bool value) {
+ if (type_ != 's')
+ visit_any_int(value);
+ }
+
+ template
+ void visit_any_int(U value) {
+ bool is_signed = type_ == 'd' || type_ == 'i';
+ using fmt::internal::Arg;
+ typedef typename fmt::internal::Conditional<
+ is_same::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(static_cast(value));
+ } else {
+ arg_.type = Arg::UINT;
+ typedef typename fmt::internal::MakeUnsigned::Type Unsigned;
+ arg_.uint_value = static_cast(static_cast(value));
+ }
+ } else {
+ if (is_signed) {
+ arg_.type = Arg::LONG_LONG;
+ // 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(value);
+ } else {
+ arg_.type = Arg::ULONG_LONG;
+ arg_.ulong_long_value =
+ static_cast::Type>(value);
+ }
+ }
+ }
+};
+
+// Converts an integer argument to char for printf.
+class CharConverter : public fmt::internal::ArgVisitor {
+ private:
+ fmt::internal::Arg &arg_;
+
+ FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
+
+ public:
+ explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
+
+ template
+ void visit_any_int(T value) {
+ arg_.type = Arg::CHAR;
+ arg_.int_value = static_cast(value);
+ }
+};
+
+// Write the content of w to os.
+void write(std::ostream &os, fmt::Writer &w) {
+ const char *data = w.data();
+ typedef internal::MakeUnsigned::Type UnsignedStreamSize;
+ UnsignedStreamSize size = w.size();
+ UnsignedStreamSize max_size =
+ internal::to_unsigned((std::numeric_limits::max)());
+ do {
+ UnsignedStreamSize n = size <= max_size ? size : max_size;
+ os.write(data, static_cast(n));
+ data += n;
+ size -= n;
+ } while (size != 0);
+}
+} // namespace
+
+namespace internal {
+
+template
+class PrintfArgFormatter :
+ public ArgFormatterBase, Char> {
+
+ void write_null_pointer() {
+ this->spec().type_ = 0;
+ this->write("(nil)");
+ }
+
+ typedef ArgFormatterBase, Char> Base;
+
+ public:
+ PrintfArgFormatter(BasicWriter &w, FormatSpec &s)
+ : ArgFormatterBase, Char>(w, s) {}
+
+ void visit_bool(bool value) {
+ FormatSpec &fmt_spec = this->spec();
+ if (fmt_spec.type_ != 's')
+ return this->visit_any_int(value);
+ fmt_spec.type_ = 0;
+ this->write(value);
+ }
+
+ void visit_char(int value) {
+ const FormatSpec &fmt_spec = this->spec();
+ BasicWriter &w = this->writer();
+ if (fmt_spec.type_ && fmt_spec.type_ != 'c')
+ w.write_int(value, fmt_spec);
+ typedef typename BasicWriter::CharPtr CharPtr;
+ CharPtr out = CharPtr();
+ if (fmt_spec.width_ > 1) {
+ Char fill = ' ';
+ out = w.grow_buffer(fmt_spec.width_);
+ if (fmt_spec.align_ != ALIGN_LEFT) {
+ std::fill_n(out, fmt_spec.width_ - 1, fill);
+ out += fmt_spec.width_ - 1;
+ } else {
+ std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
+ }
+ } else {
+ out = w.grow_buffer(1);
+ }
+ *out = static_cast(value);
+ }
+
+ void visit_cstring(const char *value) {
+ if (value)
+ Base::visit_cstring(value);
+ else if (this->spec().type_ == 'p')
+ write_null_pointer();
+ else
+ this->write("(null)");
+ }
+
+ void visit_pointer(const void *value) {
+ if (value)
+ return Base::visit_pointer(value);
+ this->spec().type_ = 0;
+ write_null_pointer();
+ }
+
+ void visit_custom(Arg::CustomValue c) {
+ BasicFormatter formatter(ArgList(), this->writer());
+ const Char format_str[] = {'}', 0};
+ const Char *format = format_str;
+ c.format(&formatter, c.value, &format);
+ }
+};
+} // namespace internal
+} // namespace fmt
+
+FMT_FUNC void fmt::SystemError::init(
+ int err_code, CStringRef format_str, ArgList args) {
+ error_code_ = err_code;
+ MemoryWriter w;
+ internal::format_system_error(w, err_code, format(format_str, args));
+ std::runtime_error &base = *this;
+ base = std::runtime_error(w.str());
+}
+
+template
+int fmt::internal::CharTraits::format_float(
+ char *buffer, std::size_t size, const char *format,
+ unsigned width, int precision, T value) {
+ if (width == 0) {
+ return precision < 0 ?
+ FMT_SNPRINTF(buffer, size, format, value) :
+ FMT_SNPRINTF(buffer, size, format, precision, value);
+ }
+ return precision < 0 ?
+ FMT_SNPRINTF(buffer, size, format, width, value) :
+ FMT_SNPRINTF(buffer, size, format, width, precision, value);
+}
+
+template
+int fmt::internal::CharTraits::format_float(
+ wchar_t *buffer, std::size_t size, const wchar_t *format,
+ unsigned width, int precision, T value) {
+ if (width == 0) {
+ return precision < 0 ?
+ FMT_SWPRINTF(buffer, size, format, value) :
+ FMT_SWPRINTF(buffer, size, format, precision, value);
+ }
+ return precision < 0 ?
+ FMT_SWPRINTF(buffer, size, format, width, value) :
+ FMT_SWPRINTF(buffer, size, format, width, precision, value);
+}
+
+template
+const char fmt::internal::BasicData::DIGITS[] =
+ "0001020304050607080910111213141516171819"
+ "2021222324252627282930313233343536373839"
+ "4041424344454647484950515253545556575859"
+ "6061626364656667686970717273747576777879"
+ "8081828384858687888990919293949596979899";
+
+#define FMT_POWERS_OF_10(factor) \
+ factor * 10, \
+ factor * 100, \
+ factor * 1000, \
+ factor * 10000, \
+ factor * 100000, \
+ factor * 1000000, \
+ factor * 10000000, \
+ factor * 100000000, \
+ factor * 1000000000
+
+template
+const uint32_t fmt::internal::BasicData::POWERS_OF_10_32[] = {
+ 0, FMT_POWERS_OF_10(1)
+};
+
+template
+const uint64_t fmt::internal::BasicData::POWERS_OF_10_64[] = {
+ 0,
+ FMT_POWERS_OF_10(1),
+ FMT_POWERS_OF_10(fmt::ULongLong(1000000000)),
+ // Multiply several constants instead of using a single long long constant
+ // to avoid warnings about C++98 not supporting long long.
+ fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10
+};
+
+FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
+ (void)type;
+ if (std::isprint(static_cast(code))) {
+ FMT_THROW(fmt::FormatError(
+ fmt::format("unknown format code '{}' for {}", code, type)));
+ }
+ FMT_THROW(fmt::FormatError(
+ fmt::format("unknown format code '\\x{:02x}' for {}",
+ static_cast(code), type)));
+}
+
+#if FMT_USE_WINDOWS_H
+
+FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
+ static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
+ if (s.size() > INT_MAX)
+ FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
+ int s_size = static_cast(s.size());
+ int length = MultiByteToWideChar(
+ CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
+ if (length == 0)
+ FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
+ buffer_.resize(length + 1);
+ length = MultiByteToWideChar(
+ CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
+ if (length == 0)
+ FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
+ buffer_[length] = 0;
+}
+
+FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
+ if (int error_code = convert(s)) {
+ FMT_THROW(WindowsError(error_code,
+ "cannot convert string from UTF-16 to UTF-8"));
+ }
+}
+
+FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
+ if (s.size() > INT_MAX)
+ return ERROR_INVALID_PARAMETER;
+ int s_size = static_cast(s.size());
+ int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
+ if (length == 0)
+ return GetLastError();
+ buffer_.resize(length + 1);
+ length = WideCharToMultiByte(
+ CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
+ if (length == 0)
+ return GetLastError();
+ buffer_[length] = 0;
+ return 0;
+}
+
+FMT_FUNC void fmt::WindowsError::init(
+ int err_code, CStringRef format_str, ArgList args) {
+ error_code_ = err_code;
+ MemoryWriter w;
+ internal::format_windows_error(w, err_code, format(format_str, args));
+ std::runtime_error &base = *this;
+ base = std::runtime_error(w.str());
+}
+
+FMT_FUNC void fmt::internal::format_windows_error(
+ fmt::Writer &out, int error_code,
+ fmt::StringRef message) FMT_NOEXCEPT {
+ FMT_TRY {
+ MemoryBuffer 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(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.
+}
+
+#endif // FMT_USE_WINDOWS_H
+
+FMT_FUNC void fmt::internal::format_system_error(
+ fmt::Writer &out, int error_code,
+ fmt::StringRef message) FMT_NOEXCEPT {
+ FMT_TRY {
+ MemoryBuffer buffer;
+ buffer.resize(INLINE_BUFFER_SIZE);
+ for (;;) {
+ char *system_message = &buffer[0];
+ int result = safe_strerror(error_code, system_message, buffer.size());
+ if (result == 0) {
+ out << message << ": " << system_message;
+ return;
+ }
+ if (result != ERANGE)
+ 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.
+}
+
+template
+void fmt::internal::ArgMap::init(const ArgList &args) {
+ if (!map_.empty())
+ return;
+ typedef internal::NamedArg NamedArg;
+ const NamedArg *named_arg = 0;
+ bool use_values =
+ args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
+ if (use_values) {
+ for (unsigned i = 0;/*nothing*/; ++i) {
+ internal::Arg::Type arg_type = args.type(i);
+ switch (arg_type) {
+ case internal::Arg::NONE:
+ return;
+ case internal::Arg::NAMED_ARG:
+ named_arg = static_cast(args.values_[i].pointer);
+ map_.push_back(Pair(named_arg->name, *named_arg));
+ break;
+ default:
+ /*nothing*/;
+ }
+ }
+ return;
+ }
+ for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
+ internal::Arg::Type arg_type = args.type(i);
+ if (arg_type == internal::Arg::NAMED_ARG) {
+ named_arg = static_cast(args.args_[i].pointer);
+ map_.push_back(Pair(named_arg->name, *named_arg));
+ }
+ }
+ for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
+ switch (args.args_[i].type) {
+ case internal::Arg::NONE:
+ return;
+ case internal::Arg::NAMED_ARG:
+ named_arg = static_cast(args.args_[i].pointer);
+ map_.push_back(Pair(named_arg->name, *named_arg));
+ break;
+ default:
+ /*nothing*/;
+ }
+ }
+}
+
+template
+void fmt::internal::FixedBuffer::grow(std::size_t) {
+ FMT_THROW(std::runtime_error("buffer overflow"));
+}
+
+FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
+ unsigned arg_index, const char *&error) {
+ Arg arg = args_[arg_index];
+ switch (arg.type) {
+ case Arg::NONE:
+ error = "argument index out of range";
+ break;
+ case Arg::NAMED_ARG:
+ arg = *static_cast(arg.pointer);
+ break;
+ default:
+ /*nothing*/;
+ }
+ return arg;
+}
+
+template
+void fmt::internal::PrintfFormatter::parse_flags(
+ FormatSpec &spec, const Char *&s) {
+ for (;;) {
+ switch (*s++) {
+ case '-':
+ spec.align_ = ALIGN_LEFT;
+ break;
+ case '+':
+ spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
+ break;
+ case '0':
+ spec.fill_ = '0';
+ break;
+ case ' ':
+ spec.flags_ |= SIGN_FLAG;
+ break;
+ case '#':
+ spec.flags_ |= HASH_FLAG;
+ break;
+ default:
+ --s;
+ return;
+ }
+ }
+}
+
+template
+Arg fmt::internal::PrintfFormatter::get_arg(
+ const Char *s, unsigned arg_index) {
+ (void)s;
+ const char *error = 0;
+ Arg arg = arg_index == UINT_MAX ?
+ next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
+ if (error)
+ FMT_THROW(FormatError(!*s ? "invalid format string" : error));
+ return arg;
+}
+
+template
+unsigned fmt::internal::PrintfFormatter::parse_header(
+ const Char *&s, FormatSpec &spec) {
+ unsigned arg_index = UINT_MAX;
+ Char c = *s;
+ if (c >= '0' && c <= '9') {
+ // Parse an argument index (if followed by '$') or a width possibly
+ // preceded with '0' flag(s).
+ unsigned value = parse_nonnegative_int(s);
+ if (*s == '$') { // value is an argument index
+ ++s;
+ arg_index = value;
+ } else {
+ if (c == '0')
+ spec.fill_ = '0';
+ if (value != 0) {
+ // Nonzero value means that we parsed width and don't need to
+ // parse it or flags again, so return now.
+ spec.width_ = value;
+ return arg_index;
+ }
+ }
+ }
+ parse_flags(spec, s);
+ // Parse width.
+ if (*s >= '0' && *s <= '9') {
+ spec.width_ = parse_nonnegative_int(s);
+ } else if (*s == '*') {
+ ++s;
+ spec.width_ = WidthHandler(spec).visit(get_arg(s));
+ }
+ return arg_index;
+}
+
+template
+void fmt::internal::PrintfFormatter::format(
+ BasicWriter &writer, BasicCStringRef format_str) {
+ const Char *start = format_str.c_str();
+ const Char *s = start;
+ while (*s) {
+ Char c = *s++;
+ if (c != '%') continue;
+ if (*s == c) {
+ write(writer, start, s);
+ start = ++s;
+ continue;
+ }
+ write(writer, start, s - 1);
+
+ FormatSpec spec;
+ spec.align_ = ALIGN_RIGHT;
+
+ // Parse argument index, flags and width.
+ unsigned arg_index = parse_header(s, spec);
+
+ // Parse precision.
+ if (*s == '.') {
+ ++s;
+ if ('0' <= *s && *s <= '9') {
+ spec.precision_ = static_cast(parse_nonnegative_int(s));
+ } else if (*s == '*') {
+ ++s;
+ spec.precision_ = PrecisionHandler().visit(get_arg(s));
+ }
+ }
+
+ Arg arg = get_arg(s, arg_index);
+ if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
+ spec.flags_ &= ~to_unsigned(HASH_FLAG);
+ if (spec.fill_ == '0') {
+ if (arg.type <= Arg::LAST_NUMERIC_TYPE)
+ spec.align_ = ALIGN_NUMERIC;
+ else
+ spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
+ }
+
+ // Parse length and convert the argument to the required type.
+ switch (*s++) {
+ case 'h':
+ if (*s == 'h')
+ ArgConverter(arg, *++s).visit(arg);
+ else
+ ArgConverter(arg, *s).visit(arg);
+ break;
+ case 'l':
+ if (*s == 'l')
+ ArgConverter(arg, *++s).visit(arg);
+ else
+ ArgConverter(arg, *s).visit(arg);
+ break;
+ case 'j':
+ ArgConverter(arg, *s).visit(arg);
+ break;
+ case 'z':
+ ArgConverter(arg, *s).visit(arg);
+ break;
+ case 't':
+ ArgConverter(arg, *s).visit(arg);
+ break;
+ case 'L':
+ // printf produces garbage when 'L' is omitted for long double, no
+ // need to do the same.
+ break;
+ default:
+ --s;
+ ArgConverter(arg, *s).visit(arg);
+ }
+
+ // Parse type.
+ if (!*s)
+ FMT_THROW(FormatError("invalid format string"));
+ spec.type_ = static_cast(*s++);
+ if (arg.type <= Arg::LAST_INTEGER_TYPE) {
+ // Normalize type.
+ switch (spec.type_) {
+ case 'i': case 'u':
+ spec.type_ = 'd';
+ break;
+ case 'c':
+ // TODO: handle wchar_t
+ CharConverter(arg).visit(arg);
+ break;
+ }
+ }
+
+ start = s;
+
+ // Format argument.
+ internal::PrintfArgFormatter(writer, spec).visit(arg);
+ }
+ write(writer, start, s);
+}
+
+FMT_FUNC void fmt::report_system_error(
+ int error_code, fmt::StringRef message) FMT_NOEXCEPT {
+ // 'fmt::' is for bcc32.
+ fmt::report_error(internal::format_system_error, error_code, message);
+}
+
+#if FMT_USE_WINDOWS_H
+FMT_FUNC void fmt::report_windows_error(
+ int error_code, fmt::StringRef message) FMT_NOEXCEPT {
+ // 'fmt::' is for bcc32.
+ fmt::report_error(internal::format_windows_error, error_code, message);
+}
+#endif
+
+FMT_FUNC void fmt::print(std::FILE *f, CStringRef format_str, ArgList args) {
+ MemoryWriter w;
+ w.write(format_str, args);
+ std::fwrite(w.data(), 1, w.size(), f);
+}
+
+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) {
+ MemoryWriter w;
+ w.write(format_str, args);
+ write(os, w);
+}
+
+FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) {
+ char escape[] = "\x1b[30m";
+ escape[3] = static_cast('0' + c);
+ std::fputs(escape, stdout);
+ print(format, args);
+ std::fputs(RESET_COLOR, stdout);
+}
+
+FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) {
+ MemoryWriter w;
+ printf(w, format, args);
+ std::size_t size = w.size();
+ return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast(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(w.size());
+}
+
+#ifndef FMT_HEADER_ONLY
+
+template struct fmt::internal::BasicData;
+
+// Explicit instantiations for char.
+
+template void fmt::internal::FixedBuffer::grow(std::size_t);
+
+template void fmt::internal::ArgMap::init(const fmt::ArgList &args);
+
+template void fmt::internal::PrintfFormatter::format(
+ BasicWriter &writer, CStringRef format);
+
+template int fmt::internal::CharTraits::format_float(
+ char *buffer, std::size_t size, const char *format,
+ unsigned width, int precision, double value);
+
+template int fmt::internal::CharTraits::format_float(
+ char *buffer, std::size_t size, const char *format,
+ unsigned width, int precision, long double value);
+
+// Explicit instantiations for wchar_t.
+
+template void fmt::internal::FixedBuffer::grow(std::size_t);
+
+template void fmt::internal::ArgMap::init(const fmt::ArgList &args);
+
+template void fmt::internal::PrintfFormatter::format(
+ BasicWriter &writer, WCStringRef format);
+
+template int fmt::internal::CharTraits::format_float(
+ wchar_t *buffer, std::size_t size, const wchar_t *format,
+ unsigned width, int precision, double value);
+
+template int fmt::internal::CharTraits::format_float(
+ wchar_t *buffer, std::size_t size, const wchar_t *format,
+ unsigned width, int precision, long double value);
+
+#endif // FMT_HEADER_ONLY
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
diff --git a/include/format.h b/include/format.h
new file mode 100644
index 00000000..67f02f22
--- /dev/null
+++ b/include/format.h
@@ -0,0 +1,3793 @@
+/*
+ Formatting library for C++
+
+ Copyright (c) 2012 - 2015, Victor Zverovich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FMT_FORMAT_H_
+#define FMT_FORMAT_H_
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifndef FMT_USE_IOSTREAMS
+# define FMT_USE_IOSTREAMS 1
+#endif
+
+#if FMT_USE_IOSTREAMS
+# include
+#endif
+
+#ifdef _SECURE_SCL
+# define FMT_SECURE_SCL _SECURE_SCL
+#else
+# define FMT_SECURE_SCL 0
+#endif
+
+#if FMT_SECURE_SCL
+# include
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER <= 1500
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+typedef __int64 intmax_t;
+#else
+#include
+#endif
+
+#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
+#endif
+#ifndef FMT_API
+# define FMT_API
+#endif
+
+#ifdef __GNUC__
+# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
+# define FMT_GCC_EXTENSION __extension__
+# if FMT_GCC_VERSION >= 406
+# pragma GCC diagnostic push
+// Disable the warning about "long long" which is sometimes reported even
+// when using __extension__.
+# pragma GCC diagnostic ignored "-Wlong-long"
+// Disable the warning about declaration shadowing because it affects too
+// many valid cases.
+# pragma GCC diagnostic ignored "-Wshadow"
+// Disable the warning about implicit conversions that may change the sign of
+// an integer; silencing it otherwise would require many explicit casts.
+# pragma GCC diagnostic ignored "-Wsign-conversion"
+# endif
+# if __cplusplus >= 201103L || defined __GXX_EXPERIMENTAL_CXX0X__
+# define FMT_HAS_GXX_CXX11 1
+# endif
+#else
+# define FMT_GCC_EXTENSION
+#endif
+
+#if defined(__clang__) && !defined(__INTEL_COMPILER)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdocumentation"
+#endif
+
+#ifdef __GNUC_LIBSTD__
+# define FMT_GNUC_LIBSTD_VERSION (__GNUC_LIBSTD__ * 100 + __GNUC_LIBSTD_MINOR__)
+#endif
+
+#ifdef __has_feature
+# define FMT_HAS_FEATURE(x) __has_feature(x)
+#else
+# define FMT_HAS_FEATURE(x) 0
+#endif
+
+#ifdef __has_builtin
+# define FMT_HAS_BUILTIN(x) __has_builtin(x)
+#else
+# define FMT_HAS_BUILTIN(x) 0
+#endif
+
+#ifdef __has_cpp_attribute
+# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
+#else
+# define FMT_HAS_CPP_ATTRIBUTE(x) 0
+#endif
+
+#ifndef FMT_USE_VARIADIC_TEMPLATES
+// Variadic templates are available in GCC since version 4.4
+// (http://gcc.gnu.org/projects/cxx0x.html) and in Visual C++
+// since version 2013.
+# define FMT_USE_VARIADIC_TEMPLATES \
+ (FMT_HAS_FEATURE(cxx_variadic_templates) || \
+ (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1800)
+#endif
+
+#ifndef FMT_USE_RVALUE_REFERENCES
+// Don't use rvalue references when compiling with clang and an old libstdc++
+// as the latter doesn't provide std::move.
+# if defined(FMT_GNUC_LIBSTD_VERSION) && FMT_GNUC_LIBSTD_VERSION <= 402
+# define FMT_USE_RVALUE_REFERENCES 0
+# else
+# define FMT_USE_RVALUE_REFERENCES \
+ (FMT_HAS_FEATURE(cxx_rvalue_references) || \
+ (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600)
+# endif
+#endif
+
+#if FMT_USE_RVALUE_REFERENCES
+# include // for std::move
+#endif
+
+// Check if exceptions are disabled.
+#if defined(__GNUC__) && !defined(__EXCEPTIONS)
+# define FMT_EXCEPTIONS 0
+#endif
+#if defined(_MSC_VER) && !_HAS_EXCEPTIONS
+# define FMT_EXCEPTIONS 0
+#endif
+#ifndef FMT_EXCEPTIONS
+# define FMT_EXCEPTIONS 1
+#endif
+
+#ifndef FMT_THROW
+# if FMT_EXCEPTIONS
+# define FMT_THROW(x) throw x
+# else
+# define FMT_THROW(x) assert(false)
+# 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
+# define FMT_USE_DELETED_FUNCTIONS 0
+#endif
+
+#if FMT_USE_DELETED_FUNCTIONS || FMT_HAS_FEATURE(cxx_deleted_functions) || \
+ (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1800
+# define FMT_DELETED_OR_UNDEFINED = delete
+# define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&) = delete; \
+ TypeName& operator=(const TypeName&) = delete
+#else
+# define FMT_DELETED_OR_UNDEFINED
+# define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&); \
+ TypeName& operator=(const TypeName&)
+#endif
+
+#ifndef FMT_USE_USER_DEFINED_LITERALS
+// All compilers which support UDLs also support variadic templates. This
+// makes the fmt::literals implementation easier. However, an explicit check
+// for variadic templates is added here just in case.
+# define FMT_USE_USER_DEFINED_LITERALS \
+ FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES && \
+ (FMT_HAS_FEATURE(cxx_user_literals) || \
+ (FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1900)
+#endif
+
+#ifndef FMT_ASSERT
+# 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 // _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(x >> 32)))
+ return 63 - (r + 32);
+
+ // Scan the low 32 bits.
+ _BitScanReverse(&r, static_cast(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 {
+ int data[2];
+ operator int() const { return 0; }
+};
+typedef std::numeric_limits FPUtil;
+
+// Dummy implementations of system functions such as signbit and ecvt called
+// if the latter are not available.
+inline DummyInt signbit(...) { return DummyInt(); }
+inline DummyInt _ecvt_s(...) { return DummyInt(); }
+inline DummyInt isinf(...) { return DummyInt(); }
+inline DummyInt _finite(...) { return DummyInt(); }
+inline DummyInt isnan(...) { return DummyInt(); }
+inline DummyInt _isnan(...) { return DummyInt(); }
+
+// A helper function to suppress bogus "conditional expression is constant"
+// warnings.
+template
+inline T check(T value) { return value; }
+}
+} // namespace fmt
+
+namespace std {
+// Standard permits specialization of std::numeric_limits. This specialization
+// is used to resolve ambiguity between isinf and std::isinf in glibc:
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48891
+// and the same for isnan and signbit.
+template <>
+class numeric_limits :
+ public std::numeric_limits {
+ public:
+ // Portable version of isinf.
+ template
+ static bool isinfinity(T x) {
+ using namespace fmt::internal;
+ // The resolution "priority" is:
+ // isinf macro > std::isinf > ::isinf > fmt::internal::isinf
+ if (check(sizeof(isinf(x)) == sizeof(bool) ||
+ sizeof(isinf(x)) == sizeof(int))) {
+ return isinf(x) != 0;
+ }
+ return !_finite(static_cast(x));
+ }
+
+ // Portable version of isnan.
+ template
+ static bool isnotanumber(T x) {
+ using namespace fmt::internal;
+ if (check(sizeof(isnan(x)) == sizeof(bool) ||
+ sizeof(isnan(x)) == sizeof(int))) {
+ return isnan(x) != 0;
+ }
+ return _isnan(static_cast(x)) != 0;
+ }
+
+ // Portable version of signbit.
+ static bool isnegative(double x) {
+ using namespace fmt::internal;
+ if (check(sizeof(signbit(x)) == sizeof(int)))
+ return signbit(x) != 0;
+ if (x < 0) return true;
+ if (!isnotanumber(x)) return false;
+ int dec = 0, sign = 0;
+ char buffer[2]; // The buffer size must be >= 2 or _ecvt_s will fail.
+ _ecvt_s(buffer, sizeof(buffer), x, 0, &dec, &sign);
+ return sign != 0;
+ }
+};
+} // namespace std
+
+namespace fmt {
+
+// Fix the warning about long long on older versions of GCC
+// that don't support the diagnostic pragma.
+FMT_GCC_EXTENSION typedef long long LongLong;
+FMT_GCC_EXTENSION typedef unsigned long long ULongLong;
+
+#if FMT_USE_RVALUE_REFERENCES
+using std::move;
+#endif
+
+template
+class BasicWriter;
+
+typedef BasicWriter Writer;
+typedef BasicWriter WWriter;
+
+namespace internal {
+template
+class BasicArgFormatter;
+}
+
+template >
+class BasicFormatter;
+
+template
+void format(BasicFormatter