Large diffs are not rendered by default.

@@ -1,23 +1,27 @@
Copyright (c) 2012 - 2016, Victor Zverovich
Copyright (c) 2012 - present, Victor Zverovich

All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

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.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

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.
--- Optional exception to the license ---

As an exception, if, as a result of your compiling your source code, portions
of this Software are embedded into a machine-executable object form of such
source code, you may redistribute such embedded portions in such object form
without including the above copyright and permission notices.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

@@ -8,65 +8,65 @@
#ifndef FMT_LOCALE_H_
#define FMT_LOCALE_H_

#include "format.h"
#include <locale>
#include "format.h"

FMT_BEGIN_NAMESPACE

namespace internal {
template <typename Char>
typename buffer_context<Char>::type::iterator vformat_to(
const std::locale &loc, basic_buffer<Char> &buf,
typename buffer_context<Char>::iterator vformat_to(
const std::locale& loc, buffer<Char>& buf,
basic_string_view<Char> format_str,
basic_format_args<typename buffer_context<Char>::type> args) {
typedef back_insert_range<basic_buffer<Char> > range;
return vformat_to<arg_formatter<range>>(
buf, to_string_view(format_str), args, internal::locale_ref(loc));
basic_format_args<buffer_context<Char>> args) {
using range = buffer_range<Char>;
return vformat_to<arg_formatter<range>>(buf, to_string_view(format_str), args,
internal::locale_ref(loc));
}

template <typename Char>
std::basic_string<Char> vformat(
const std::locale &loc, basic_string_view<Char> format_str,
basic_format_args<typename buffer_context<Char>::type> args) {
std::basic_string<Char> vformat(const std::locale& loc,
basic_string_view<Char> format_str,
basic_format_args<buffer_context<Char>> args) {
basic_memory_buffer<Char> buffer;
internal::vformat_to(loc, buffer, format_str, args);
return fmt::to_string(buffer);
}
}
} // namespace internal

template <typename S, typename Char = FMT_CHAR(S)>
template <typename S, typename Char = char_t<S>>
inline std::basic_string<Char> vformat(
const std::locale &loc, const S &format_str,
basic_format_args<typename buffer_context<Char>::type> args) {
const std::locale& loc, const S& format_str,
basic_format_args<buffer_context<Char>> args) {
return internal::vformat(loc, to_string_view(format_str), args);
}

template <typename S, typename... Args>
inline std::basic_string<FMT_CHAR(S)> format(
const std::locale &loc, const S &format_str, const Args &... args) {
template <typename S, typename... Args, typename Char = char_t<S>>
inline std::basic_string<Char> format(const std::locale& loc,
const S& format_str, Args&&... args) {
return internal::vformat(
loc, to_string_view(format_str),
*internal::checked_args<S, Args...>(format_str, args...));
loc, to_string_view(format_str),
{internal::make_args_checked<Args...>(format_str, args...)});
}

template <typename String, typename OutputIt, typename... Args>
inline typename std::enable_if<internal::is_output_iterator<OutputIt>::value,
OutputIt>::type
vformat_to(OutputIt out, const std::locale &loc, const String &format_str,
typename format_args_t<OutputIt, FMT_CHAR(String)>::type args) {
typedef output_range<OutputIt, FMT_CHAR(String)> range;
template <typename S, typename OutputIt, typename... Args,
typename Char = enable_if_t<
internal::is_output_iterator<OutputIt>::value, char_t<S>>>
inline OutputIt vformat_to(OutputIt out, const std::locale& loc,
const S& format_str,
format_args_t<OutputIt, Char> args) {
using range = internal::output_range<OutputIt, Char>;
return vformat_to<arg_formatter<range>>(
range(out), to_string_view(format_str), args, internal::locale_ref(loc));
range(out), to_string_view(format_str), args, internal::locale_ref(loc));
}

template <typename OutputIt, typename S, typename... Args>
inline typename std::enable_if<
internal::is_string<S>::value &&
internal::is_output_iterator<OutputIt>::value, OutputIt>::type
format_to(OutputIt out, const std::locale &loc, const S &format_str,
const Args &... args) {
template <typename OutputIt, typename S, typename... Args,
FMT_ENABLE_IF(internal::is_output_iterator<OutputIt>::value&&
internal::is_string<S>::value)>
inline OutputIt format_to(OutputIt out, const std::locale& loc,
const S& format_str, Args&&... args) {
internal::check_format_string<Args...>(format_str);
typedef typename format_context_t<OutputIt, FMT_CHAR(S)>::type context;
using context = format_context_t<OutputIt, char_t<S>>;
format_arg_store<context, Args...> as{args...};
return vformat_to(out, loc, to_string_view(format_str),
basic_format_args<context>(as));
@@ -8,22 +8,21 @@
#ifndef FMT_OSTREAM_H_
#define FMT_OSTREAM_H_

#include "format.h"
#include <ostream>
#include "format.h"

FMT_BEGIN_NAMESPACE
namespace internal {

template <class Char>
class formatbuf : public std::basic_streambuf<Char> {
template <class Char> class formatbuf : public std::basic_streambuf<Char> {
private:
typedef typename std::basic_streambuf<Char>::int_type int_type;
typedef typename std::basic_streambuf<Char>::traits_type traits_type;
using int_type = typename std::basic_streambuf<Char>::int_type;
using traits_type = typename std::basic_streambuf<Char>::traits_type;

basic_buffer<Char> &buffer_;
buffer<Char>& buffer_;

public:
formatbuf(basic_buffer<Char> &buffer) : buffer_(buffer) {}
formatbuf(buffer<Char>& buf) : buffer_(buf) {}

protected:
// The put-area is actually always empty. This makes the implementation
@@ -39,99 +38,89 @@ class formatbuf : public std::basic_streambuf<Char> {
return ch;
}

std::streamsize xsputn(const Char *s, std::streamsize count) FMT_OVERRIDE {
std::streamsize xsputn(const Char* s, std::streamsize count) FMT_OVERRIDE {
buffer_.append(s, s + count);
return count;
}
};

template <typename Char>
struct test_stream : std::basic_ostream<Char> {
template <typename Char> struct test_stream : std::basic_ostream<Char> {
private:
struct null;
// Hide all operator<< from std::basic_ostream<Char>.
void operator<<(null);
void_t<> operator<<(null<>);
void_t<> operator<<(const Char*);

template <typename T, FMT_ENABLE_IF(std::is_convertible<T, int>::value &&
!std::is_enum<T>::value)>
void_t<> operator<<(T);
};

// Checks if T has a user-defined operator<< (e.g. not a member of std::ostream).
template <typename T, typename Char>
class is_streamable {
// Checks if T has a user-defined operator<< (e.g. not a member of
// std::ostream).
template <typename T, typename Char> class is_streamable {
private:
template <typename U>
static decltype(
internal::declval<test_stream<Char>&>()
<< internal::declval<U>(), std::true_type()) test(int);
static bool_constant<!std::is_same<decltype(std::declval<test_stream<Char>&>()
<< std::declval<U>()),
void_t<>>::value>
test(int);

template <typename>
static std::false_type test(...);
template <typename> static std::false_type test(...);

typedef decltype(test<T>(0)) result;
using result = decltype(test<T>(0));

public:
static const bool value = result::value;
};

// Write the content of buf to os.
template <typename Char>
void write(std::basic_ostream<Char> &os, basic_buffer<Char> &buf) {
const Char *data = buf.data();
typedef std::make_unsigned<std::streamsize>::type UnsignedStreamSize;
UnsignedStreamSize size = buf.size();
UnsignedStreamSize max_size =
internal::to_unsigned((std::numeric_limits<std::streamsize>::max)());
void write(std::basic_ostream<Char>& os, buffer<Char>& buf) {
const Char* buf_data = buf.data();
using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
unsigned_streamsize size = buf.size();
unsigned_streamsize max_size = to_unsigned(max_value<std::streamsize>());
do {
UnsignedStreamSize n = size <= max_size ? size : max_size;
os.write(data, static_cast<std::streamsize>(n));
data += n;
unsigned_streamsize n = size <= max_size ? size : max_size;
os.write(buf_data, static_cast<std::streamsize>(n));
buf_data += n;
size -= n;
} while (size != 0);
}

template <typename Char, typename T>
void format_value(basic_buffer<Char> &buffer, const T &value) {
internal::formatbuf<Char> format_buf(buffer);
void format_value(buffer<Char>& buf, const T& value,
locale_ref loc = locale_ref()) {
formatbuf<Char> format_buf(buf);
std::basic_ostream<Char> output(&format_buf);
if (loc) output.imbue(loc.get<std::locale>());
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
output << value;
buffer.resize(buffer.size());
buf.resize(buf.size());
}
} // namespace internal

// Disable conversion to int if T has an overloaded operator<< which is a free
// function (not a member of std::ostream).
template <typename T, typename Char>
struct convert_to_int<T, Char, void> {
static const bool value =
convert_to_int<T, Char, int>::value &&
!internal::is_streamable<T, Char>::value;
};

// Formats an object of type T that has an overloaded ostream operator<<.
template <typename T, typename Char>
struct formatter<T, Char,
typename std::enable_if<
internal::is_streamable<T, Char>::value &&
!internal::format_type<
typename buffer_context<Char>::type, T>::value>::type>
struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>
: formatter<basic_string_view<Char>, Char> {

template <typename Context>
auto format(const T &value, Context &ctx) -> decltype(ctx.out()) {
auto format(const T& value, Context& ctx) -> decltype(ctx.out()) {
basic_memory_buffer<Char> buffer;
internal::format_value(buffer, value);
format_value(buffer, value, ctx.locale());
basic_string_view<Char> str(buffer.data(), buffer.size());
return formatter<basic_string_view<Char>, Char>::format(str, ctx);
}
};
} // namespace internal

template <typename Char>
inline void vprint(std::basic_ostream<Char> &os,
basic_string_view<Char> format_str,
basic_format_args<typename buffer_context<Char>::type> args) {
void vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str,
basic_format_args<buffer_context<Char>> args) {
basic_memory_buffer<Char> buffer;
internal::vformat_to(buffer, format_str, args);
internal::write(os, buffer);
}

/**
\rst
Prints formatted data to the stream *os*.
@@ -141,12 +130,11 @@ inline void vprint(std::basic_ostream<Char> &os,
fmt::print(cerr, "Don't {}!", "panic");
\endrst
*/
template <typename S, typename... Args>
inline typename std::enable_if<internal::is_string<S>::value>::type
print(std::basic_ostream<FMT_CHAR(S)> &os, const S &format_str,
const Args & ... args) {
internal::checked_args<S, Args...> ca(format_str, args...);
vprint(os, to_string_view(format_str), *ca);
template <typename S, typename... Args,
typename Char = enable_if_t<internal::is_string<S>::value, char_t<S>>>
void print(std::basic_ostream<Char>& os, const S& format_str, Args&&... args) {
vprint(os, to_string_view(format_str),
{internal::make_args_checked<Args...>(format_str, args...)});
}
FMT_END_NAMESPACE

@@ -10,54 +10,65 @@

#if defined(__MINGW32__) || defined(__CYGWIN__)
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
# undef __STRICT_ANSI__
# undef __STRICT_ANSI__
#endif

#include <errno.h>
#include <fcntl.h> // for O_RDONLY
#include <locale.h> // for locale_t
#include <stdio.h>
#include <stdlib.h> // for strtod_l
#include <cerrno>
#include <clocale> // for locale_t
#include <cstdio>
#include <cstdlib> // for strtod_l

#include <cstddef>

#if defined __APPLE__ || defined(__FreeBSD__)
# include <xlocale.h> // for LC_NUMERIC_MASK on OS X
# include <xlocale.h> // for LC_NUMERIC_MASK on OS X
#endif

#include "format.h"

// UWP doesn't provide _pipe.
#if FMT_HAS_INCLUDE("winapifamily.h")
# include <winapifamily.h>
#endif
#if FMT_HAS_INCLUDE("fcntl.h") && \
(!defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))
# include <fcntl.h> // for O_RDONLY
# define FMT_USE_FCNTL 1
#else
# define FMT_USE_FCNTL 0
#endif

#ifndef FMT_POSIX
# if defined(_WIN32) && !defined(__MINGW32__)
# if defined(_WIN32) && !defined(__MINGW32__)
// Fix warnings about deprecated symbols.
# define FMT_POSIX(call) _##call
# else
# define FMT_POSIX(call) call
# endif
# 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)
# define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
#else
# define FMT_SYSTEM(call) call
# ifdef _WIN32
# 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
# define FMT_POSIX_CALL(call) ::_##call
# else
# define FMT_POSIX_CALL(call) ::call
# endif
#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)
# 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)
# define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
#endif

#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
@@ -69,7 +80,7 @@ FMT_BEGIN_NAMESPACE
A reference to a null-terminated string. It can be constructed from a C
string or ``std::string``.
You can use one of the following typedefs for common character types:
You can use one of the following type aliases for common character types:
+---------------+-----------------------------+
| Type | Definition |
@@ -89,28 +100,27 @@ FMT_BEGIN_NAMESPACE
format(std::string("{}"), 42);
\endrst
*/
template <typename Char>
class basic_cstring_view {
template <typename Char> class basic_cstring_view {
private:
const Char *data_;
const Char* data_;

public:
/** Constructs a string reference object from a C string. */
basic_cstring_view(const Char *s) : data_(s) {}
basic_cstring_view(const Char* s) : data_(s) {}

/**
\rst
Constructs a string reference from an ``std::string`` object.
\endrst
*/
basic_cstring_view(const std::basic_string<Char> &s) : data_(s.c_str()) {}
basic_cstring_view(const std::basic_string<Char>& s) : data_(s.c_str()) {}

/** Returns the pointer to a C string. */
const Char *c_str() const { return data_; }
const Char* c_str() const { return data_; }
};

typedef basic_cstring_view<char> cstring_view;
typedef basic_cstring_view<wchar_t> wcstring_view;
using cstring_view = basic_cstring_view<char>;
using wcstring_view = basic_cstring_view<wchar_t>;

// An error code.
class error_code {
@@ -126,33 +136,31 @@ class error_code {
// A buffered file.
class buffered_file {
private:
FILE *file_;
FILE* file_;

friend class file;

explicit buffered_file(FILE *f) : file_(f) {}
explicit buffered_file(FILE* f) : file_(f) {}

public:
buffered_file(const buffered_file&) = delete;
void operator=(const buffered_file&) = delete;

// Constructs a buffered_file object which doesn't represent any file.
buffered_file() FMT_NOEXCEPT : file_(FMT_NULL) {}
buffered_file() FMT_NOEXCEPT : file_(nullptr) {}

// Destroys the object closing the file it represents if any.
FMT_API ~buffered_file() FMT_NOEXCEPT;

private:
buffered_file(const buffered_file &) = delete;
void operator=(const buffered_file &) = delete;


public:
buffered_file(buffered_file &&other) FMT_NOEXCEPT : file_(other.file_) {
other.file_ = FMT_NULL;
buffered_file(buffered_file&& other) FMT_NOEXCEPT : file_(other.file_) {
other.file_ = nullptr;
}

buffered_file& operator=(buffered_file &&other) {
buffered_file& operator=(buffered_file&& other) {
close();
file_ = other.file_;
other.file_ = FMT_NULL;
other.file_ = nullptr;
return *this;
}

@@ -163,22 +171,23 @@ class buffered_file {
FMT_API void close();

// Returns the pointer to a FILE object representing this file.
FILE *get() const FMT_NOEXCEPT { return 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.
FMT_API int (fileno)() const;
FMT_API int(fileno)() const;

void vprint(string_view format_str, format_args args) {
fmt::vprint(file_, format_str, args);
}

template <typename... Args>
inline void print(string_view format_str, const Args & ... args) {
inline void print(string_view format_str, const Args&... args) {
vprint(format_str, make_format_args(args...));
}
};

#if FMT_USE_FCNTL
// A file. Closed file is represented by a file object with descriptor -1.
// Methods that are not declared with FMT_NOEXCEPT may throw
// fmt::system_error in case of failure. Note that some errors such as
@@ -195,9 +204,9 @@ class file {
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.
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.
@@ -206,16 +215,13 @@ class file {
// Opens a file and constructs a file object representing this file.
FMT_API file(cstring_view path, int oflag);

private:
file(const file &) = delete;
void operator=(const file &) = delete;

public:
file(file &&other) FMT_NOEXCEPT : fd_(other.fd_) {
other.fd_ = -1;
}
file(const file&) = delete;
void operator=(const file&) = delete;

file(file&& other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; }

file& operator=(file &&other) {
file& operator=(file&& other) FMT_NOEXCEPT {
close();
fd_ = other.fd_;
other.fd_ = -1;
@@ -236,10 +242,10 @@ class file {
FMT_API long long size() const;

// Attempts to read count bytes from the file into the specified buffer.
FMT_API std::size_t read(void *buffer, std::size_t count);
FMT_API std::size_t read(void* buffer, std::size_t count);

// Attempts to write count bytes from the specified buffer to the file.
FMT_API std::size_t write(const void *buffer, std::size_t count);
FMT_API 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.
@@ -251,68 +257,59 @@ class file {

// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
FMT_API void dup2(int fd, error_code &ec) FMT_NOEXCEPT;
FMT_API void dup2(int fd, error_code& ec) FMT_NOEXCEPT;

// Creates a pipe setting up read_end and write_end file objects for reading
// and writing respectively.
FMT_API static void pipe(file &read_end, file &write_end);
FMT_API static void pipe(file& read_end, file& write_end);

// Creates a buffered_file object associated with this file and detaches
// this file object from the file.
FMT_API buffered_file fdopen(const char *mode);
FMT_API buffered_file fdopen(const char* mode);
};

// Returns the memory page size.
long getpagesize();

#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && \
!defined(__ANDROID__) && !defined(__CYGWIN__) && !defined(__OpenBSD__) && \
!defined(__NEWLIB_H__)
# define FMT_LOCALE
#endif
#endif // FMT_USE_FCNTL

#ifdef FMT_LOCALE
// A "C" numeric locale.
class Locale {
private:
# ifdef _MSC_VER
typedef _locale_t locale_t;
# ifdef _WIN32
using locale_t = _locale_t;

enum { LC_NUMERIC_MASK = LC_NUMERIC };

static locale_t newlocale(int category_mask, const char *locale, locale_t) {
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 void freelocale(locale_t locale) { _free_locale(locale); }

static double strtod_l(const char *nptr, char **endptr, _locale_t locale) {
static double strtod_l(const char* nptr, char** endptr, _locale_t locale) {
return _strtod_l(nptr, endptr, locale);
}
# endif
# endif

locale_t locale_;

Locale(const Locale &) = delete;
void operator=(const Locale &) = delete;

public:
typedef locale_t Type;
using type = locale_t;
Locale(const Locale&) = delete;
void operator=(const Locale&) = delete;

Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", FMT_NULL)) {
if (!locale_)
FMT_THROW(system_error(errno, "cannot create locale"));
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", nullptr)) {
if (!locale_) FMT_THROW(system_error(errno, "cannot create locale"));
}
~Locale() { freelocale(locale_); }

Type get() const { return 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 = FMT_NULL;
double strtod(const char*& str) const {
char* end = nullptr;
double result = strtod_l(str, &end, locale_);
str = end;
return result;

Large diffs are not rendered by default.

Large diffs are not rendered by default.

This file was deleted.

@@ -8,51 +8,168 @@
#include "fmt/format-inl.h"

FMT_BEGIN_NAMESPACE
template struct internal::basic_data<void>;
template FMT_API internal::locale_ref::locale_ref(const std::locale &loc);
namespace internal {

template <typename T>
int format_float(char* buf, std::size_t size, const char* format, int precision,
T value) {
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if (precision > 100000)
throw std::runtime_error(
"fuzz mode - avoid large allocation inside snprintf");
#endif
// Suppress the warning about nonliteral format string.
auto snprintf_ptr = FMT_SNPRINTF;
return precision < 0 ? snprintf_ptr(buf, size, format, value)
: snprintf_ptr(buf, size, format, precision, value);
}
struct sprintf_specs {
int precision;
char type;
bool alt : 1;

template <typename Char>
constexpr sprintf_specs(basic_format_specs<Char> specs)
: precision(specs.precision), type(specs.type), alt(specs.alt) {}

constexpr bool has_precision() const { return precision >= 0; }
};

// This is deprecated and is kept only to preserve ABI compatibility.
template <typename Double>
char* sprintf_format(Double value, internal::buffer<char>& buf,
sprintf_specs specs) {
// Buffer capacity must be non-zero, otherwise MSVC's vsnprintf_s will fail.
FMT_ASSERT(buf.capacity() != 0, "empty buffer");

// Build format string.
enum { max_format_size = 10 }; // longest format: %#-*.*Lg
char format[max_format_size];
char* format_ptr = format;
*format_ptr++ = '%';
if (specs.alt || !specs.type) *format_ptr++ = '#';
if (specs.precision >= 0) {
*format_ptr++ = '.';
*format_ptr++ = '*';
}
if (std::is_same<Double, long double>::value) *format_ptr++ = 'L';

char type = specs.type;

if (type == '%')
type = 'f';
else if (type == 0 || type == 'n')
type = 'g';
#if FMT_MSC_VER
if (type == 'F') {
// MSVC's printf doesn't support 'F'.
type = 'f';
}
#endif
*format_ptr++ = type;
*format_ptr = '\0';

// Format using snprintf.
char* start = nullptr;
char* decimal_point_pos = nullptr;
for (;;) {
std::size_t buffer_size = buf.capacity();
start = &buf[0];
int result =
format_float(start, buffer_size, format, specs.precision, value);
if (result >= 0) {
unsigned n = internal::to_unsigned(result);
if (n < buf.capacity()) {
// Find the decimal point.
auto p = buf.data(), end = p + n;
if (*p == '+' || *p == '-') ++p;
if (specs.type != 'a' && specs.type != 'A') {
while (p < end && *p >= '0' && *p <= '9') ++p;
if (p < end && *p != 'e' && *p != 'E') {
decimal_point_pos = p;
if (!specs.type) {
// Keep only one trailing zero after the decimal point.
++p;
if (*p == '0') ++p;
while (p != end && *p >= '1' && *p <= '9') ++p;
char* where = p;
while (p != end && *p == '0') ++p;
if (p == end || *p < '0' || *p > '9') {
if (p != end) std::memmove(where, p, to_unsigned(end - p));
n -= static_cast<unsigned>(p - where);
}
}
}
}
buf.resize(n);
break; // The buffer is large enough - continue with formatting.
}
buf.reserve(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.
buf.reserve(buf.capacity() + 1);
}
}
return decimal_point_pos;
}
} // namespace internal

template FMT_API char* internal::sprintf_format(double, internal::buffer<char>&,
sprintf_specs);
template FMT_API char* internal::sprintf_format(long double,
internal::buffer<char>&,
sprintf_specs);

template struct FMT_API internal::basic_data<void>;

// Workaround a bug in MSVC2013 that prevents instantiation of format_float.
int (*instantiate_format_float)(double, int, internal::float_specs,
internal::buffer<char>&) =
internal::format_float;

#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
template FMT_API internal::locale_ref::locale_ref(const std::locale& loc);
template FMT_API std::locale internal::locale_ref::get<std::locale>() const;
#endif

// Explicit instantiations for char.

template FMT_API std::string internal::grouping_impl<char>(locale_ref);
template FMT_API char internal::thousands_sep_impl(locale_ref);
template FMT_API char internal::decimal_point_impl(locale_ref);

template FMT_API void internal::basic_buffer<char>::append(const char *, const char *);
template FMT_API void internal::buffer<char>::append(const char*, const char*);

template FMT_API void internal::arg_map<format_context>::init(
const basic_format_args<format_context> &args);

template FMT_API int internal::char_traits<char>::format_float(
char *, std::size_t, const char *, int, double);

template FMT_API int internal::char_traits<char>::format_float(
char *, std::size_t, const char *, int, long double);
const basic_format_args<format_context>& args);

template FMT_API std::string internal::vformat<char>(
string_view, basic_format_args<format_context>);

template FMT_API format_context::iterator internal::vformat_to(
internal::buffer &, string_view, basic_format_args<format_context>);

template FMT_API void internal::sprintf_format(
double, internal::buffer &, core_format_specs);
template FMT_API void internal::sprintf_format(
long double, internal::buffer &, core_format_specs);
internal::buffer<char>&, string_view, basic_format_args<format_context>);

template FMT_API int internal::snprintf_float(double, int,
internal::float_specs,
internal::buffer<char>&);
template FMT_API int internal::snprintf_float(long double, int,
internal::float_specs,
internal::buffer<char>&);
template FMT_API int internal::format_float(double, int, internal::float_specs,
internal::buffer<char>&);
template FMT_API int internal::format_float(long double, int,
internal::float_specs,
internal::buffer<char>&);

// Explicit instantiations for wchar_t.

template FMT_API std::string internal::grouping_impl<wchar_t>(locale_ref);
template FMT_API wchar_t internal::thousands_sep_impl(locale_ref);
template FMT_API wchar_t internal::decimal_point_impl(locale_ref);

template FMT_API void internal::basic_buffer<wchar_t>::append(
const wchar_t *, const wchar_t *);

template FMT_API void internal::arg_map<wformat_context>::init(
const basic_format_args<wformat_context> &);

template FMT_API int internal::char_traits<wchar_t>::format_float(
wchar_t *, std::size_t, const wchar_t *, int, double);

template FMT_API int internal::char_traits<wchar_t>::format_float(
wchar_t *, std::size_t, const wchar_t *, int, long double);
template FMT_API void internal::buffer<wchar_t>::append(const wchar_t*,
const wchar_t*);

template FMT_API std::wstring internal::vformat<wchar_t>(
wstring_view, basic_format_args<wformat_context>);
@@ -7,49 +7,51 @@

// Disable bogus MSVC warnings.
#if !defined(_CRT_SECURE_NO_WARNINGS) && defined(_MSC_VER)
# define _CRT_SECURE_NO_WARNINGS
# define _CRT_SECURE_NO_WARNINGS
#endif

#include "fmt/posix.h"

#include <limits.h>
#include <sys/types.h>
#include <climits>

#if FMT_USE_FCNTL
#include <sys/stat.h>
#include <sys/types.h>

#ifndef _WIN32
# include <unistd.h>
# include <unistd.h>
#else
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# include <io.h>

# 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

# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <io.h>
# include <windows.h>

# 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
#endif // FMT_USE_FCNTL

#ifdef fileno
# undef fileno
# undef fileno
#endif

namespace {
#ifdef _WIN32
// Return type of read and write functions.
typedef int RWResult;
using RWResult = int;

// On Windows the count argument to read and write is unsigned, so convert
// it from size_t preventing integer overflow.
@@ -58,11 +60,11 @@ inline unsigned convert_rwcount(std::size_t count) {
}
#else
// Return type of read and write functions.
typedef ssize_t RWResult;
using RWResult = ssize_t;

inline std::size_t convert_rwcount(std::size_t count) { return count; }
#endif
}
} // namespace

FMT_BEGIN_NAMESPACE

@@ -72,31 +74,29 @@ buffered_file::~buffered_file() FMT_NOEXCEPT {
}

buffered_file::buffered_file(cstring_view filename, cstring_view mode) {
FMT_RETRY_VAL(file_,
FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), FMT_NULL);
FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())),
nullptr);
if (!file_)
FMT_THROW(system_error(errno, "cannot open file {}", filename.c_str()));
}

void buffered_file::close() {
if (!file_)
return;
if (!file_) return;
int result = FMT_SYSTEM(fclose(file_));
file_ = FMT_NULL;
if (result != 0)
FMT_THROW(system_error(errno, "cannot close file"));
file_ = nullptr;
if (result != 0) FMT_THROW(system_error(errno, "cannot close file"));
}

// A macro used to prevent expansion of fileno on broken versions of MinGW.
#define FMT_ARGS

int buffered_file::fileno() const {
int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_));
if (fd == -1)
FMT_THROW(system_error(errno, "cannot get file descriptor"));
if (fd == -1) FMT_THROW(system_error(errno, "cannot get file descriptor"));
return fd;
}

#if FMT_USE_FCNTL
file::file(cstring_view path, int oflag) {
int mode = S_IRUSR | S_IWUSR;
#if defined(_WIN32) && !defined(__MINGW32__)
@@ -117,14 +117,12 @@ file::~file() FMT_NOEXCEPT {
}

void file::close() {
if (fd_ == -1)
return;
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)
FMT_THROW(system_error(errno, "cannot close file"));
if (result != 0) FMT_THROW(system_error(errno, "cannot close file"));
}

long long file::size() const {
@@ -143,29 +141,27 @@ long long file::size() const {
unsigned long long long_size = size_upper;
return (long_size << sizeof(DWORD) * CHAR_BIT) | size_lower;
#else
typedef struct stat Stat;
using Stat = struct stat;
Stat file_stat = Stat();
if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1)
FMT_THROW(system_error(errno, "cannot get file attributes"));
static_assert(sizeof(long long) >= sizeof(file_stat.st_size),
"return type of file::size is not large enough");
"return type of file::size is not large enough");
return file_stat.st_size;
#endif
}

std::size_t file::read(void *buffer, std::size_t count) {
std::size_t 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)
FMT_THROW(system_error(errno, "cannot read from file"));
if (result < 0) FMT_THROW(system_error(errno, "cannot read from file"));
return internal::to_unsigned(result);
}

std::size_t file::write(const void *buffer, std::size_t count) {
std::size_t 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)
FMT_THROW(system_error(errno, "cannot write to file"));
if (result < 0) FMT_THROW(system_error(errno, "cannot write to file"));
return internal::to_unsigned(result);
}

@@ -182,19 +178,18 @@ void file::dup2(int fd) {
int result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
if (result == -1) {
FMT_THROW(system_error(errno,
"cannot duplicate file descriptor {} to {}", fd_, fd));
FMT_THROW(system_error(errno, "cannot duplicate file descriptor {} to {}",
fd_, fd));
}
}

void file::dup2(int fd, error_code &ec) FMT_NOEXCEPT {
void file::dup2(int fd, error_code& ec) FMT_NOEXCEPT {
int result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
if (result == -1)
ec = error_code(errno);
if (result == -1) ec = error_code(errno);
}

void file::pipe(file &read_end, file &write_end) {
void 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();
@@ -209,20 +204,19 @@ void file::pipe(file &read_end, file &write_end) {
// http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html
int result = FMT_POSIX_CALL(pipe(fds));
#endif
if (result != 0)
FMT_THROW(system_error(errno, "cannot create pipe"));
if (result != 0) FMT_THROW(system_error(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]);
}

buffered_file file::fdopen(const char *mode) {
buffered_file file::fdopen(const char* mode) {
// Don't retry as fdopen doesn't return EINTR.
FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode));
FILE* f = FMT_POSIX_CALL(fdopen(fd_, mode));
if (!f)
FMT_THROW(system_error(errno,
"cannot associate stream with file descriptor"));
FMT_THROW(
system_error(errno, "cannot associate stream with file descriptor"));
buffered_file bf(f);
fd_ = -1;
return bf;
@@ -235,10 +229,9 @@ long getpagesize() {
return si.dwPageSize;
#else
long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE));
if (size < 0)
FMT_THROW(system_error(errno, "cannot get memory page size"));
if (size < 0) FMT_THROW(system_error(errno, "cannot get memory page size"));
return size;
#endif
}
#endif // FMT_USE_FCNTL
FMT_END_NAMESPACE

Large diffs are not rendered by default.

@@ -0,0 +1,19 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :

# A vagrant config for testing against gcc-4.8.
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/xenial64"

config.vm.provider "virtualbox" do |vb|
vb.memory = "4096"
end

config.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y g++ make wget git
wget -q https://github.com/Kitware/CMake/releases/download/v3.14.4/cmake-3.14.4-Linux-x86_64.tar.gz
tar xzf cmake-3.14.4-Linux-x86_64.tar.gz
ln -s `pwd`/cmake-3.14.4-Linux-x86_64/bin/cmake /usr/local/bin
SHELL
end
@@ -23,14 +23,17 @@
# Add MSBuild 14.0 to PATH as described in
# http://help.appveyor.com/discussions/problems/2229-v140-not-found-on-vs2105rc.
os.environ['PATH'] = r'C:\Program Files (x86)\MSBuild\15.0\Bin;' + path
if image == 'Visual Studio 2013':
generator = 'Visual Studio 12 2013'
elif image == 'Visual Studio 2015':
generator = 'Visual Studio 14 2015'
elif image == 'Visual Studio 2017':
generator = 'Visual Studio 15 2017'
if platform == 'x64':
generator += ' Win64'
if image == 'Visual Studio 2019':
generator = 'Visual Studio 16 2019'
if platform == 'x64':
cmake_command.extend(['-A', 'x64'])
else:
if image == 'Visual Studio 2015':
generator = 'Visual Studio 14 2015'
elif image == 'Visual Studio 2017':
generator = 'Visual Studio 15 2017'
if platform == 'x64':
generator += ' Win64'
cmake_command.append('-G' + generator)
build_command = ['cmake', '--build', '.', '--config', config, '--', '/m:4']
test_command = ['ctest', '-C', config]
@@ -4,20 +4,27 @@ configuration:

clone_depth: 1

platform:
- Win32
- x64

image:
- Visual Studio 2013
- Visual Studio 2015
- Visual Studio 2019
- Visual Studio 2017

platform:
- Win32
- x64

environment:
CTEST_OUTPUT_ON_FAILURE: 1
MSVC_DEFAULT_OPTIONS: ON
BUILD: msvc

matrix:
exclude:
- image: Visual Studio 2015
platform: Win32
- image: Visual Studio 2019
platform: Win32

before_build:
- mkdir build
- cd build
@@ -9,10 +9,12 @@ buildscript {
//
// https://developer.android.com/studio/releases/gradle-plugin
//
// Notice that 3.1.3 here is the version of [Android Gradle Plugin]
// Accroding to URL above you will need Gradle 4.4 or higher
// Notice that 3.3.0 here is the version of [Android Gradle Plugin]
// Accroding to URL above you will need Gradle 5.0 or higher
//
classpath 'com.android.tools.build:gradle:3.1.3'
// If you are using Android Studio, and it is using Gradle's lower
// version, Use the plugin version 3.1.3 ~ 3.2.0 for Gradle 4.4 ~ 4.10
classpath 'com.android.tools.build:gradle:3.3.0'
}
}
repositories {
@@ -43,8 +45,8 @@ android {
defaultConfig {
minSdkVersion 21 // Android 5.0+
targetSdkVersion 25 // Follow Compile SDK
versionCode 20 // Follow release count
versionName "5.2.1" // Follow Official version
versionCode 21 // Follow release count
versionName "5.3.0" // Follow Official version
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

externalNativeBuild {
@@ -50,6 +50,7 @@ set(CMAKE_REQUIRED_FLAGS ${CXX_STANDARD_FLAG})

# Check if variadic templates are working and not affected by GCC bug 39653:
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=39653
# Can be removed once gcc 4.4 support is dropped.
check_cxx_source_compiles("
template <class T, class ...Types>
struct S { typedef typename S<Types...>::type type; };
@@ -58,33 +59,6 @@ if (NOT SUPPORTS_VARIADIC_TEMPLATES)
set (SUPPORTS_VARIADIC_TEMPLATES OFF)
endif ()

# Check if initializer lists are supported.
check_cxx_source_compiles("
#include <initializer_list>
int main() {}" SUPPORTS_INITIALIZER_LIST)
if (NOT SUPPORTS_INITIALIZER_LIST)
set (SUPPORTS_INITIALIZER_LIST OFF)
endif ()

# Check if enum bases are available
check_cxx_source_compiles("
enum C : char {A};
int main() {}"
SUPPORTS_ENUM_BASE)
if (NOT SUPPORTS_ENUM_BASE)
set (SUPPORTS_ENUM_BASE OFF)
endif ()

# Check if type traits are available
check_cxx_source_compiles("
#include <type_traits>
class C { void operator=(const C&); };
int main() { static_assert(!std::is_copy_assignable<C>::value, \"\"); }"
SUPPORTS_TYPE_TRAITS)
if (NOT SUPPORTS_TYPE_TRAITS)
set (SUPPORTS_TYPE_TRAITS OFF)
endif ()

# Check if user-defined literals are available
check_cxx_source_compiles("
void operator\"\" _udl(long double);
@@ -94,4 +68,14 @@ if (NOT SUPPORTS_USER_DEFINED_LITERALS)
set (SUPPORTS_USER_DEFINED_LITERALS OFF)
endif ()

# Check if <variant> is available
set(CMAKE_REQUIRED_FLAGS -std=c++1z)
check_cxx_source_compiles("
#include <variant>
int main() {}"
FMT_HAS_VARIANT)
if (NOT FMT_HAS_VARIANT)
set (FMT_HAS_VARIANT OFF)
endif ()

set(CMAKE_REQUIRED_FLAGS )
@@ -1,7 +1,7 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@

Name: fmt
Description: A modern formatting library

This file was deleted.

@@ -5,6 +5,9 @@
Usage:
manage.py release [<branch>]
manage.py site
For the release command $FMT_TOKEN should contain a GitHub personal access token
obtained from https://github.com/settings/tokens.
"""

from __future__ import print_function
@@ -142,6 +145,7 @@ def update_site(env):
b.data = b.data.replace('std::FILE*', 'std::FILE *')
b.data = b.data.replace('unsigned int', 'unsigned')
b.data = b.data.replace('operator""_', 'operator"" _')
b.data = b.data.replace(', size_t', ', std::size_t')
# Fix a broken link in index.rst.
index = os.path.join(target_doc_dir, 'index.rst')
with rewrite(index) as b:
@@ -1,2 +1,2 @@
If you are not redirected automatically, follow the
`link to the fmt documentation <http://fmtlib.net/latest/>`_.
`link to the fmt documentation <https://fmt.dev/latest/>`_.
@@ -2,15 +2,15 @@

{% block extrahead %}
<meta charset="UTF-8">
<meta http-equiv="refresh" content="1;url=http://fmtlib.net/latest/">
<meta http-equiv="refresh" content="1;url=https://fmt.dev/latest/">
<script type="text/javascript">
window.location.href = "http://fmtlib.net/latest/"
window.location.href = "https://fmt.dev/latest/"
</script>
<title>Page Redirection</title>
{% endblock %}

{% block document %}
If you are not redirected automatically, follow the <a href='http://fmtlib.net/latest/'>link to the fmt documentation</a>.
If you are not redirected automatically, follow the <a href='https://fmt.dev/latest/'>link to the fmt documentation</a>.
{% endblock %}

{% block footer %}
@@ -83,27 +83,33 @@ def install_dependencies():
build_dir = os.path.join(fmt_dir, "_build")
test_build_dir = os.path.join(fmt_dir, "_build_test")

# Configure library.
# Configure the library.
makedirs_if_not_exist(build_dir)
cmake_flags = [
'-DCMAKE_INSTALL_PREFIX=' + install_dir, '-DCMAKE_BUILD_TYPE=' + build,
'-DCMAKE_CXX_STANDARD=' + standard
]

# Make sure the fuzzers still compile.
main_cmake_flags = list(cmake_flags)
if 'ENABLE_FUZZING' in os.environ:
main_cmake_flags += ['-DFMT_FUZZ=ON', '-DFMT_FUZZ_LINKMAIN=On']

check_call(['cmake', '-DFMT_DOC=OFF', '-DFMT_PEDANTIC=ON', '-DFMT_WERROR=ON', fmt_dir] +
cmake_flags, cwd=build_dir)
main_cmake_flags, cwd=build_dir)

# Build library.
check_call(['make', '-j4'], cwd=build_dir)
# Build the library.
check_call(['cmake', '--build','.'], cwd=build_dir)

# Test library.
# Test the library.
env = os.environ.copy()
env['CTEST_OUTPUT_ON_FAILURE'] = '1'
if call(['make', 'test'], env=env, cwd=build_dir):
with open(os.path.join(build_dir, 'Testing', 'Temporary', 'LastTest.log'), 'r') as f:
print(f.read())
sys.exit(-1)

# Install library.
# Install the library.
check_call(['make', 'install'], cwd=build_dir)

# Test installation.
@@ -11,7 +11,7 @@
#include <iomanip>
#include <string>

#include <fmt/time.h>
#include <fmt/chrono.h>

#include "Common/CommonTypes.h"

@@ -12,8 +12,8 @@
#include <utility>
#include <variant>

#include <fmt/chrono.h>
#include <fmt/format.h>
#include <fmt/time.h>

#ifdef _WIN32
#include <windows.h>
@@ -989,7 +989,7 @@ void GetBPRegInfo(const u8* data, std::string* name, std::string* desc)
SetRegName(BPMEM_EFB_TL);
X10Y10 left_top;
left_top.hex = cmddata;
*desc = fmt::format("Left: {}\nTop: {}", left_top.x, left_top.y);
*desc = fmt::format("Left: {}\nTop: {}", u32(left_top.x), u32(left_top.y));
}
break;

@@ -1183,7 +1183,7 @@ void GetBPRegInfo(const u8* data, std::string* name, std::string* desc)
"Width: {}\n"
"Height: {}\n"
"Format: {:x}\n",
texnum, teximg.width + 1, teximg.height + 1, teximg.format);
texnum, u32(teximg.width) + 1, u32(teximg.height) + 1, u32(teximg.format));
}
break;

@@ -1206,8 +1206,8 @@ void GetBPRegInfo(const u8* data, std::string* name, std::string* desc)
"Even TMEM Width: {}\n"
"Even TMEM Height: {}\n"
"Cache is manually managed: {}\n",
texnum, teximg.tmem_even, teximg.cache_width, teximg.cache_height,
no_yes[teximg.image_type]);
texnum, u32(teximg.tmem_even), u32(teximg.cache_width),
u32(teximg.cache_height), no_yes[teximg.image_type]);
}
break;

@@ -1229,7 +1229,8 @@ void GetBPRegInfo(const u8* data, std::string* name, std::string* desc)
"Odd TMEM Offset: {:x}\n"
"Odd TMEM Width: {}\n"
"Odd TMEM Height: {}\n",
texnum, teximg.tmem_odd, teximg.cache_width, teximg.cache_height);
texnum, u32(teximg.tmem_odd), u32(teximg.cache_width),
u32(teximg.cache_height));
}
break;