clang-format for test files

- Applied format to test files
 - build tested with gcc-8 / g++-8
This commit is contained in:
luncliff 2018-12-19 15:52:51 +09:00
parent 8671608b83
commit 2420a589c6
28 changed files with 1931 additions and 1405 deletions

View File

@ -28,9 +28,8 @@ enum class numeric_system {
// Parses a put_time-like format string and invokes handler actions.
template <typename Char, typename Handler>
FMT_CONSTEXPR const Char *parse_chrono_format(const Char *begin,
const Char *end,
Handler &&handler) {
FMT_CONSTEXPR const Char *parse_chrono_format(
const Char *begin, const Char *end, Handler &&handler) {
auto ptr = begin;
while (ptr != end) {
auto c = *ptr;
@ -214,9 +213,10 @@ struct chrono_format_checker {
template <typename Int>
inline int to_int(Int value) {
FMT_ASSERT(value >= (std::numeric_limits<int>::min)() &&
value <= (std::numeric_limits<int>::max)(),
"invalid value");
FMT_ASSERT(
value >= (std::numeric_limits<int>::min)() &&
value <= (std::numeric_limits<int>::max)(),
"invalid value");
return static_cast<int>(value);
}
@ -491,8 +491,8 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
format_to(buf, "{}[{}/{}]s", d.count(), Period::num, Period::den);
typedef output_range<decltype(ctx.out()), Char> range;
basic_writer<range> w(range(ctx.out()));
internal::handle_dynamic_spec<internal::width_checker>(spec.width_,
width_ref, ctx);
internal::handle_dynamic_spec<internal::width_checker>(
spec.width_, width_ref, ctx);
w.write(buf.data(), buf.size(), spec);
return w.out();
}

View File

@ -19,13 +19,13 @@ enum color { black, red, green, yellow, blue, magenta, cyan, white };
FMT_API void vprint_colored(color c, string_view format, format_args args);
FMT_API void vprint_colored(color c, wstring_view format, wformat_args args);
template <typename... Args>
inline void print_colored(color c, string_view format_str,
const Args&... args) {
inline void print_colored(
color c, string_view format_str, const Args&... args) {
vprint_colored(c, format_str, make_format_args(args...));
}
template <typename... Args>
inline void print_colored(color c, wstring_view format_str,
const Args&... args) {
inline void print_colored(
color c, wstring_view format_str, const Args&... args) {
vprint_colored(c, format_str, make_format_args<wformat_context>(args...));
}
@ -290,13 +290,13 @@ class text_style {
background_color.value.rgb_color |= rhs.background_color.value.rgb_color;
}
ems = static_cast<emphasis>(static_cast<uint8_t>(ems) |
static_cast<uint8_t>(rhs.ems));
ems = static_cast<emphasis>(
static_cast<uint8_t>(ems) | static_cast<uint8_t>(rhs.ems));
return *this;
}
friend FMT_CONSTEXPR text_style operator|(text_style lhs,
const text_style &rhs) {
friend FMT_CONSTEXPR text_style
operator|(text_style lhs, const text_style &rhs) {
return lhs |= rhs;
}
@ -319,13 +319,13 @@ class text_style {
background_color.value.rgb_color &= rhs.background_color.value.rgb_color;
}
ems = static_cast<emphasis>(static_cast<uint8_t>(ems) &
static_cast<uint8_t>(rhs.ems));
ems = static_cast<emphasis>(
static_cast<uint8_t>(ems) & static_cast<uint8_t>(rhs.ems));
return *this;
}
friend FMT_CONSTEXPR text_style operator&(text_style lhs,
const text_style &rhs) {
friend FMT_CONSTEXPR text_style
operator&(text_style lhs, const text_style &rhs) {
return lhs &= rhs;
}
@ -352,11 +352,10 @@ class text_style {
}
private:
FMT_CONSTEXPR text_style(bool is_foreground,
internal::color_type text_color) FMT_NOEXCEPT
: set_foreground_color(),
set_background_color(),
ems() {
FMT_CONSTEXPR text_style(bool is_foreground, internal::color_type text_color)
FMT_NOEXCEPT : set_foreground_color(),
set_background_color(),
ems() {
if (is_foreground) {
foreground_color = text_color;
set_foreground_color = true;
@ -394,8 +393,8 @@ namespace internal {
template <typename Char>
struct ansi_color_escape {
FMT_CONSTEXPR ansi_color_escape(internal::color_type text_color,
const char *esc) FMT_NOEXCEPT {
FMT_CONSTEXPR ansi_color_escape(
internal::color_type text_color, const char *esc) FMT_NOEXCEPT {
// If we have a terminal color, we need to output another escape code
// sequence.
if (!text_color.is_rgb) {
@ -459,8 +458,8 @@ struct ansi_color_escape {
private:
Char buffer[7 + 3 * 4 + 1];
static FMT_CONSTEXPR void to_esc(uint8_t c, Char *out,
char delimiter) FMT_NOEXCEPT {
static FMT_CONSTEXPR void to_esc(uint8_t c, Char *out, char delimiter)
FMT_NOEXCEPT {
out[0] = static_cast<Char>('0' + c / 100);
out[1] = static_cast<Char>('0' + c / 10 % 10);
out[2] = static_cast<Char>('0' + c % 10);
@ -516,8 +515,11 @@ struct is_string<const std::FILE *> : std::false_type {};
} // namespace internal
template <typename S, typename Char = typename internal::char_t<S>::type>
void vprint(std::FILE *f, const text_style &ts, const S &format,
basic_format_args<typename buffer_context<Char>::type> args) {
void vprint(
std::FILE *f,
const text_style &ts,
const S &format,
basic_format_args<typename buffer_context<Char>::type> args) {
bool has_style = false;
if (ts.has_emphasis()) {
has_style = true;
@ -548,7 +550,9 @@ void vprint(std::FILE *f, const text_style &ts, const S &format,
*/
template <typename String, typename... Args>
typename std::enable_if<internal::is_string<String>::value>::type print(
std::FILE *f, const text_style &ts, const String &format_str,
std::FILE *f,
const text_style &ts,
const String &format_str,
const Args &... args) {
internal::check_format_string<Args...>(format_str);
typedef typename internal::char_t<String>::type char_t;

View File

@ -178,8 +178,9 @@
#endif
// libc++ supports string_view in pre-c++17.
#if (FMT_HAS_INCLUDE(<string_view>) && \
(__cplusplus > 201402L || defined(_LIBCPP_VERSION))) || \
#if ( \
FMT_HAS_INCLUDE(<string_view>) && \
(__cplusplus > 201402L || defined(_LIBCPP_VERSION))) || \
(defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)
#include <string_view>
#define FMT_STRING_VIEW std::basic_string_view
@ -232,10 +233,10 @@ class basic_buffer {
// Don't initialize ptr_ since it is not accessed to save a few cycles.
basic_buffer(std::size_t sz) FMT_NOEXCEPT : size_(sz), capacity_(sz) {}
basic_buffer(T *p = FMT_NULL, std::size_t sz = 0,
std::size_t cap = 0) FMT_NOEXCEPT : ptr_(p),
size_(sz),
capacity_(cap) {}
basic_buffer(T *p = FMT_NULL, std::size_t sz = 0, std::size_t cap = 0)
FMT_NOEXCEPT : ptr_(p),
size_(sz),
capacity_(cap) {}
/** Sets the buffer data and capacity. */
void set(T *buf_data, std::size_t buf_capacity) FMT_NOEXCEPT {
@ -491,8 +492,10 @@ struct compile_string {};
template <typename S>
struct is_compile_string : std::is_base_of<compile_string, S> {};
template <typename S, typename Enable = typename std::enable_if<
is_compile_string<S>::value>::type>
template <
typename S,
typename Enable =
typename std::enable_if<is_compile_string<S>::value>::type>
FMT_CONSTEXPR basic_string_view<typename S::char_type> to_string_view(
const S &s) {
return s;
@ -521,8 +524,10 @@ struct formatter {
template <typename T, typename Char, typename Enable = void>
struct convert_to_int
: std::integral_constant<bool, !std::is_arithmetic<T>::value &&
std::is_convertible<T, int>::value> {};
: std::integral_constant<
bool,
!std::is_arithmetic<T>::value && std::is_convertible<T, int>::value> {
};
namespace internal {
@ -534,11 +539,11 @@ using fmt::v5::to_string_view;
// Specifies whether S is a string type convertible to fmt::basic_string_view.
template <typename S>
struct is_string
: std::integral_constant<
bool, !std::is_same<dummy_string_view,
decltype(to_string_view(declval<S>()))>::value> {
};
struct is_string : std::integral_constant<
bool,
!std::is_same<
dummy_string_view,
decltype(to_string_view(declval<S>()))>::value> {};
template <typename S>
struct char_t {
@ -623,13 +628,13 @@ class value {
value(long double val) { long_double_value = val; }
value(const char_type *val) { string.value = val; }
value(const signed char *val) {
static_assert(std::is_same<char, char_type>::value,
"incompatible string types");
static_assert(
std::is_same<char, char_type>::value, "incompatible string types");
sstring.value = val;
}
value(const unsigned char *val) {
static_assert(std::is_same<char, char_type>::value,
"incompatible string types");
static_assert(
std::is_same<char, char_type>::value, "incompatible string types");
ustring.value = val;
}
value(basic_string_view<char_type> val) {
@ -697,13 +702,16 @@ FMT_MAKE_VALUE_SAME(uint_type, unsigned)
// either to int or to long long depending on its size.
typedef std::conditional<sizeof(long) == sizeof(int), int, long long>::type
long_type;
FMT_MAKE_VALUE((sizeof(long) == sizeof(int) ? int_type : long_long_type), long,
long_type)
typedef std::conditional<sizeof(unsigned long) == sizeof(unsigned), unsigned,
unsigned long long>::type ulong_type;
FMT_MAKE_VALUE((sizeof(unsigned long) == sizeof(unsigned) ? uint_type
: ulong_long_type),
unsigned long, ulong_type)
FMT_MAKE_VALUE(
(sizeof(long) == sizeof(int) ? int_type : long_long_type), long, long_type)
typedef std::conditional<
sizeof(unsigned long) == sizeof(unsigned),
unsigned,
unsigned long long>::type ulong_type;
FMT_MAKE_VALUE(
(sizeof(unsigned long) == sizeof(unsigned) ? uint_type : ulong_long_type),
unsigned long,
ulong_type)
FMT_MAKE_VALUE_SAME(long_long_type, long long)
FMT_MAKE_VALUE_SAME(ulong_long_type, unsigned long long)
@ -712,18 +720,18 @@ FMT_MAKE_VALUE(uint_type, unsigned char, unsigned)
// This doesn't use FMT_MAKE_VALUE because of ambiguity in gcc 4.4.
template <typename C, typename Char>
FMT_CONSTEXPR
typename std::enable_if<std::is_same<typename C::char_type, Char>::value,
init<C, int, char_type>>::type
make_value(Char val) {
FMT_CONSTEXPR typename std::enable_if<
std::is_same<typename C::char_type, Char>::value,
init<C, int, char_type>>::type
make_value(Char val) {
return val;
}
template <typename C>
FMT_CONSTEXPR
typename std::enable_if<!std::is_same<typename C::char_type, char>::value,
init<C, int, char_type>>::type
make_value(char val) {
FMT_CONSTEXPR typename std::enable_if<
!std::is_same<typename C::char_type, char>::value,
init<C, int, char_type>>::type
make_value(char val) {
return val;
}
@ -733,21 +741,24 @@ FMT_MAKE_VALUE_SAME(long_double_type, long double)
// Formatting of wide strings into a narrow buffer and multibyte strings
// into a wide buffer is disallowed (https://github.com/fmtlib/fmt/pull/606).
FMT_MAKE_VALUE(cstring_type, typename C::char_type *,
const typename C::char_type *)
FMT_MAKE_VALUE(cstring_type, const typename C::char_type *,
const typename C::char_type *)
FMT_MAKE_VALUE(
cstring_type, typename C::char_type *, const typename C::char_type *)
FMT_MAKE_VALUE(
cstring_type, const typename C::char_type *, const typename C::char_type *)
FMT_MAKE_VALUE(cstring_type, signed char *, const signed char *)
FMT_MAKE_VALUE_SAME(cstring_type, const signed char *)
FMT_MAKE_VALUE(cstring_type, unsigned char *, const unsigned char *)
FMT_MAKE_VALUE_SAME(cstring_type, const unsigned char *)
FMT_MAKE_VALUE_SAME(string_type, basic_string_view<typename C::char_type>)
FMT_MAKE_VALUE(string_type,
typename basic_string_view<typename C::char_type>::type,
basic_string_view<typename C::char_type>)
FMT_MAKE_VALUE(string_type, const std::basic_string<typename C::char_type> &,
basic_string_view<typename C::char_type>)
FMT_MAKE_VALUE(
string_type,
typename basic_string_view<typename C::char_type>::type,
basic_string_view<typename C::char_type>)
FMT_MAKE_VALUE(
string_type,
const std::basic_string<typename C::char_type> &,
basic_string_view<typename C::char_type>)
FMT_MAKE_VALUE(pointer_type, void *, const void *)
FMT_MAKE_VALUE_SAME(pointer_type, const void *)
@ -766,11 +777,10 @@ make_value(const T *) {
}
template <typename C, typename T>
inline
typename std::enable_if<std::is_enum<T>::value &&
convert_to_int<T, typename C::char_type>::value,
init<C, int, int_type>>::type
make_value(const T &val) {
inline typename std::enable_if<
std::is_enum<T>::value && convert_to_int<T, typename C::char_type>::value,
init<C, int, int_type>>::type
make_value(const T &val) {
return static_cast<int>(val);
}
@ -810,9 +820,10 @@ FMT_CONSTEXPR11 typename std::enable_if<
init<C, basic_string_view<typename C::char_type>, string_type>>::type
make_value(const S &val) {
// Handle adapted strings.
static_assert(std::is_same<typename C::char_type,
typename internal::char_t<S>::type>::value,
"mismatch between char-types of context and argument");
static_assert(
std::is_same<typename C::char_type, typename internal::char_t<S>::type>::
value,
"mismatch between char-types of context and argument");
return to_string_view(val);
}
@ -906,8 +917,8 @@ FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type visit_format_arg(
case internal::cstring_type:
return vis(arg.value_.string.value);
case internal::string_type:
return vis(basic_string_view<char_type>(arg.value_.string.value,
arg.value_.string.size));
return vis(basic_string_view<char_type>(
arg.value_.string.value, arg.value_.string.size));
case internal::pointer_type:
return vis(arg.value_.pointer);
case internal::custom_type:
@ -934,8 +945,8 @@ class basic_parse_context : private ErrorHandler {
typedef Char char_type;
typedef typename basic_string_view<Char>::iterator iterator;
explicit FMT_CONSTEXPR basic_parse_context(basic_string_view<Char> format_str,
ErrorHandler eh = ErrorHandler())
explicit FMT_CONSTEXPR basic_parse_context(
basic_string_view<Char> format_str, ErrorHandler eh = ErrorHandler())
: ErrorHandler(eh), format_str_(format_str), next_arg_id_(0) {}
// Returns an iterator to the beginning of the format string range being
@ -1049,9 +1060,11 @@ class context_base {
typedef Char char_type;
typedef basic_format_arg<Context> format_arg;
context_base(OutputIt out, basic_string_view<char_type> format_str,
basic_format_args<Context> ctx_args,
locale_ref loc = locale_ref())
context_base(
OutputIt out,
basic_string_view<char_type> format_str,
basic_format_args<Context> ctx_args,
locale_ref loc = locale_ref())
: parse_context_(format_str), out_(out), args_(ctx_args), loc_(loc) {}
// Returns the argument with specified index.
@ -1131,8 +1144,8 @@ make_arg(const T &value) {
// Formatting context.
template <typename OutputIt, typename Char>
class basic_format_context
: public internal::context_base<
OutputIt, basic_format_context<OutputIt, Char>, Char> {
: public internal::
context_base<OutputIt, basic_format_context<OutputIt, Char>, Char> {
public:
/** The character type for the output. */
typedef Char char_type;
@ -1160,9 +1173,11 @@ class basic_format_context
Constructs a ``basic_format_context`` object. References to the arguments are
stored in the object so make sure they have appropriate lifetimes.
*/
basic_format_context(OutputIt out, basic_string_view<char_type> format_str,
basic_format_args<basic_format_context> ctx_args,
internal::locale_ref loc = internal::locale_ref())
basic_format_context(
OutputIt out,
basic_string_view<char_type> format_str,
basic_format_args<basic_format_context> ctx_args,
internal::locale_ref loc = internal::locale_ref())
: base(out, format_str, ctx_args, loc) {}
format_arg next_arg() {
@ -1178,7 +1193,8 @@ class basic_format_context
template <typename Char>
struct buffer_context {
typedef basic_format_context<
std::back_insert_iterator<internal::basic_buffer<Char>>, Char>
std::back_insert_iterator<internal::basic_buffer<Char>>,
Char>
type;
};
typedef buffer_context<char>::type format_context;
@ -1199,8 +1215,10 @@ class format_arg_store {
// Packed is a macro on MinGW so use IS_PACKED instead.
static const bool IS_PACKED = NUM_ARGS < internal::max_packed_args;
typedef typename std::conditional<IS_PACKED, internal::value<Context>,
basic_format_arg<Context>>::type value_type;
typedef typename std::conditional<
IS_PACKED,
internal::value<Context>,
basic_format_arg<Context>>::type value_type;
// If the arguments are not packed, add one more element to mark the end.
static const size_t DATA_SIZE =
@ -1279,8 +1297,8 @@ class basic_format_args {
typename internal::type type(unsigned index) const {
unsigned shift = index * 4;
return static_cast<typename internal::type>((types_ & (0xfull << shift)) >>
shift);
return static_cast<typename internal::type>(
(types_ & (0xfull << shift)) >> shift);
}
friend class internal::arg_map<Context>;
@ -1366,13 +1384,14 @@ struct wformat_args : basic_format_args<wformat_context> {
#if FMT_USE_ALIAS_TEMPLATES
/** String's character type. */
template <typename S>
using char_t = FMT_ENABLE_IF_T(internal::is_string<S>::value,
typename internal::char_t<S>::type);
using char_t = FMT_ENABLE_IF_T(
internal::is_string<S>::value, typename internal::char_t<S>::type);
#define FMT_CHAR(S) fmt::char_t<S>
#else
template <typename S>
struct char_t : std::enable_if<internal::is_string<S>::value,
typename internal::char_t<S>::type> {};
struct char_t : std::enable_if<
internal::is_string<S>::value,
typename internal::char_t<S>::type> {};
#define FMT_CHAR(S) typename char_t<S>::type
#endif
@ -1430,7 +1449,8 @@ std::basic_string<Char> vformat(
template <typename Char>
typename buffer_context<Char>::type::iterator vformat_to(
internal::basic_buffer<Char> &buf, basic_string_view<Char> format_str,
internal::basic_buffer<Char> &buf,
basic_string_view<Char> format_str,
basic_format_args<typename buffer_context<Char>::type> args);
} // namespace internal
@ -1468,21 +1488,26 @@ struct is_contiguous<internal::basic_buffer<Char>> : std::true_type {};
/** Formats a string and writes the output to ``out``. */
template <typename Container, typename S>
typename std::enable_if<is_contiguous<Container>::value,
std::back_insert_iterator<Container>>::type
vformat_to(std::back_insert_iterator<Container> out, const S &format_str,
basic_format_args<typename buffer_context<FMT_CHAR(S)>::type> args) {
typename std::enable_if<
is_contiguous<Container>::value,
std::back_insert_iterator<Container>>::type
vformat_to(
std::back_insert_iterator<Container> out,
const S &format_str,
basic_format_args<typename buffer_context<FMT_CHAR(S)>::type> args) {
internal::container_buffer<Container> buf(internal::get_container(out));
internal::vformat_to(buf, to_string_view(format_str), args);
return out;
}
template <typename Container, typename S, typename... Args>
inline typename std::enable_if<is_contiguous<Container>::value &&
internal::is_string<S>::value,
std::back_insert_iterator<Container>>::type
format_to(std::back_insert_iterator<Container> out, const S &format_str,
const Args &... args) {
inline typename std::enable_if<
is_contiguous<Container>::value && internal::is_string<S>::value,
std::back_insert_iterator<Container>>::type
format_to(
std::back_insert_iterator<Container> out,
const S &format_str,
const Args &... args) {
internal::checked_args<S, Args...> ca(format_str, args...);
return vformat_to(out, to_string_view(format_str), *ca);
}
@ -1505,8 +1530,8 @@ inline std::basic_string<Char> vformat(
\endrst
*/
template <typename S, typename... Args>
inline std::basic_string<FMT_CHAR(S)> format(const S &format_str,
const Args &... args) {
inline std::basic_string<FMT_CHAR(S)> format(
const S &format_str, const Args &... args) {
return internal::vformat(
to_string_view(format_str),
*internal::checked_args<S, Args...>(format_str, args...));
@ -1529,8 +1554,10 @@ FMT_API void vprint(std::FILE *f, wstring_view format_str, wformat_args args);
template <typename S, typename... Args>
inline FMT_ENABLE_IF_T(internal::is_string<S>::value, void)
print(std::FILE *f, const S &format_str, const Args &... args) {
vprint(f, to_string_view(format_str),
internal::checked_args<S, Args...>(format_str, args...));
vprint(
f,
to_string_view(format_str),
internal::checked_args<S, Args...>(format_str, args...));
}
FMT_API void vprint(string_view format_str, format_args args);
@ -1548,8 +1575,9 @@ FMT_API void vprint(wstring_view format_str, wformat_args args);
template <typename S, typename... Args>
inline FMT_ENABLE_IF_T(internal::is_string<S>::value, void)
print(const S &format_str, const Args &... args) {
vprint(to_string_view(format_str),
internal::checked_args<S, Args...>(format_str, args...));
vprint(
to_string_view(format_str),
internal::checked_args<S, Args...>(format_str, args...));
}
FMT_END_NAMESPACE

View File

@ -95,8 +95,8 @@ typedef void (*FormatFunc)(internal::buffer &, int, string_view);
// 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 {
int safe_strerror(int error_code, char *&buffer, std::size_t buffer_size)
FMT_NOEXCEPT {
FMT_ASSERT(buffer != FMT_NULL && buffer_size != 0, "invalid buffer");
class dispatcher {
@ -153,8 +153,8 @@ int safe_strerror(int error_code, char *&buffer,
return dispatcher(error_code, buffer, buffer_size).run();
}
void format_error_code(internal::buffer &out, int error_code,
string_view message) FMT_NOEXCEPT {
void format_error_code(
internal::buffer &out, int error_code, string_view 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.
@ -180,8 +180,8 @@ void format_error_code(internal::buffer &out, int error_code,
assert(out.size() <= inline_buffer_size);
}
void report_error(FormatFunc func, int error_code,
string_view message) FMT_NOEXCEPT {
void report_error(FormatFunc func, int error_code, string_view message)
FMT_NOEXCEPT {
memory_buffer full_message;
func(full_message, error_code, message);
// Use Writer::data instead of Writer::c_str to avoid potential memory
@ -228,8 +228,8 @@ FMT_FUNC Char internal::thousands_sep_impl(locale_ref) {
}
#endif
FMT_FUNC void system_error::init(int err_code, string_view format_str,
format_args args) {
FMT_FUNC void system_error::init(
int err_code, string_view format_str, format_args args) {
error_code_ = err_code;
memory_buffer buffer;
format_system_error(buffer, err_code, vformat(format_str, args));
@ -239,17 +239,19 @@ FMT_FUNC void system_error::init(int err_code, string_view format_str,
namespace internal {
template <typename T>
int char_traits<char>::format_float(char *buf, std::size_t size,
const char *format, int precision,
T value) {
int char_traits<char>::format_float(
char *buf, std::size_t size, const char *format, int precision, T value) {
return precision < 0 ? FMT_SNPRINTF(buf, size, format, value)
: FMT_SNPRINTF(buf, size, format, precision, value);
}
template <typename T>
int char_traits<wchar_t>::format_float(wchar_t *buf, std::size_t size,
const wchar_t *format, int precision,
T value) {
int char_traits<wchar_t>::format_float(
wchar_t *buf,
std::size_t size,
const wchar_t *format,
int precision,
T value) {
return precision < 0 ? FMT_SWPRINTF(buf, size, format, value)
: FMT_SWPRINTF(buf, size, format, precision, value);
}
@ -276,7 +278,9 @@ const uint32_t basic_data<T>::ZERO_OR_POWERS_OF_10_32[] = {0,
template <typename T>
const uint64_t basic_data<T>::ZERO_OR_POWERS_OF_10_64[] = {
0, FMT_POWERS_OF_10(1), FMT_POWERS_OF_10(1000000000ull),
0,
FMT_POWERS_OF_10(1),
FMT_POWERS_OF_10(1000000000ull),
10000000000000000000ull};
// Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340.
@ -451,9 +455,15 @@ FMT_FUNC fp get_cached_power(int min_exponent, int &pow10_exponent) {
return fp(data::POW10_SIGNIFICANDS[index], data::POW10_EXPONENTS[index]);
}
FMT_FUNC bool grisu2_round(char *buf, ptrdiff_t &size, size_t max_digits,
uint64_t delta, uint64_t remainder, uint64_t exp,
uint64_t diff, int &exp10) {
FMT_FUNC bool grisu2_round(
char *buf,
ptrdiff_t &size,
size_t max_digits,
uint64_t delta,
uint64_t remainder,
uint64_t exp,
uint64_t diff,
int &exp10) {
while (
remainder < diff && delta - remainder >= exp &&
(remainder + exp < diff || diff - remainder > remainder + exp - diff)) {
@ -470,10 +480,16 @@ FMT_FUNC bool grisu2_round(char *buf, ptrdiff_t &size, size_t max_digits,
}
// Generates output using Grisu2 digit-gen algorithm.
FMT_FUNC bool grisu2_gen_digits(char *buf, ptrdiff_t &size, uint32_t hi,
uint64_t lo, int &exp, uint64_t delta,
const fp &one, const fp &diff,
size_t max_digits) {
FMT_FUNC bool grisu2_gen_digits(
char *buf,
ptrdiff_t &size,
uint32_t hi,
uint64_t lo,
int &exp,
uint64_t delta,
const fp &one,
const fp &diff,
size_t max_digits) {
// Generate digits for the most significant part (hi).
while (exp > 0) {
uint32_t digit = 0;
@ -529,8 +545,13 @@ FMT_FUNC bool grisu2_gen_digits(char *buf, ptrdiff_t &size, uint32_t hi,
uint64_t remainder = (static_cast<uint64_t>(hi) << -one.e) + lo;
if (remainder <= delta || size > static_cast<ptrdiff_t>(max_digits)) {
return grisu2_round(
buf, size, max_digits, delta, remainder,
static_cast<uint64_t>(data::POWERS_OF_10_32[exp]) << -one.e, diff.f,
buf,
size,
max_digits,
delta,
remainder,
static_cast<uint64_t>(data::POWERS_OF_10_32[exp]) << -one.e,
diff.f,
exp);
}
}
@ -544,8 +565,15 @@ FMT_FUNC bool grisu2_gen_digits(char *buf, ptrdiff_t &size, uint32_t hi,
lo &= one.f - 1;
--exp;
if (lo < delta || size > static_cast<ptrdiff_t>(max_digits)) {
return grisu2_round(buf, size, max_digits, delta, lo, one.f,
diff.f * data::POWERS_OF_10_32[-exp], exp);
return grisu2_round(
buf,
size,
max_digits,
delta,
lo,
one.f,
diff.f * data::POWERS_OF_10_32[-exp],
exp);
}
}
}
@ -636,8 +664,8 @@ struct fill {
// The number is given as v = f * pow(10, exp), where f has size digits.
template <typename Handler>
FMT_FUNC void grisu2_prettify(const gen_digits_params &params, int size,
int exp, Handler &&handler) {
FMT_FUNC void grisu2_prettify(
const gen_digits_params &params, int size, int exp, Handler &&handler) {
if (!params.fixed) {
// Insert a decimal point after the first digit and add an exponent.
handler.insert(1, '.');
@ -692,8 +720,8 @@ struct char_counter {
// Converts format specifiers into parameters for digit generation and computes
// output buffer size for a number in the range [pow(10, exp - 1), pow(10, exp)
// or 0 if exp == 1.
FMT_FUNC gen_digits_params process_specs(const core_format_specs &specs,
int exp, buffer &buf) {
FMT_FUNC gen_digits_params
process_specs(const core_format_specs &specs, int exp, buffer &buf) {
auto params = gen_digits_params();
int num_digits = specs.precision >= 0 ? specs.precision : 6;
switch (specs.type) {
@ -754,7 +782,8 @@ grisu2_format(Double value, buffer &buf, core_format_specs specs) {
const int min_exp = -60; // alpha in Grisu.
int cached_exp = 0; // K in Grisu.
auto cached_pow = get_cached_power( // \tilde{c}_{-k} in Grisu.
min_exp - (upper.e + fp::significand_size), cached_exp);
min_exp - (upper.e + fp::significand_size),
cached_exp);
cached_exp = -cached_exp;
upper = upper * cached_pow; // \tilde{M}^+ in Grisu.
--upper.f; // \tilde{M}^+ - 1 ulp -> M^+_{\downarrow}.
@ -774,8 +803,8 @@ grisu2_format(Double value, buffer &buf, core_format_specs specs) {
// lo = supper % one.
uint64_t lo = upper.f & (one.f - 1);
ptrdiff_t size = 0;
if (!grisu2_gen_digits(buf.data(), size, hi, lo, exp, delta, one, diff,
params.num_digits)) {
if (!grisu2_gen_digits(
buf.data(), size, hi, lo, exp, delta, one, diff, params.num_digits)) {
buf.clear();
return false;
}
@ -784,8 +813,8 @@ grisu2_format(Double value, buffer &buf, core_format_specs specs) {
}
template <typename Double>
void sprintf_format(Double value, internal::buffer &buf,
core_format_specs spec) {
void sprintf_format(
Double value, internal::buffer &buf, core_format_specs spec) {
// Buffer capacity must be non-zero, otherwise MSVC's vsnprintf_s will fail.
FMT_ASSERT(buf.capacity() != 0, "empty buffer");
@ -842,13 +871,13 @@ FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
return;
}
int length = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s.data(),
s_size, FMT_NULL, 0);
int length = MultiByteToWideChar(
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);
if (length == 0)
FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
buffer_.resize(length + 1);
length = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size,
&buffer_[0], length);
length = MultiByteToWideChar(
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
if (length == 0)
FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
buffer_[length] = 0;
@ -856,8 +885,8 @@ FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
FMT_FUNC internal::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
if (int error_code = convert(s)) {
FMT_THROW(windows_error(error_code,
"cannot convert string from UTF-16 to UTF-8"));
FMT_THROW(windows_error(
error_code, "cannot convert string from UTF-16 to UTF-8"));
}
}
@ -872,21 +901,21 @@ FMT_FUNC int internal::utf16_to_utf8::convert(wstring_view s) {
return 0;
}
int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0,
FMT_NULL, FMT_NULL);
int length = WideCharToMultiByte(
CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);
if (length == 0)
return GetLastError();
buffer_.resize(length + 1);
length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, &buffer_[0],
length, FMT_NULL, FMT_NULL);
length = WideCharToMultiByte(
CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);
if (length == 0)
return GetLastError();
buffer_[length] = 0;
return 0;
}
FMT_FUNC void windows_error::init(int err_code, string_view format_str,
format_args args) {
FMT_FUNC void windows_error::init(
int err_code, string_view format_str, format_args args) {
error_code_ = err_code;
memory_buffer buffer;
internal::format_windows_error(buffer, err_code, vformat(format_str, args));
@ -894,18 +923,21 @@ FMT_FUNC void windows_error::init(int err_code, string_view format_str,
base = std::runtime_error(to_string(buffer));
}
FMT_FUNC void internal::format_windows_error(internal::buffer &out,
int error_code,
string_view message) FMT_NOEXCEPT {
FMT_FUNC void internal::format_windows_error(
internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
FMT_TRY {
wmemory_buffer buf;
buf.resize(inline_buffer_size);
for (;;) {
wchar_t *system_message = &buf[0];
int result = FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, FMT_NULL,
error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), system_message,
static_cast<uint32_t>(buf.size()), FMT_NULL);
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
FMT_NULL,
error_code,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
system_message,
static_cast<uint32_t>(buf.size()),
FMT_NULL);
if (result != 0) {
utf16_to_utf8 utf8_message;
if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
@ -928,8 +960,8 @@ FMT_FUNC void internal::format_windows_error(internal::buffer &out,
#endif // FMT_USE_WINDOWS_H
FMT_FUNC void format_system_error(internal::buffer &out, int error_code,
string_view message) FMT_NOEXCEPT {
FMT_FUNC void format_system_error(
internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
FMT_TRY {
memory_buffer buf;
buf.resize(inline_buffer_size);
@ -956,22 +988,22 @@ FMT_FUNC void internal::error_handler::on_error(const char *message) {
FMT_THROW(format_error(message));
}
FMT_FUNC void report_system_error(int error_code,
fmt::string_view message) FMT_NOEXCEPT {
FMT_FUNC void report_system_error(int error_code, fmt::string_view message)
FMT_NOEXCEPT {
report_error(format_system_error, error_code, message);
}
#if FMT_USE_WINDOWS_H
FMT_FUNC void report_windows_error(int error_code,
fmt::string_view message) FMT_NOEXCEPT {
FMT_FUNC void report_windows_error(int error_code, fmt::string_view message)
FMT_NOEXCEPT {
report_error(internal::format_windows_error, error_code, message);
}
#endif
FMT_FUNC void vprint(std::FILE *f, string_view format_str, format_args args) {
memory_buffer buffer;
internal::vformat_to(buffer, format_str,
basic_format_args<buffer_context<char>::type>(args));
internal::vformat_to(
buffer, format_str, basic_format_args<buffer_context<char>::type>(args));
std::fwrite(buffer.data(), 1, buffer.size(), f);
}

View File

@ -130,8 +130,9 @@ FMT_END_NAMESPACE
#ifndef FMT_USE_USER_DEFINED_LITERALS
// For Intel's compiler and NVIDIA's compiler both it and the system gcc/msc
// must support UDLs.
#if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \
FMT_MSC_VER >= 1900) && \
#if ( \
FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \
FMT_MSC_VER >= 1900) && \
(!(FMT_ICC_VERSION || FMT_CUDA_VERSION) || FMT_ICC_VERSION >= 1500 || \
FMT_CUDA_VERSION >= 700)
#define FMT_USE_USER_DEFINED_LITERALS 1
@ -398,8 +399,8 @@ struct checked {
// Make a checked iterator to avoid warnings on MSVC.
template <typename T>
inline stdext::checked_array_iterator<T *> make_checked(T *p,
std::size_t size) {
inline stdext::checked_array_iterator<T *> make_checked(
T *p, std::size_t size) {
return {p, size};
}
#else
@ -418,8 +419,8 @@ template <typename U>
void basic_buffer<T>::append(const U *begin, const U *end) {
std::size_t new_size = size_ + internal::to_unsigned(end - begin);
reserve(new_size);
std::uninitialized_copy(begin, end,
internal::make_checked(ptr_, capacity_) + size_);
std::uninitialized_copy(
begin, end, internal::make_checked(ptr_, capacity_) + size_);
size_ = new_size;
}
} // namespace internal
@ -439,8 +440,8 @@ class u8string_view : public basic_string_view<char8_t> {
u8string_view(const char *s)
: basic_string_view<char8_t>(reinterpret_cast<const char8_t *>(s)) {}
u8string_view(const char *s, size_t count) FMT_NOEXCEPT
: basic_string_view<char8_t>(reinterpret_cast<const char8_t *>(s),
count) {}
: basic_string_view<char8_t>(
reinterpret_cast<const char8_t *>(s), count) {}
};
#if FMT_USE_USER_DEFINED_LITERALS
@ -484,8 +485,10 @@ enum { inline_buffer_size = 500 };
The output can be converted to an ``std::string`` with ``to_string(out)``.
\endrst
*/
template <typename T, std::size_t SIZE = inline_buffer_size,
typename Allocator = std::allocator<T>>
template <
typename T,
std::size_t SIZE = inline_buffer_size,
typename Allocator = std::allocator<T>>
class basic_memory_buffer : private Allocator,
public internal::basic_buffer<T> {
private:
@ -517,8 +520,10 @@ class basic_memory_buffer : private Allocator,
std::size_t size = other.size(), capacity = other.capacity();
if (data == other.store_) {
this->set(store_, capacity);
std::uninitialized_copy(other.store_, other.store_ + size,
internal::make_checked(store_, capacity));
std::uninitialized_copy(
other.store_,
other.store_ + size,
internal::make_checked(store_, capacity));
} else {
this->set(data, capacity);
// Set pointer to the inline array so that delete is not called
@ -562,8 +567,10 @@ void basic_memory_buffer<T, SIZE, Allocator>::grow(std::size_t size) {
T *old_data = this->data();
T *new_data = internal::allocate<Allocator>(*this, new_capacity);
// The following code doesn't throw, so the raw pointer above doesn't leak.
std::uninitialized_copy(old_data, old_data + this->size(),
internal::make_checked(new_data, new_capacity));
std::uninitialized_copy(
old_data,
old_data + this->size(),
internal::make_checked(new_data, new_capacity));
this->set(new_data, new_capacity);
// deallocate must not throw according to the standard, but even if it does,
// the buffer already uses the new storage and will deallocate it in
@ -584,33 +591,50 @@ template <>
struct char_traits<char> {
// Formats a floating-point number.
template <typename T>
FMT_API static int format_float(char *buffer, std::size_t size,
const char *format, int precision, T value);
FMT_API static int format_float(
char *buffer,
std::size_t size,
const char *format,
int precision,
T value);
};
template <>
struct char_traits<wchar_t> {
template <typename T>
FMT_API static int format_float(wchar_t *buffer, std::size_t size,
const wchar_t *format, int precision,
T value);
FMT_API static int format_float(
wchar_t *buffer,
std::size_t size,
const wchar_t *format,
int precision,
T value);
};
#if FMT_USE_EXTERN_TEMPLATES
extern template int char_traits<char>::format_float<double>(char *buffer,
std::size_t size,
const char *format,
int precision,
double value);
extern template int char_traits<char>::format_float<double>(
char *buffer,
std::size_t size,
const char *format,
int precision,
double value);
extern template int char_traits<char>::format_float<long double>(
char *buffer, std::size_t size, const char *format, int precision,
char *buffer,
std::size_t size,
const char *format,
int precision,
long double value);
extern template int char_traits<wchar_t>::format_float<double>(
wchar_t *buffer, std::size_t size, const wchar_t *format, int precision,
wchar_t *buffer,
std::size_t size,
const wchar_t *format,
int precision,
double value);
extern template int char_traits<wchar_t>::format_float<long double>(
wchar_t *buffer, std::size_t size, const wchar_t *format, int precision,
wchar_t *buffer,
std::size_t size,
const wchar_t *format,
int precision,
long double value);
#endif
@ -694,9 +718,10 @@ class truncating_iterator_base {
// An output iterator that truncates the output and counts the number of objects
// written to it.
template <typename OutputIt,
typename Enable = typename std::is_void<
typename std::iterator_traits<OutputIt>::value_type>::type>
template <
typename OutputIt,
typename Enable = typename std::is_void<
typename std::iterator_traits<OutputIt>::value_type>::type>
class truncating_iterator;
template <typename OutputIt>
@ -768,8 +793,10 @@ template <typename T>
struct int_traits {
// Smallest of uint32_t and uint64_t that is large enough to represent
// all values of T.
typedef typename std::conditional<std::numeric_limits<T>::digits <= 32,
uint32_t, uint64_t>::type main_type;
typedef typename std::conditional<
std::numeric_limits<T>::digits <= 32,
uint32_t,
uint64_t>::type main_type;
};
// Static data is placed in this class template to allow header-only
@ -838,21 +865,23 @@ inline char8_t to_char8_t(char c) { return static_cast<char8_t>(c); }
template <typename InputIt, typename OutChar>
struct needs_conversion
: std::integral_constant<
bool, std::is_same<typename std::iterator_traits<InputIt>::value_type,
char>::value &&
std::is_same<OutChar, char8_t>::value> {};
bool,
std::is_same<
typename std::iterator_traits<InputIt>::value_type,
char>::value &&
std::is_same<OutChar, char8_t>::value> {};
template <typename OutChar, typename InputIt, typename OutputIt>
typename std::enable_if<!needs_conversion<InputIt, OutChar>::value,
OutputIt>::type
copy_str(InputIt begin, InputIt end, OutputIt it) {
typename std::enable_if<!needs_conversion<InputIt, OutChar>::value, OutputIt>::
type
copy_str(InputIt begin, InputIt end, OutputIt it) {
return std::copy(begin, end, it);
}
template <typename OutChar, typename InputIt, typename OutputIt>
typename std::enable_if<needs_conversion<InputIt, OutChar>::value,
OutputIt>::type
copy_str(InputIt begin, InputIt end, OutputIt it) {
typename std::enable_if<needs_conversion<InputIt, OutChar>::value, OutputIt>::
type
copy_str(InputIt begin, InputIt end, OutputIt it) {
return std::transform(begin, end, it, to_char8_t);
}
@ -971,8 +1000,10 @@ class add_thousands_sep {
if (++digit_index_ % 3 != 0)
return;
buffer -= sep_.size();
std::uninitialized_copy(sep_.data(), sep_.data() + sep_.size(),
internal::make_checked(buffer, sep_.size()));
std::uninitialized_copy(
sep_.data(),
sep_.data() + sep_.size(),
internal::make_checked(buffer, sep_.size()));
}
enum { size = 1 };
@ -995,8 +1026,8 @@ inline wchar_t thousands_sep(locale_ref loc) {
// thousands_sep is a functor that is called after writing each char to
// add a thousands separator if necessary.
template <typename UInt, typename Char, typename ThousandsSep>
inline Char *format_decimal(Char *buffer, UInt value, unsigned num_digits,
ThousandsSep thousands_sep) {
inline Char *format_decimal(
Char *buffer, UInt value, unsigned num_digits, ThousandsSep thousands_sep) {
buffer += num_digits;
Char *end = buffer;
while (value >= 100) {
@ -1021,10 +1052,13 @@ inline Char *format_decimal(Char *buffer, UInt value, unsigned num_digits,
return end;
}
template <typename OutChar, typename UInt, typename Iterator,
typename ThousandsSep>
inline Iterator format_decimal(Iterator out, UInt value, unsigned num_digits,
ThousandsSep sep) {
template <
typename OutChar,
typename UInt,
typename Iterator,
typename ThousandsSep>
inline Iterator format_decimal(
Iterator out, UInt value, unsigned num_digits, ThousandsSep sep) {
typedef typename ThousandsSep::char_type char_type;
// Buffer should be large enough to hold all digits (<= digits10 + 1).
enum { max_size = std::numeric_limits<UInt>::digits10 + 1 };
@ -1040,8 +1074,8 @@ inline It format_decimal(It out, UInt value, unsigned num_digits) {
}
template <unsigned BASE_BITS, typename Char, typename UInt>
inline Char *format_uint(Char *buffer, UInt value, unsigned num_digits,
bool upper = false) {
inline Char *format_uint(
Char *buffer, UInt value, unsigned num_digits, bool upper = false) {
buffer += num_digits;
Char *end = buffer;
do {
@ -1053,8 +1087,8 @@ inline Char *format_uint(Char *buffer, UInt value, unsigned num_digits,
}
template <unsigned BASE_BITS, typename Char, typename It, typename UInt>
inline It format_uint(It out, UInt value, unsigned num_digits,
bool upper = false) {
inline It format_uint(
It out, UInt value, unsigned num_digits, bool upper = false) {
// Buffer should be large enough to hold all digits (digits / BASE_BITS + 1)
// and null.
char buffer[std::numeric_limits<UInt>::digits / BASE_BITS + 2];
@ -1105,8 +1139,10 @@ class utf16_to_utf8 {
FMT_API int convert(wstring_view s);
};
FMT_API void format_windows_error(fmt::internal::buffer &out, int error_code,
fmt::string_view message) FMT_NOEXCEPT;
FMT_API void format_windows_error(
fmt::internal::buffer &out,
int error_code,
fmt::string_view message) FMT_NOEXCEPT;
#endif
template <typename T = void>
@ -1232,8 +1268,8 @@ FMT_CONSTEXPR void handle_float_type_spec(char spec, Handler &&handler) {
}
template <typename Char, typename Handler>
FMT_CONSTEXPR void handle_char_specs(const basic_format_specs<Char> *specs,
Handler &&handler) {
FMT_CONSTEXPR void handle_char_specs(
const basic_format_specs<Char> *specs, Handler &&handler) {
if (!specs)
return handler.on_char();
if (specs->type && specs->type != 'c')
@ -1420,9 +1456,9 @@ class arg_formatter_base {
}
template <typename T>
typename std::enable_if<std::is_integral<T>::value ||
std::is_same<T, char_type>::value,
iterator>::type
typename std::enable_if<
std::is_integral<T>::value || std::is_same<T, char_type>::value,
iterator>::type
operator()(T value) {
// MSVC2013 fails to compile separate overloads for bool and char_type so
// use std::is_same instead.
@ -1476,8 +1512,8 @@ class arg_formatter_base {
iterator operator()(const char_type *value) {
if (!specs_)
return write(value), out();
internal::handle_cstring_type_spec(specs_->type,
cstring_spec_handler(*this, value));
internal::handle_cstring_type_spec(
specs_->type, cstring_spec_handler(*this, value));
return out();
}
@ -1507,9 +1543,8 @@ FMT_CONSTEXPR bool is_name_start(Char c) {
// Parses the range [begin, end) as an unsigned integer. This function assumes
// that the range is non-empty and the first character is a digit.
template <typename Char, typename ErrorHandler>
FMT_CONSTEXPR unsigned parse_nonnegative_int(const Char *&begin,
const Char *end,
ErrorHandler &&eh) {
FMT_CONSTEXPR unsigned parse_nonnegative_int(
const Char *&begin, const Char *end, ErrorHandler &&eh) {
assert(begin != end && '0' <= *begin && *begin <= '9');
if (*begin == '0') {
++begin;
@ -1712,10 +1747,13 @@ class specs_checker : public Handler {
internal::type arg_type_;
};
template <template <typename> class Handler, typename T, typename Context,
typename ErrorHandler>
FMT_CONSTEXPR void set_dynamic_spec(T &value, basic_format_arg<Context> arg,
ErrorHandler eh) {
template <
template <typename> class Handler,
typename T,
typename Context,
typename ErrorHandler>
FMT_CONSTEXPR void set_dynamic_spec(
T &value, basic_format_arg<Context> arg, ErrorHandler eh) {
unsigned long long big_value =
visit_format_arg(Handler<ErrorHandler>(eh), arg);
if (big_value > to_unsigned((std::numeric_limits<int>::max)()))
@ -1731,20 +1769,20 @@ class specs_handler : public specs_setter<typename Context::char_type> {
public:
typedef typename Context::char_type char_type;
FMT_CONSTEXPR specs_handler(basic_format_specs<char_type> &specs,
Context &ctx)
FMT_CONSTEXPR specs_handler(
basic_format_specs<char_type> &specs, Context &ctx)
: specs_setter<char_type>(specs), context_(ctx) {}
template <typename Id>
FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {
set_dynamic_spec<width_checker>(this->specs_.width_, get_arg(arg_id),
context_.error_handler());
set_dynamic_spec<width_checker>(
this->specs_.width_, get_arg(arg_id), context_.error_handler());
}
template <typename Id>
FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {
set_dynamic_spec<precision_checker>(this->specs_.precision, get_arg(arg_id),
context_.error_handler());
set_dynamic_spec<precision_checker>(
this->specs_.precision, get_arg(arg_id), context_.error_handler());
}
void on_error(const char *message) { context_.on_error(message); }
@ -1804,8 +1842,8 @@ class dynamic_specs_handler
public:
typedef typename ParseContext::char_type char_type;
FMT_CONSTEXPR dynamic_specs_handler(dynamic_format_specs<char_type> &specs,
ParseContext &ctx)
FMT_CONSTEXPR dynamic_specs_handler(
dynamic_format_specs<char_type> &specs, ParseContext &ctx)
: specs_setter<char_type>(specs), specs_(specs), context_(ctx) {}
FMT_CONSTEXPR dynamic_specs_handler(const dynamic_specs_handler &other)
@ -1845,8 +1883,8 @@ class dynamic_specs_handler
};
template <typename Char, typename IDHandler>
FMT_CONSTEXPR const Char *parse_arg_id(const Char *begin, const Char *end,
IDHandler &&handler) {
FMT_CONSTEXPR const Char *parse_arg_id(
const Char *begin, const Char *end, IDHandler &&handler) {
assert(begin != end);
Char c = *begin;
if (c == '}' || c == ':')
@ -1908,8 +1946,8 @@ struct precision_adapter {
// Parses fill and alignment.
template <typename Char, typename Handler>
FMT_CONSTEXPR const Char *parse_align(const Char *begin, const Char *end,
Handler &&handler) {
FMT_CONSTEXPR const Char *parse_align(
const Char *begin, const Char *end, Handler &&handler) {
FMT_ASSERT(begin != end, "");
alignment align = ALIGN_DEFAULT;
int i = 0;
@ -1947,8 +1985,8 @@ FMT_CONSTEXPR const Char *parse_align(const Char *begin, const Char *end,
}
template <typename Char, typename Handler>
FMT_CONSTEXPR const Char *parse_width(const Char *begin, const Char *end,
Handler &&handler) {
FMT_CONSTEXPR const Char *parse_width(
const Char *begin, const Char *end, Handler &&handler) {
FMT_ASSERT(begin != end, "");
if ('0' <= *begin && *begin <= '9') {
handler.on_width(parse_nonnegative_int(begin, end, handler));
@ -1966,8 +2004,8 @@ FMT_CONSTEXPR const Char *parse_width(const Char *begin, const Char *end,
// Parses standard format specifiers and sends notifications about parsed
// components to handler.
template <typename Char, typename SpecHandler>
FMT_CONSTEXPR const Char *parse_format_specs(const Char *begin, const Char *end,
SpecHandler &&handler) {
FMT_CONSTEXPR const Char *parse_format_specs(
const Char *begin, const Char *end, SpecHandler &&handler) {
if (begin == end || *begin == '}')
return begin;
@ -2019,8 +2057,8 @@ FMT_CONSTEXPR const Char *parse_format_specs(const Char *begin, const Char *end,
} else if (c == '{') {
++begin;
if (begin != end) {
begin = parse_arg_id(begin, end,
precision_adapter<SpecHandler, Char>(handler));
begin = parse_arg_id(
begin, end, precision_adapter<SpecHandler, Char>(handler));
}
if (begin == end || *begin++ != '}')
return handler.on_error("invalid format string"), begin;
@ -2047,8 +2085,8 @@ FMT_CONSTEXPR bool find(Ptr first, Ptr last, T value, Ptr &out) {
}
template <>
inline bool find<false, char>(const char *first, const char *last, char value,
const char *&out) {
inline bool find<false, char>(
const char *first, const char *last, char value, const char *&out) {
out = static_cast<const char *>(std::memchr(first, value, last - first));
return out != FMT_NULL;
}
@ -2067,8 +2105,8 @@ struct id_adapter {
};
template <bool IS_CONSTEXPR, typename Char, typename Handler>
FMT_CONSTEXPR void parse_format_string(basic_string_view<Char> format_str,
Handler &&handler) {
FMT_CONSTEXPR void parse_format_string(
basic_string_view<Char> format_str, Handler &&handler) {
struct writer {
FMT_CONSTEXPR void operator()(const Char *begin, const Char *end) {
if (begin == end)
@ -2180,8 +2218,8 @@ class format_string_checker {
};
template <typename Char, typename ErrorHandler, typename... Args>
FMT_CONSTEXPR bool do_check_format_string(basic_string_view<Char> s,
ErrorHandler eh = ErrorHandler()) {
FMT_CONSTEXPR bool do_check_format_string(
basic_string_view<Char> s, ErrorHandler eh = ErrorHandler()) {
format_string_checker<Char, ErrorHandler, Args...> checker(s, eh);
parse_format_string<true>(s, checker);
return true;
@ -2191,9 +2229,9 @@ template <typename... Args, typename S>
typename std::enable_if<is_compile_string<S>::value>::type check_format_string(
S format_str) {
typedef typename S::char_type char_t;
FMT_CONSTEXPR_DECL bool invalid_format =
internal::do_check_format_string<char_t, internal::error_handler,
Args...>(to_string_view(format_str));
FMT_CONSTEXPR_DECL bool invalid_format = internal::
do_check_format_string<char_t, internal::error_handler, Args...>(
to_string_view(format_str));
(void)invalid_format;
}
@ -2206,19 +2244,20 @@ struct format_type
};
template <template <typename> class Handler, typename Spec, typename Context>
void handle_dynamic_spec(Spec &value, arg_ref<typename Context::char_type> ref,
Context &ctx) {
void handle_dynamic_spec(
Spec &value, arg_ref<typename Context::char_type> ref, Context &ctx) {
typedef typename Context::char_type char_type;
switch (ref.kind) {
case arg_ref<char_type>::NONE:
break;
case arg_ref<char_type>::INDEX:
internal::set_dynamic_spec<Handler>(value, ctx.get_arg(ref.index),
ctx.error_handler());
internal::set_dynamic_spec<Handler>(
value, ctx.get_arg(ref.index), ctx.error_handler());
break;
case arg_ref<char_type>::NAME:
internal::set_dynamic_spec<Handler>(
value, ctx.get_arg({ref.name.value, ref.name.size}),
value,
ctx.get_arg({ref.name.value, ref.name.size}),
ctx.error_handler());
break;
}
@ -2323,8 +2362,10 @@ class system_error : public std::runtime_error {
may look like "Unknown error -1" and is platform-dependent.
\endrst
*/
FMT_API void format_system_error(internal::buffer &out, int error_code,
fmt::string_view message) FMT_NOEXCEPT;
FMT_API void format_system_error(
internal::buffer &out,
int error_code,
fmt::string_view message) FMT_NOEXCEPT;
/**
This template provides operations for formatting and writing data into a
@ -2398,8 +2439,8 @@ class basic_writer {
// <left-padding><prefix><numeric-padding><digits><right-padding>
// where <digits> are written by f(it).
template <typename Spec, typename F>
void write_int(unsigned num_digits, string_view prefix, const Spec &spec,
F f) {
void write_int(
unsigned num_digits, string_view prefix, const Spec &spec, F f) {
std::size_t size = prefix.size() + num_digits;
char_type fill = static_cast<char_type>(spec.fill());
std::size_t padding = 0;
@ -2485,8 +2526,8 @@ class basic_writer {
void on_dec() {
unsigned num_digits = internal::count_digits(abs_value);
writer.write_int(num_digits, get_prefix(), spec,
dec_writer{abs_value, num_digits});
writer.write_int(
num_digits, get_prefix(), spec, dec_writer{abs_value, num_digits});
}
struct hex_writer {
@ -2495,8 +2536,8 @@ class basic_writer {
template <typename It>
void operator()(It &&it) const {
it = internal::format_uint<4, char_type>(it, self.abs_value, num_digits,
self.spec.type != 'x');
it = internal::format_uint<4, char_type>(
it, self.abs_value, num_digits, self.spec.type != 'x');
}
};
@ -2506,8 +2547,8 @@ class basic_writer {
prefix[prefix_size++] = static_cast<char>(spec.type);
}
unsigned num_digits = count_digits<4>();
writer.write_int(num_digits, get_prefix(), spec,
hex_writer{*this, num_digits});
writer.write_int(
num_digits, get_prefix(), spec, hex_writer{*this, num_digits});
}
template <int BITS>
@ -2527,8 +2568,8 @@ class basic_writer {
prefix[prefix_size++] = static_cast<char>(spec.type);
}
unsigned num_digits = count_digits<1>();
writer.write_int(num_digits, get_prefix(), spec,
bin_writer<1>{abs_value, num_digits});
writer.write_int(
num_digits, get_prefix(), spec, bin_writer<1>{abs_value, num_digits});
}
void on_oct() {
@ -2539,8 +2580,8 @@ class basic_writer {
// is not greater than the number of digits.
prefix[prefix_size++] = '0';
}
writer.write_int(num_digits, get_prefix(), spec,
bin_writer<3>{abs_value, num_digits});
writer.write_int(
num_digits, get_prefix(), spec, bin_writer<3>{abs_value, num_digits});
}
enum { SEP_SIZE = 1 };
@ -2562,8 +2603,8 @@ class basic_writer {
unsigned num_digits = internal::count_digits(abs_value);
char_type sep = internal::thousands_sep<char_type>(writer.locale_);
unsigned size = num_digits + SEP_SIZE * ((num_digits - 1) / 3);
writer.write_int(size, get_prefix(), spec,
num_writer{abs_value, size, sep});
writer.write_int(
size, get_prefix(), spec, num_writer{abs_value, size, sep});
}
void on_error() { FMT_THROW(format_error("invalid type specifier")); }
@ -2572,8 +2613,8 @@ class basic_writer {
// Writes a formatted integer.
template <typename T, typename Spec>
void write_int(T value, const Spec &spec) {
internal::handle_int_type_spec(spec.type,
int_writer<T, Spec>(*this, value, spec));
internal::handle_int_type_spec(
spec.type, int_writer<T, Spec>(*this, value, spec));
}
enum { INF_SIZE = 3 }; // This is an enum to workaround a bug in MSVC.
@ -2639,8 +2680,8 @@ class basic_writer {
public:
/** Constructs a ``basic_writer`` object. */
explicit basic_writer(Range out,
internal::locale_ref loc = internal::locale_ref())
explicit basic_writer(
Range out, internal::locale_ref loc = internal::locale_ref())
: out_(out.begin()), locale_(loc) {}
iterator out() const { return out_; }
@ -2705,8 +2746,8 @@ class basic_writer {
}
template <typename Char>
void write(basic_string_view<Char> s,
const format_specs &spec = format_specs()) {
void write(
basic_string_view<Char> s, const format_specs &spec = format_specs()) {
const Char *data = s.data();
std::size_t size = s.size();
if (spec.precision >= 0 && internal::to_unsigned(spec.precision) < size)
@ -2825,8 +2866,8 @@ void basic_writer<Range>::write_double(T value, const format_specs &spec) {
// Reports a system error without throwing an exception.
// Can be used to report errors from destructors.
FMT_API void report_system_error(int error_code,
string_view message) FMT_NOEXCEPT;
FMT_API void report_system_error(int error_code, string_view message)
FMT_NOEXCEPT;
#if FMT_USE_WINDOWS_H
@ -2872,8 +2913,8 @@ class windows_error : public system_error {
// Reports a Windows error without throwing an exception.
// Can be used to report errors from destructors.
FMT_API void report_windows_error(int error_code,
string_view message) FMT_NOEXCEPT;
FMT_API void report_windows_error(int error_code, string_view message)
FMT_NOEXCEPT;
#endif
@ -2977,16 +3018,19 @@ inline void format_decimal(char *&buffer, T value) {
return;
}
unsigned num_digits = internal::count_digits(abs_value);
internal::format_decimal<char>(internal::make_checked(buffer, num_digits),
abs_value, num_digits);
internal::format_decimal<char>(
internal::make_checked(buffer, num_digits), abs_value, num_digits);
buffer += num_digits;
}
// Formatter of objects of type T.
template <typename T, typename Char>
struct formatter<T, Char,
typename std::enable_if<internal::format_type<
typename buffer_context<Char>::type, T>::value>::type> {
struct formatter<
T,
Char,
typename std::enable_if<
internal::format_type<typename buffer_context<Char>::type, T>::value>::
type> {
// Parses format specifiers stopping either at the end of the range or at the
// terminating '}'.
template <typename ParseContext>
@ -2994,8 +3038,8 @@ struct formatter<T, Char,
typedef internal::dynamic_specs_handler<ParseContext> handler_type;
auto type =
internal::get_type<typename buffer_context<Char>::type, T>::value;
internal::specs_checker<handler_type> handler(handler_type(specs_, ctx),
type);
internal::specs_checker<handler_type> handler(
handler_type(specs_, ctx), type);
auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
auto type_spec = specs_.type;
auto eh = ctx.error_handler();
@ -3009,8 +3053,8 @@ struct formatter<T, Char,
case internal::long_long_type:
case internal::ulong_long_type:
case internal::bool_type:
handle_int_type_spec(type_spec,
internal::int_type_checker<decltype(eh)>(eh));
handle_int_type_spec(
type_spec, internal::int_type_checker<decltype(eh)>(eh));
break;
case internal::char_type:
handle_char_specs(
@ -3018,8 +3062,8 @@ struct formatter<T, Char,
break;
case internal::double_type:
case internal::long_double_type:
handle_float_type_spec(type_spec,
internal::float_type_checker<decltype(eh)>(eh));
handle_float_type_spec(
type_spec, internal::float_type_checker<decltype(eh)>(eh));
break;
case internal::cstring_type:
internal::handle_cstring_type_spec(
@ -3045,11 +3089,13 @@ struct formatter<T, Char,
specs_.width_, specs_.width_ref, ctx);
internal::handle_dynamic_spec<internal::precision_checker>(
specs_.precision, specs_.precision_ref, ctx);
typedef output_range<typename FormatContext::iterator,
typename FormatContext::char_type>
typedef output_range<
typename FormatContext::iterator,
typename FormatContext::char_type>
range_type;
return visit_format_arg(arg_formatter<range_type>(ctx, &specs_),
internal::make_arg<FormatContext>(val));
return visit_format_arg(
arg_formatter<range_type>(ctx, &specs_),
internal::make_arg<FormatContext>(val));
}
private:
@ -3101,11 +3147,13 @@ class dynamic_formatter {
checker.on_hash();
if (specs_.precision != -1)
checker.end_precision();
typedef output_range<typename FormatContext::iterator,
typename FormatContext::char_type>
typedef output_range<
typename FormatContext::iterator,
typename FormatContext::char_type>
range;
visit_format_arg(arg_formatter<range>(ctx, &specs_),
internal::make_arg<FormatContext>(val));
visit_format_arg(
arg_formatter<range>(ctx, &specs_),
internal::make_arg<FormatContext>(val));
return ctx.out();
}
@ -3135,9 +3183,11 @@ template <typename ArgFormatter, typename Char, typename Context>
struct format_handler : internal::error_handler {
typedef typename ArgFormatter::range range;
format_handler(range r, basic_string_view<Char> str,
basic_format_args<Context> format_args,
internal::locale_ref loc)
format_handler(
range r,
basic_string_view<Char> str,
basic_format_args<Context> format_args,
internal::locale_ref loc)
: context(r.begin(), str, format_args, loc) {}
void on_text(const Char *begin, const Char *end) {
@ -3187,7 +3237,8 @@ struct format_handler : internal::error_handler {
/** Formats arguments and writes the output to the range. */
template <typename ArgFormatter, typename Char, typename Context>
typename Context::iterator vformat_to(
typename ArgFormatter::range out, basic_string_view<Char> format_str,
typename ArgFormatter::range out,
basic_string_view<Char> format_str,
basic_format_args<Context> args,
internal::locale_ref loc = internal::locale_ref()) {
format_handler<ArgFormatter, Char, Context> h(out, format_str, args, loc);
@ -3297,30 +3348,36 @@ std::basic_string<Char> to_string(const basic_memory_buffer<Char, SIZE> &buf) {
template <typename Char>
typename buffer_context<Char>::type::iterator internal::vformat_to(
internal::basic_buffer<Char> &buf, basic_string_view<Char> format_str,
internal::basic_buffer<Char> &buf,
basic_string_view<Char> format_str,
basic_format_args<typename buffer_context<Char>::type> args) {
typedef back_insert_range<internal::basic_buffer<Char>> range;
return vformat_to<arg_formatter<range>>(buf, to_string_view(format_str),
args);
return vformat_to<arg_formatter<range>>(
buf, to_string_view(format_str), args);
}
template <typename S, typename Char = FMT_CHAR(S)>
inline typename buffer_context<Char>::type::iterator vformat_to(
internal::basic_buffer<Char> &buf, const S &format_str,
internal::basic_buffer<Char> &buf,
const S &format_str,
basic_format_args<typename buffer_context<Char>::type> args) {
return internal::vformat_to(buf, to_string_view(format_str), args);
}
template <typename S, typename... Args, std::size_t SIZE = inline_buffer_size,
typename Char = typename internal::char_t<S>::type>
template <
typename S,
typename... Args,
std::size_t SIZE = inline_buffer_size,
typename Char = typename internal::char_t<S>::type>
inline typename buffer_context<Char>::type::iterator format_to(
basic_memory_buffer<Char, SIZE> &buf, const S &format_str,
basic_memory_buffer<Char, SIZE> &buf,
const S &format_str,
const Args &... args) {
internal::check_format_string<Args...>(format_str);
typedef typename buffer_context<Char>::type context;
format_arg_store<context, Args...> as{args...};
return internal::vformat_to(buf, to_string_view(format_str),
basic_format_args<context>(as));
return internal::vformat_to(
buf, to_string_view(format_str), basic_format_args<context>(as));
}
namespace internal {
@ -3386,13 +3443,15 @@ struct format_args_t {
};
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 String &format_str,
typename format_args_t<OutputIt, FMT_CHAR(String)>::type args) {
inline typename std::
enable_if<internal::is_output_iterator<OutputIt>::value, OutputIt>::type
vformat_to(
OutputIt out,
const String &format_str,
typename format_args_t<OutputIt, FMT_CHAR(String)>::type args) {
typedef output_range<OutputIt, FMT_CHAR(String)> range;
return vformat_to<arg_formatter<range>>(range(out),
to_string_view(format_str), args);
return vformat_to<arg_formatter<range>>(
range(out), to_string_view(format_str), args);
}
/**
@ -3407,15 +3466,16 @@ vformat_to(OutputIt out, const String &format_str,
\endrst
*/
template <typename OutputIt, typename S, typename... Args>
inline FMT_ENABLE_IF_T(internal::is_string<S>::value
&&internal::is_output_iterator<OutputIt>::value,
OutputIt)
inline FMT_ENABLE_IF_T(
internal::is_string<S>::value
&&internal::is_output_iterator<OutputIt>::value,
OutputIt)
format_to(OutputIt out, const S &format_str, const Args &... args) {
internal::check_format_string<Args...>(format_str);
typedef typename format_context_t<OutputIt, FMT_CHAR(S)>::type context;
format_arg_store<context, Args...> as{args...};
return vformat_to(out, to_string_view(format_str),
basic_format_args<context>(as));
return vformat_to(
out, to_string_view(format_str), basic_format_args<context>(as));
}
template <typename OutputIt>
@ -3437,18 +3497,24 @@ struct format_to_n_args {
};
template <typename OutputIt, typename Char, typename... Args>
inline format_arg_store<typename format_to_n_context<OutputIt, Char>::type,
Args...>
inline format_arg_store<
typename format_to_n_context<OutputIt, Char>::type,
Args...>
make_format_to_n_args(const Args &... args) {
return format_arg_store<typename format_to_n_context<OutputIt, Char>::type,
Args...>(args...);
return format_arg_store<
typename format_to_n_context<OutputIt, Char>::type,
Args...>(args...);
}
template <typename OutputIt, typename Char, typename... Args>
inline typename std::enable_if<internal::is_output_iterator<OutputIt>::value,
format_to_n_result<OutputIt>>::type
vformat_to_n(OutputIt out, std::size_t n, basic_string_view<Char> format_str,
typename format_to_n_args<OutputIt, Char>::type args) {
inline typename std::enable_if<
internal::is_output_iterator<OutputIt>::value,
format_to_n_result<OutputIt>>::type
vformat_to_n(
OutputIt out,
std::size_t n,
basic_string_view<Char> format_str,
typename format_to_n_args<OutputIt, Char>::type args) {
typedef internal::truncating_iterator<OutputIt> It;
auto it = vformat_to(It(out, n), format_str, args);
return {it.base(), it.count()};
@ -3462,17 +3528,24 @@ vformat_to_n(OutputIt out, std::size_t n, basic_string_view<Char> format_str,
\endrst
*/
template <typename OutputIt, typename S, typename... Args>
inline FMT_ENABLE_IF_T(internal::is_string<S>::value
&&internal::is_output_iterator<OutputIt>::value,
format_to_n_result<OutputIt>)
format_to_n(OutputIt out, std::size_t n, const S &format_str,
const Args &... args) {
inline FMT_ENABLE_IF_T(
internal::is_string<S>::value
&&internal::is_output_iterator<OutputIt>::value,
format_to_n_result<OutputIt>)
format_to_n(
OutputIt out,
std::size_t n,
const S &format_str,
const Args &... args) {
internal::check_format_string<Args...>(format_str);
typedef FMT_CHAR(S) Char;
format_arg_store<typename format_to_n_context<OutputIt, Char>::type, Args...>
as(args...);
return vformat_to_n(out, n, to_string_view(format_str),
typename format_to_n_args<OutputIt, Char>::type(as));
return vformat_to_n(
out,
n,
to_string_view(format_str),
typename format_to_n_args<OutputIt, Char>::type(as));
}
template <typename Char>
@ -3489,8 +3562,8 @@ inline std::basic_string<Char> internal::vformat(
``format(format_str, args...)``.
*/
template <typename... Args>
inline std::size_t formatted_size(string_view format_str,
const Args &... args) {
inline std::size_t formatted_size(
string_view format_str, const Args &... args) {
auto it = format_to(internal::counting_iterator<char>(), format_str, args...);
return it.count();
}
@ -3554,12 +3627,12 @@ FMT_CONSTEXPR internal::udl_formatter<Char, CHARS...> operator""_format() {
std::string message = "The answer is {}"_format(42);
\endrst
*/
inline internal::udl_formatter<char> operator"" _format(const char *s,
std::size_t) {
inline internal::udl_formatter<char> operator"" _format(
const char *s, std::size_t) {
return {s};
}
inline internal::udl_formatter<wchar_t> operator"" _format(const wchar_t *s,
std::size_t) {
inline internal::udl_formatter<wchar_t> operator"" _format(
const wchar_t *s, std::size_t) {
return {s};
}
#endif // FMT_UDL_TEMPLATE

View File

@ -17,17 +17,19 @@ FMT_BEGIN_NAMESPACE
namespace internal {
template <typename Char>
typename buffer_context<Char>::type::iterator vformat_to(
const std::locale &loc, basic_buffer<Char> &buf,
const std::locale &loc,
basic_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));
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,
const std::locale &loc,
basic_string_view<Char> format_str,
basic_format_args<typename buffer_context<Char>::type> args) {
basic_memory_buffer<Char> buffer;
internal::vformat_to(loc, buffer, format_str, args);
@ -37,42 +39,49 @@ std::basic_string<Char> vformat(
template <typename S, typename Char = FMT_CHAR(S)>
inline std::basic_string<Char> vformat(
const std::locale &loc, const S &format_str,
const std::locale &loc,
const S &format_str,
basic_format_args<typename buffer_context<Char>::type> 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) {
inline std::basic_string<FMT_CHAR(S)> format(
const std::locale &loc, const S &format_str, const Args &... args) {
return internal::vformat(
loc, to_string_view(format_str),
loc,
to_string_view(format_str),
*internal::checked_args<S, 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) {
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;
return vformat_to<arg_formatter<range>>(
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) {
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) {
internal::check_format_string<Args...>(format_str);
typedef typename format_context_t<OutputIt, FMT_CHAR(S)>::type context;
format_arg_store<context, Args...> as{args...};
return vformat_to(out, loc, to_string_view(format_str),
basic_format_args<context>(as));
return vformat_to(
out, loc, to_string_view(format_str), basic_format_args<context>(as));
}
FMT_END_NAMESPACE

View File

@ -1,6 +1,5 @@
#include "fmt/format.h"
int main(int argc, char** argv) {
for(int i = 0; i < argc; ++i)
fmt::print("{}: {}\n", i, argv[i]);
for (int i = 0; i < argc; ++i) fmt::print("{}: {}\n", i, argv[i]);
}

View File

@ -9,11 +9,11 @@
#include "gtest.h"
#if GTEST_HAS_DEATH_TEST
# define EXPECT_DEBUG_DEATH_IF_SUPPORTED(statement, regex) \
EXPECT_DEBUG_DEATH(statement, regex)
#define EXPECT_DEBUG_DEATH_IF_SUPPORTED(statement, regex) \
EXPECT_DEBUG_DEATH(statement, regex)
#else
# define EXPECT_DEBUG_DEATH_IF_SUPPORTED(statement, regex) \
GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
#define EXPECT_DEBUG_DEATH_IF_SUPPORTED(statement, regex) \
GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
#endif
TEST(AssertTest, Fail) {

View File

@ -34,8 +34,8 @@ std::tm make_second(int s) {
return time;
}
std::string format_tm(const std::tm &time, const char *spec,
const std::locale &loc) {
std::string format_tm(
const std::tm &time, const char *spec, const std::locale &loc) {
auto &facet = std::use_facet<std::time_put<char>>(loc);
std::ostringstream os;
os.imbue(loc);
@ -43,52 +43,54 @@ std::string format_tm(const std::tm &time, const char *spec,
return os.str();
}
#define EXPECT_TIME(spec, time, duration) { \
std::locale loc("ja_JP.utf8"); \
EXPECT_EQ(format_tm(time, spec, loc), \
fmt::format(loc, "{:" spec "}", duration)); \
#define EXPECT_TIME(spec, time, duration) \
{ \
std::locale loc("ja_JP.utf8"); \
EXPECT_EQ( \
format_tm(time, spec, loc), \
fmt::format(loc, "{:" spec "}", duration)); \
}
TEST(ChronoTest, FormatDefault) {
EXPECT_EQ("42s", fmt::format("{}", std::chrono::seconds(42)));
EXPECT_EQ("42as",
fmt::format("{}", std::chrono::duration<int, std::atto>(42)));
EXPECT_EQ("42fs",
fmt::format("{}", std::chrono::duration<int, std::femto>(42)));
EXPECT_EQ("42ps",
fmt::format("{}", std::chrono::duration<int, std::pico>(42)));
EXPECT_EQ(
"42as", fmt::format("{}", std::chrono::duration<int, std::atto>(42)));
EXPECT_EQ(
"42fs", fmt::format("{}", std::chrono::duration<int, std::femto>(42)));
EXPECT_EQ(
"42ps", fmt::format("{}", std::chrono::duration<int, std::pico>(42)));
EXPECT_EQ("42ns", fmt::format("{}", std::chrono::nanoseconds(42)));
EXPECT_EQ("42µs", fmt::format("{}", std::chrono::microseconds(42)));
EXPECT_EQ("42ms", fmt::format("{}", std::chrono::milliseconds(42)));
EXPECT_EQ("42cs",
fmt::format("{}", std::chrono::duration<int, std::centi>(42)));
EXPECT_EQ("42ds",
fmt::format("{}", std::chrono::duration<int, std::deci>(42)));
EXPECT_EQ(
"42cs", fmt::format("{}", std::chrono::duration<int, std::centi>(42)));
EXPECT_EQ(
"42ds", fmt::format("{}", std::chrono::duration<int, std::deci>(42)));
EXPECT_EQ("42s", fmt::format("{}", std::chrono::seconds(42)));
EXPECT_EQ("42das",
fmt::format("{}", std::chrono::duration<int, std::deca>(42)));
EXPECT_EQ("42hs",
fmt::format("{}", std::chrono::duration<int, std::hecto>(42)));
EXPECT_EQ("42ks",
fmt::format("{}", std::chrono::duration<int, std::kilo>(42)));
EXPECT_EQ("42Ms",
fmt::format("{}", std::chrono::duration<int, std::mega>(42)));
EXPECT_EQ("42Gs",
fmt::format("{}", std::chrono::duration<int, std::giga>(42)));
EXPECT_EQ("42Ts",
fmt::format("{}", std::chrono::duration<int, std::tera>(42)));
EXPECT_EQ("42Ps",
fmt::format("{}", std::chrono::duration<int, std::peta>(42)));
EXPECT_EQ("42Es",
fmt::format("{}", std::chrono::duration<int, std::exa>(42)));
EXPECT_EQ(
"42das", fmt::format("{}", std::chrono::duration<int, std::deca>(42)));
EXPECT_EQ(
"42hs", fmt::format("{}", std::chrono::duration<int, std::hecto>(42)));
EXPECT_EQ(
"42ks", fmt::format("{}", std::chrono::duration<int, std::kilo>(42)));
EXPECT_EQ(
"42Ms", fmt::format("{}", std::chrono::duration<int, std::mega>(42)));
EXPECT_EQ(
"42Gs", fmt::format("{}", std::chrono::duration<int, std::giga>(42)));
EXPECT_EQ(
"42Ts", fmt::format("{}", std::chrono::duration<int, std::tera>(42)));
EXPECT_EQ(
"42Ps", fmt::format("{}", std::chrono::duration<int, std::peta>(42)));
EXPECT_EQ(
"42Es", fmt::format("{}", std::chrono::duration<int, std::exa>(42)));
EXPECT_EQ("42m", fmt::format("{}", std::chrono::minutes(42)));
EXPECT_EQ("42h", fmt::format("{}", std::chrono::hours(42)));
EXPECT_EQ("42[15]s",
fmt::format("{}",
std::chrono::duration<int, std::ratio<15, 1>>(42)));
EXPECT_EQ("42[15/4]s",
fmt::format("{}",
std::chrono::duration<int, std::ratio<15, 4>>(42)));
EXPECT_EQ(
"42[15]s",
fmt::format("{}", std::chrono::duration<int, std::ratio<15, 1>>(42)));
EXPECT_EQ(
"42[15/4]s",
fmt::format("{}", std::chrono::duration<int, std::ratio<15, 4>>(42)));
}
TEST(ChronoTest, Align) {
@ -120,8 +122,8 @@ TEST(ChronoTest, FormatSpecs) {
EXPECT_EQ("12", fmt::format("{:%I}", std::chrono::hours(24)));
EXPECT_EQ("04", fmt::format("{:%I}", std::chrono::hours(4)));
EXPECT_EQ("02", fmt::format("{:%I}", std::chrono::hours(14)));
EXPECT_EQ("03:25:45",
fmt::format("{:%H:%M:%S}", std::chrono::seconds(12345)));
EXPECT_EQ(
"03:25:45", fmt::format("{:%H:%M:%S}", std::chrono::seconds(12345)));
EXPECT_EQ("03:25", fmt::format("{:%R}", std::chrono::seconds(12345)));
EXPECT_EQ("03:25:45", fmt::format("{:%T}", std::chrono::seconds(12345)));
}
@ -144,12 +146,12 @@ TEST(ChronoTest, InvalidSpecs) {
EXPECT_THROW_MSG(fmt::format("{:%B}", sec), fmt::format_error, "no date");
EXPECT_THROW_MSG(fmt::format("{:%z}", sec), fmt::format_error, "no date");
EXPECT_THROW_MSG(fmt::format("{:%Z}", sec), fmt::format_error, "no date");
EXPECT_THROW_MSG(fmt::format("{:%q}", sec), fmt::format_error,
"invalid format");
EXPECT_THROW_MSG(fmt::format("{:%Eq}", sec), fmt::format_error,
"invalid format");
EXPECT_THROW_MSG(fmt::format("{:%Oq}", sec), fmt::format_error,
"invalid format");
EXPECT_THROW_MSG(
fmt::format("{:%q}", sec), fmt::format_error, "invalid format");
EXPECT_THROW_MSG(
fmt::format("{:%Eq}", sec), fmt::format_error, "invalid format");
EXPECT_THROW_MSG(
fmt::format("{:%Oq}", sec), fmt::format_error, "invalid format");
}
TEST(ChronoTest, Locale) {
@ -159,7 +161,8 @@ TEST(ChronoTest, Locale) {
try {
loc = std::locale(loc_name);
has_locale = true;
} catch (const std::runtime_error &) {}
} catch (const std::runtime_error &) {
}
if (!has_locale) {
fmt::print("{} locale is missing.\n", loc_name);
return;

View File

@ -11,9 +11,9 @@
#include <functional>
#include <iterator>
#include <limits>
#include <memory>
#include <string>
#include <type_traits>
#include <memory>
#include "test-assert.h"
@ -21,7 +21,7 @@
// Check if fmt/core.h compiles with windows.h included before it.
#ifdef _WIN32
# include <windows.h>
#include <windows.h>
#endif
#include "fmt/core.h"
@ -30,9 +30,9 @@
#undef max
using fmt::basic_format_arg;
using fmt::string_view;
using fmt::internal::basic_buffer;
using fmt::internal::value;
using fmt::string_view;
using testing::_;
using testing::StrictMock;
@ -67,18 +67,18 @@ FMT_END_NAMESPACE
#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 470
TEST(BufferTest, Noncopyable) {
EXPECT_FALSE(std::is_copy_constructible<basic_buffer<char> >::value);
EXPECT_FALSE(std::is_copy_constructible<basic_buffer<char>>::value);
#if !FMT_MSC_VER
// std::is_copy_assignable is broken in MSVC2013.
EXPECT_FALSE(std::is_copy_assignable<basic_buffer<char> >::value);
EXPECT_FALSE(std::is_copy_assignable<basic_buffer<char>>::value);
#endif
}
TEST(BufferTest, Nonmoveable) {
EXPECT_FALSE(std::is_move_constructible<basic_buffer<char> >::value);
EXPECT_FALSE(std::is_move_constructible<basic_buffer<char>>::value);
#if !FMT_MSC_VER
// std::is_move_assignable is broken in MSVC2013.
EXPECT_FALSE(std::is_move_assignable<basic_buffer<char> >::value);
EXPECT_FALSE(std::is_move_assignable<basic_buffer<char>>::value);
#endif
}
#endif
@ -91,7 +91,7 @@ struct test_buffer : basic_buffer<T> {
template <typename T>
struct mock_buffer : basic_buffer<T> {
MOCK_METHOD1(do_grow, void (std::size_t capacity));
MOCK_METHOD1(do_grow, void(std::size_t capacity));
void grow(std::size_t capacity) {
this->set(this->data(), capacity);
@ -219,7 +219,7 @@ struct custom_context {
return ctx.begin();
}
const char *format(const T &, custom_context& ctx) {
const char *format(const T &, custom_context &ctx) {
ctx.called = true;
return FMT_NULL;
}
@ -249,7 +249,7 @@ template <typename Char>
bool operator==(custom_value<Char> lhs, custom_value<Char> rhs) {
return lhs.value == rhs.value;
}
}
} // namespace internal
FMT_END_NAMESPACE
// Use a unique result type to make sure that there are no undesirable
@ -259,14 +259,16 @@ struct test_result {};
template <typename T>
struct mock_visitor {
template <typename U>
struct result { typedef test_result type; };
struct result {
typedef test_result type;
};
mock_visitor() {
ON_CALL(*this, visit(_)).WillByDefault(testing::Return(test_result()));
}
MOCK_METHOD1_T(visit, test_result (T value));
MOCK_METHOD0_T(unexpected, void ());
MOCK_METHOD1_T(visit, test_result(T value));
MOCK_METHOD0_T(unexpected, void());
test_result operator()(T value) { return visit(value); }
@ -278,11 +280,15 @@ struct mock_visitor {
};
template <typename T>
struct visit_type { typedef T Type; };
struct visit_type {
typedef T Type;
};
#define VISIT_TYPE(Type_, visit_type_) \
template <> \
struct visit_type<Type_> { typedef visit_type_ Type; }
template <> \
struct visit_type<Type_> { \
typedef visit_type_ Type; \
}
VISIT_TYPE(signed char, int);
VISIT_TYPE(unsigned char, unsigned);
@ -299,28 +305,42 @@ VISIT_TYPE(unsigned long, unsigned long long);
VISIT_TYPE(float, double);
#define CHECK_ARG_(Char, expected, value) { \
testing::StrictMock<mock_visitor<decltype(expected)>> visitor; \
EXPECT_CALL(visitor, visit(expected)); \
typedef std::back_insert_iterator<basic_buffer<Char>> iterator; \
fmt::visit(visitor, \
make_arg<fmt::basic_format_context<iterator, Char>>(value)); \
}
#define CHECK_ARG_(Char, expected, value) \
{ \
testing::StrictMock<mock_visitor<decltype(expected)>> visitor; \
EXPECT_CALL(visitor, visit(expected)); \
typedef std::back_insert_iterator<basic_buffer<Char>> iterator; \
fmt::visit( \
visitor, make_arg<fmt::basic_format_context<iterator, Char>>(value)); \
}
#define CHECK_ARG(value, typename_) { \
typedef decltype(value) value_type; \
typename_ visit_type<value_type>::Type expected = value; \
CHECK_ARG_(char, expected, value) \
CHECK_ARG_(wchar_t, expected, value) \
}
#define CHECK_ARG(value, typename_) \
{ \
typedef decltype(value) value_type; \
typename_ visit_type<value_type>::Type expected = value; \
CHECK_ARG_(char, expected, value) \
CHECK_ARG_(wchar_t, expected, value) \
}
template <typename T>
class NumericArgTest : public testing::Test {};
typedef ::testing::Types<
bool, signed char, unsigned char, signed, unsigned short,
int, unsigned, long, unsigned long, long long, unsigned long long,
float, double, long double> Types;
bool,
signed char,
unsigned char,
signed,
unsigned short,
int,
unsigned,
long,
unsigned long,
long long,
unsigned long long,
float,
double,
long double>
Types;
TYPED_TEST_CASE(NumericArgTest, Types);
template <typename T>
@ -330,7 +350,7 @@ typename std::enable_if<std::is_integral<T>::value, T>::type test_value() {
template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type
test_value() {
test_value() {
return static_cast<T>(4.2);
}
@ -395,14 +415,14 @@ struct check_custom {
TEST(ArgTest, CustomArg) {
test_struct test;
typedef mock_visitor<fmt::basic_format_arg<fmt::format_context>::handle>
visitor;
visitor;
testing::StrictMock<visitor> v;
EXPECT_CALL(v, visit(_)).WillOnce(testing::Invoke(check_custom()));
fmt::visit(v, make_arg<fmt::format_context>(test));
}
TEST(ArgTest, VisitInvalidArg) {
testing::StrictMock< mock_visitor<fmt::monostate> > visitor;
testing::StrictMock<mock_visitor<fmt::monostate>> visitor;
EXPECT_CALL(visitor, visit(_));
fmt::basic_format_arg<fmt::format_context> arg;
visit(visitor, arg);
@ -461,21 +481,22 @@ template <typename Char>
class my_string {
public:
my_string(const Char *s) : s_(s) {}
const Char * data() const FMT_NOEXCEPT { return s_.data(); }
const Char *data() const FMT_NOEXCEPT { return s_.data(); }
std::size_t length() const FMT_NOEXCEPT { return s_.size(); }
operator const Char*() const { return s_.c_str(); }
operator const Char *() const { return s_.c_str(); }
private:
std::basic_string<Char> s_;
};
template <typename Char>
inline fmt::basic_string_view<Char>
to_string_view(const my_string<Char> &s) FMT_NOEXCEPT {
return { s.data(), s.length() };
inline fmt::basic_string_view<Char> to_string_view(const my_string<Char> &s)
FMT_NOEXCEPT {
return {s.data(), s.length()};
}
struct non_string {};
}
} // namespace my_ns
namespace FakeQt {
class QString {
@ -490,12 +511,12 @@ class QString {
std::shared_ptr<std::wstring> s_;
};
inline fmt::basic_string_view<wchar_t> to_string_view(
const QString &s) FMT_NOEXCEPT {
inline fmt::basic_string_view<wchar_t> to_string_view(const QString &s)
FMT_NOEXCEPT {
return {reinterpret_cast<const wchar_t *>(s.utf16()),
static_cast<std::size_t>(s.size())};
}
}
} // namespace FakeQt
template <typename T>
class IsStringTest : public testing::Test {};
@ -506,7 +527,7 @@ TYPED_TEST_CASE(IsStringTest, StringCharTypes);
namespace {
template <typename Char>
struct derived_from_string_view : fmt::basic_string_view<Char> {};
}
} // namespace
TYPED_TEST(IsStringTest, IsString) {
EXPECT_TRUE((fmt::internal::is_string<TypeParam *>::value));
@ -515,9 +536,9 @@ TYPED_TEST(IsStringTest, IsString) {
EXPECT_TRUE((fmt::internal::is_string<const TypeParam[2]>::value));
EXPECT_TRUE((fmt::internal::is_string<std::basic_string<TypeParam>>::value));
EXPECT_TRUE(
(fmt::internal::is_string<fmt::basic_string_view<TypeParam>>::value));
(fmt::internal::is_string<fmt::basic_string_view<TypeParam>>::value));
EXPECT_TRUE(
(fmt::internal::is_string<derived_from_string_view<TypeParam>>::value));
(fmt::internal::is_string<derived_from_string_view<TypeParam>>::value));
#ifdef FMT_STRING_VIEW
EXPECT_TRUE((fmt::internal::is_string<FMT_STRING_VIEW<TypeParam>>::value));
#endif
@ -529,7 +550,7 @@ TYPED_TEST(IsStringTest, IsString) {
TEST(CoreTest, Format) {
// This should work without including fmt/format.h.
#ifdef FMT_FORMAT_H_
# error fmt/format.h must not be included in the core test
#error fmt/format.h must not be included in the core test
#endif
EXPECT_EQ(fmt::format("{}", 42), "42");
}
@ -537,7 +558,7 @@ TEST(CoreTest, Format) {
TEST(CoreTest, FormatTo) {
// This should work without including fmt/format.h.
#ifdef FMT_FORMAT_H_
# error fmt/format.h must not be included in the core test
#error fmt/format.h must not be included in the core test
#endif
std::string s;
fmt::format_to(std::back_inserter(s), "{}", 42);
@ -595,16 +616,19 @@ struct explicitly_convertible_to_wstring_view {
};
TEST(FormatterTest, FormatExplicitlyConvertibleToWStringView) {
EXPECT_EQ(L"foo",
fmt::format(L"{}", explicitly_convertible_to_wstring_view()));
EXPECT_EQ(
L"foo", fmt::format(L"{}", explicitly_convertible_to_wstring_view()));
}
struct explicitly_convertible_to_string_like {
template <
typename String,
typename = typename std::enable_if<
std::is_constructible<String, const char*, std::size_t>::value>::type>
FMT_EXPLICIT operator String() const { return String("foo", 3u); }
std::is_constructible<String, const char *, std::size_t>::value>::
type>
FMT_EXPLICIT operator String() const {
return String("foo", 3u);
}
};
TEST(FormatterTest, FormatExplicitlyConvertibleToStringLike) {

View File

@ -13,15 +13,15 @@
// A custom argument formatter that doesn't print `-` for floating-point values
// rounded to 0.
class custom_arg_formatter :
public fmt::arg_formatter<fmt::back_insert_range<fmt::internal::buffer>> {
class custom_arg_formatter
: public fmt::arg_formatter<fmt::back_insert_range<fmt::internal::buffer>> {
public:
typedef fmt::back_insert_range<fmt::internal::buffer> range;
typedef fmt::arg_formatter<range> base;
custom_arg_formatter(
fmt::format_context &ctx, fmt::format_specs *s = FMT_NULL)
: base(ctx, s) {}
: base(ctx, s) {}
using base::operator();
@ -41,7 +41,7 @@ std::string custom_vformat(fmt::string_view format_str, fmt::format_args args) {
}
template <typename... Args>
std::string custom_format(const char *format_str, const Args & ... args) {
std::string custom_format(const char *format_str, const Args &... args) {
auto va = fmt::make_format_args(args...);
return custom_vformat(format_str, va);
}

View File

@ -1,6 +1,5 @@
#include "fmt/format.h"
int main(int argc, char** argv) {
for(int i = 0; i < argc; ++i)
fmt::print("{}: {}\n", i, argv[i]);
for (int i = 0; i < argc; ++i) fmt::print("{}: {}\n", i, argv[i]);
}

View File

@ -25,9 +25,9 @@
#undef max
#if FMT_HAS_CPP_ATTRIBUTE(noreturn)
# define FMT_NORETURN [[noreturn]]
#define FMT_NORETURN [[noreturn]]
#else
# define FMT_NORETURN
#define FMT_NORETURN
#endif
using fmt::internal::fp;
@ -108,10 +108,8 @@ TEST(FPTest, Grisu2FormatCompilesWithNonIEEEDouble) {
}
template <typename T>
struct ValueExtractor: fmt::internal::function<T> {
T operator()(T value) {
return value;
}
struct ValueExtractor : fmt::internal::function<T> {
T operator()(T value) { return value; }
template <typename U>
FMT_NORETURN T operator()(U) {
@ -122,8 +120,9 @@ struct ValueExtractor: fmt::internal::function<T> {
TEST(FormatTest, ArgConverter) {
long long value = std::numeric_limits<long long>::max();
auto arg = fmt::internal::make_arg<fmt::format_context>(value);
visit(fmt::internal::arg_converter<long long, fmt::format_context>(arg, 'd'),
arg);
visit(
fmt::internal::arg_converter<long long, fmt::format_context>(arg, 'd'),
arg);
EXPECT_EQ(value, visit(ValueExtractor<long long>(), arg));
}
@ -138,10 +137,10 @@ TEST(FormatTest, FormatNegativeNaN) {
TEST(FormatTest, StrError) {
char *message = FMT_NULL;
char buffer[BUFFER_SIZE];
EXPECT_ASSERT(fmt::safe_strerror(EDOM, message = FMT_NULL, 0),
"invalid buffer");
EXPECT_ASSERT(fmt::safe_strerror(EDOM, message = buffer, 0),
"invalid buffer");
EXPECT_ASSERT(
fmt::safe_strerror(EDOM, message = FMT_NULL, 0), "invalid buffer");
EXPECT_ASSERT(
fmt::safe_strerror(EDOM, message = buffer, 0), "invalid buffer");
buffer[0] = 'x';
#if defined(_GNU_SOURCE) && !defined(__COVERITY__)
// Use invalid error code to make sure that safe_strerror returns an error
@ -188,8 +187,7 @@ TEST(FormatTest, FormatErrorCode) {
// Test maximum buffer size.
msg = fmt::format("error {}", codes[i]);
fmt::memory_buffer buffer;
std::string prefix(
fmt::inline_buffer_size - msg.size() - sep.size(), 'x');
std::string prefix(fmt::inline_buffer_size - msg.size() - sep.size(), 'x');
fmt::format_error_code(buffer, codes[i], prefix);
EXPECT_EQ(prefix + sep + msg, to_string(buffer));
std::size_t size = fmt::inline_buffer_size;
@ -207,40 +205,59 @@ TEST(FormatTest, CountCodePoints) {
}
TEST(ColorsTest, Colors) {
EXPECT_WRITE(stdout, fmt::print(fg(fmt::rgb(255, 20, 30)), "rgb(255,20,30)"),
"\x1b[38;2;255;020;030mrgb(255,20,30)\x1b[0m");
EXPECT_WRITE(stdout, fmt::print(fg(fmt::color::blue), "blue"),
"\x1b[38;2;000;000;255mblue\x1b[0m");
EXPECT_WRITE(
stdout,
fmt::print(fg(fmt::rgb(255, 20, 30)), "rgb(255,20,30)"),
"\x1b[38;2;255;020;030mrgb(255,20,30)\x1b[0m");
EXPECT_WRITE(
stdout,
fmt::print(fg(fmt::color::blue), "blue"),
"\x1b[38;2;000;000;255mblue\x1b[0m");
EXPECT_WRITE(
stdout,
fmt::print(fg(fmt::color::blue) | bg(fmt::color::red), "two color"),
"\x1b[38;2;000;000;255m\x1b[48;2;255;000;000mtwo color\x1b[0m");
EXPECT_WRITE(stdout, fmt::print(fmt::emphasis::bold, "bold"),
"\x1b[1mbold\x1b[0m");
EXPECT_WRITE(stdout, fmt::print(fmt::emphasis::italic, "italic"),
"\x1b[3mitalic\x1b[0m");
EXPECT_WRITE(stdout, fmt::print(fmt::emphasis::underline, "underline"),
"\x1b[4munderline\x1b[0m");
EXPECT_WRITE(stdout,
fmt::print(fmt::emphasis::strikethrough, "strikethrough"),
"\x1b[9mstrikethrough\x1b[0m");
EXPECT_WRITE(
stdout, fmt::print(fmt::emphasis::bold, "bold"), "\x1b[1mbold\x1b[0m");
EXPECT_WRITE(
stdout,
fmt::print(fmt::emphasis::italic, "italic"),
"\x1b[3mitalic\x1b[0m");
EXPECT_WRITE(
stdout,
fmt::print(fmt::emphasis::underline, "underline"),
"\x1b[4munderline\x1b[0m");
EXPECT_WRITE(
stdout,
fmt::print(fmt::emphasis::strikethrough, "strikethrough"),
"\x1b[9mstrikethrough\x1b[0m");
EXPECT_WRITE(
stdout,
fmt::print(fg(fmt::color::blue) | fmt::emphasis::bold, "blue/bold"),
"\x1b[1m\x1b[38;2;000;000;255mblue/bold\x1b[0m");
EXPECT_WRITE(stderr, fmt::print(stderr, fmt::emphasis::bold, "bold error"),
"\x1b[1mbold error\x1b[0m");
EXPECT_WRITE(stderr, fmt::print(stderr, fg(fmt::color::blue), "blue log"),
"\x1b[38;2;000;000;255mblue log\x1b[0m");
EXPECT_WRITE(
stderr,
fmt::print(stderr, fmt::emphasis::bold, "bold error"),
"\x1b[1mbold error\x1b[0m");
EXPECT_WRITE(
stderr,
fmt::print(stderr, fg(fmt::color::blue), "blue log"),
"\x1b[38;2;000;000;255mblue log\x1b[0m");
EXPECT_WRITE(stdout, fmt::print(fmt::text_style(), "hi"), "hi");
EXPECT_WRITE(stdout, fmt::print(fg(fmt::terminal_color::red), "tred"),
"\x1b[31mtred\x1b[0m");
EXPECT_WRITE(stdout, fmt::print(bg(fmt::terminal_color::cyan), "tcyan"),
"\x1b[46mtcyan\x1b[0m");
EXPECT_WRITE(stdout,
fmt::print(fg(fmt::terminal_color::bright_green), "tbgreen"),
"\x1b[92mtbgreen\x1b[0m");
EXPECT_WRITE(stdout,
fmt::print(bg(fmt::terminal_color::bright_magenta), "tbmagenta"),
"\x1b[105mtbmagenta\x1b[0m");
EXPECT_WRITE(
stdout,
fmt::print(fg(fmt::terminal_color::red), "tred"),
"\x1b[31mtred\x1b[0m");
EXPECT_WRITE(
stdout,
fmt::print(bg(fmt::terminal_color::cyan), "tcyan"),
"\x1b[46mtcyan\x1b[0m");
EXPECT_WRITE(
stdout,
fmt::print(fg(fmt::terminal_color::bright_green), "tbgreen"),
"\x1b[92mtbgreen\x1b[0m");
EXPECT_WRITE(
stdout,
fmt::print(bg(fmt::terminal_color::bright_magenta), "tbmagenta"),
"\x1b[105mtbmagenta\x1b[0m");
}

File diff suppressed because it is too large Load Diff

View File

@ -7,14 +7,14 @@
#include "gtest-extra.h"
#include <cstring>
#include <algorithm>
#include <stdexcept>
#include <gtest/gtest-spi.h>
#include <algorithm>
#include <cstring>
#include <stdexcept>
#if defined(_WIN32) && !defined(__MINGW32__)
# include <crtdbg.h> // for _CrtSetReportMode
#endif // _WIN32
#include <crtdbg.h> // for _CrtSetReportMode
#endif // _WIN32
#include "util.h"
@ -23,7 +23,7 @@ using testing::internal::scoped_ptr;
namespace {
// This is used to suppress coverity warnings about untrusted values.
std::string sanitize(const std::string &s) {
std::string sanitize(const std::string& s) {
std::string result;
for (std::string::const_iterator i = s.begin(), end = s.end(); i != end; ++i)
result.push_back(static_cast<char>(*i & 0xff));
@ -53,13 +53,9 @@ int SingleEvaluationTest::b_;
void do_nothing() {}
void throw_exception() {
throw std::runtime_error("test");
}
void throw_exception() { throw std::runtime_error("test"); }
void throw_system_error() {
throw fmt::system_error(EDOM, "test");
}
void throw_system_error() { throw fmt::system_error(EDOM, "test"); }
// Tests that when EXPECT_THROW_MSG fails, it evaluates its message argument
// exactly once.
@ -88,26 +84,38 @@ TEST_F(SingleEvaluationTest, FailedEXPECT_WRITE) {
// Tests that assertion arguments are evaluated exactly once.
TEST_F(SingleEvaluationTest, ExceptionTests) {
// successful EXPECT_THROW_MSG
EXPECT_THROW_MSG({ // NOLINT
a_++;
throw_exception();
}, std::exception, (b_++, "test"));
EXPECT_THROW_MSG(
{ // NOLINT
a_++;
throw_exception();
},
std::exception,
(b_++, "test"));
EXPECT_EQ(1, a_);
EXPECT_EQ(1, b_);
// failed EXPECT_THROW_MSG, throws different type
EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG({ // NOLINT
a_++;
throw_exception();
}, std::logic_error, (b_++, "test")), "throws a different type");
EXPECT_NONFATAL_FAILURE(
EXPECT_THROW_MSG(
{ // NOLINT
a_++;
throw_exception();
},
std::logic_error,
(b_++, "test")),
"throws a different type");
EXPECT_EQ(2, a_);
EXPECT_EQ(2, b_);
// failed EXPECT_THROW_MSG, throws an exception with different message
EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG({ // NOLINT
a_++;
throw_exception();
}, std::exception, (b_++, "other")),
EXPECT_NONFATAL_FAILURE(
EXPECT_THROW_MSG(
{ // NOLINT
a_++;
throw_exception();
},
std::exception,
(b_++, "other")),
"throws an exception with a different message");
EXPECT_EQ(3, a_);
EXPECT_EQ(3, b_);
@ -121,26 +129,38 @@ TEST_F(SingleEvaluationTest, ExceptionTests) {
TEST_F(SingleEvaluationTest, SystemErrorTests) {
// successful EXPECT_SYSTEM_ERROR
EXPECT_SYSTEM_ERROR({ // NOLINT
a_++;
throw_system_error();
}, EDOM, (b_++, "test"));
EXPECT_SYSTEM_ERROR(
{ // NOLINT
a_++;
throw_system_error();
},
EDOM,
(b_++, "test"));
EXPECT_EQ(1, a_);
EXPECT_EQ(1, b_);
// failed EXPECT_SYSTEM_ERROR, throws different type
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR({ // NOLINT
a_++;
throw_exception();
}, EDOM, (b_++, "test")), "throws a different type");
EXPECT_NONFATAL_FAILURE(
EXPECT_SYSTEM_ERROR(
{ // NOLINT
a_++;
throw_exception();
},
EDOM,
(b_++, "test")),
"throws a different type");
EXPECT_EQ(2, a_);
EXPECT_EQ(2, b_);
// failed EXPECT_SYSTEM_ERROR, throws an exception with different message
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR({ // NOLINT
a_++;
throw_system_error();
}, EDOM, (b_++, "other")),
EXPECT_NONFATAL_FAILURE(
EXPECT_SYSTEM_ERROR(
{ // NOLINT
a_++;
throw_system_error();
},
EDOM,
(b_++, "other")),
"throws an exception with a different message");
EXPECT_EQ(3, a_);
EXPECT_EQ(3, b_);
@ -155,18 +175,26 @@ TEST_F(SingleEvaluationTest, SystemErrorTests) {
// Tests that assertion arguments are evaluated exactly once.
TEST_F(SingleEvaluationTest, WriteTests) {
// successful EXPECT_WRITE
EXPECT_WRITE(stdout, { // NOLINT
a_++;
std::printf("test");
}, (b_++, "test"));
EXPECT_WRITE(
stdout,
{ // NOLINT
a_++;
std::printf("test");
},
(b_++, "test"));
EXPECT_EQ(1, a_);
EXPECT_EQ(1, b_);
// failed EXPECT_WRITE
EXPECT_NONFATAL_FAILURE(EXPECT_WRITE(stdout, { // NOLINT
a_++;
std::printf("test");
}, (b_++, "other")), "Actual: test");
EXPECT_NONFATAL_FAILURE(
EXPECT_WRITE(
stdout,
{ // NOLINT
a_++;
std::printf("test");
},
(b_++, "other")),
"Actual: test");
EXPECT_EQ(2, a_);
EXPECT_EQ(2, b_);
}
@ -179,8 +207,8 @@ TEST(ExpectThrowTest, DoesNotGenerateUnreachableCodeWarning) {
EXPECT_THROW_MSG(throw runtime_error(""), runtime_error, "");
EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG(n++, runtime_error, ""), "");
EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG(throw 1, runtime_error, ""), "");
EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG(
throw runtime_error("a"), runtime_error, "b"), "");
EXPECT_NONFATAL_FAILURE(
EXPECT_THROW_MSG(throw runtime_error("a"), runtime_error, "b"), "");
}
// Tests that the compiler will not complain about unreachable code in the
@ -190,8 +218,9 @@ TEST(ExpectSystemErrorTest, DoesNotGenerateUnreachableCodeWarning) {
EXPECT_SYSTEM_ERROR(throw fmt::system_error(EDOM, "test"), EDOM, "test");
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(n++, EDOM, ""), "");
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(throw 1, EDOM, ""), "");
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(
throw fmt::system_error(EDOM, "aaa"), EDOM, "bbb"), "");
EXPECT_NONFATAL_FAILURE(
EXPECT_SYSTEM_ERROR(throw fmt::system_error(EDOM, "aaa"), EDOM, "bbb"),
"");
}
TEST(AssertionSyntaxTest, ExceptionAssertionBehavesLikeSingleStatement) {
@ -279,7 +308,8 @@ TEST(StreamingAssertionsTest, EXPECT_THROW_MSG) {
<< "unexpected failure";
EXPECT_NONFATAL_FAILURE(
EXPECT_THROW_MSG(throw_exception(), std::exception, "other")
<< "expected failure", "expected failure");
<< "expected failure",
"expected failure");
}
TEST(StreamingAssertionsTest, EXPECT_SYSTEM_ERROR) {
@ -287,15 +317,15 @@ TEST(StreamingAssertionsTest, EXPECT_SYSTEM_ERROR) {
<< "unexpected failure";
EXPECT_NONFATAL_FAILURE(
EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "other")
<< "expected failure", "expected failure");
<< "expected failure",
"expected failure");
}
TEST(StreamingAssertionsTest, EXPECT_WRITE) {
EXPECT_WRITE(stdout, std::printf("test"), "test")
<< "unexpected failure";
EXPECT_WRITE(stdout, std::printf("test"), "test") << "unexpected failure";
EXPECT_NONFATAL_FAILURE(
EXPECT_WRITE(stdout, std::printf("test"), "other")
<< "expected failure", "expected failure");
EXPECT_WRITE(stdout, std::printf("test"), "other") << "expected failure",
"expected failure");
}
TEST(UtilTest, FormatSystemError) {
@ -341,8 +371,8 @@ TEST(OutputRedirectTest, FlushErrorInCtor) {
EXPECT_EQ('x', fputc('x', f.get()));
FMT_POSIX(close(write_fd));
scoped_ptr<OutputRedirect> redir{FMT_NULL};
EXPECT_SYSTEM_ERROR_NOASSERT(redir.reset(new OutputRedirect(f.get())),
EBADF, "cannot flush stream");
EXPECT_SYSTEM_ERROR_NOASSERT(
redir.reset(new OutputRedirect(f.get())), EBADF, "cannot flush stream");
redir.reset(FMT_NULL);
write_copy.dup2(write_fd); // "undo" close or dtor will fail
}
@ -353,8 +383,10 @@ TEST(OutputRedirectTest, DupErrorInCtor) {
file copy = file::dup(fd);
FMT_POSIX(close(fd));
scoped_ptr<OutputRedirect> redir{FMT_NULL};
EXPECT_SYSTEM_ERROR_NOASSERT(redir.reset(new OutputRedirect(f.get())),
EBADF, fmt::format("cannot duplicate file descriptor {}", fd));
EXPECT_SYSTEM_ERROR_NOASSERT(
redir.reset(new OutputRedirect(f.get())),
EBADF,
fmt::format("cannot duplicate file descriptor {}", fd));
copy.dup2(fd); // "undo" close or dtor will fail
}
@ -383,8 +415,8 @@ TEST(OutputRedirectTest, FlushErrorInRestoreAndRead) {
// Put a character in a file buffer.
EXPECT_EQ('x', fputc('x', f.get()));
FMT_POSIX(close(write_fd));
EXPECT_SYSTEM_ERROR_NOASSERT(redir.restore_and_read(),
EBADF, "cannot flush stream");
EXPECT_SYSTEM_ERROR_NOASSERT(
redir.restore_and_read(), EBADF, "cannot flush stream");
write_copy.dup2(write_fd); // "undo" close or dtor will fail
}
@ -397,15 +429,18 @@ TEST(OutputRedirectTest, ErrorInDtor) {
scoped_ptr<OutputRedirect> redir(new OutputRedirect(f.get()));
// Put a character in a file buffer.
EXPECT_EQ('x', fputc('x', f.get()));
EXPECT_WRITE(stderr, {
// The close function must be called inside EXPECT_WRITE, otherwise
// the system may recycle closed file descriptor when redirecting the
// output in EXPECT_STDERR and the second close will break output
// redirection.
FMT_POSIX(close(write_fd));
SUPPRESS_ASSERT(redir.reset(FMT_NULL));
}, format_system_error(EBADF, "cannot flush stream"));
write_copy.dup2(write_fd); // "undo" close or dtor of buffered_file will fail
EXPECT_WRITE(
stderr,
{
// The close function must be called inside EXPECT_WRITE, otherwise
// the system may recycle closed file descriptor when redirecting the
// output in EXPECT_STDERR and the second close will break output
// redirection.
FMT_POSIX(close(write_fd));
SUPPRESS_ASSERT(redir.reset(FMT_NULL));
},
format_system_error(EBADF, "cannot flush stream"));
write_copy.dup2(write_fd); // "undo" close or dtor of buffered_file will fail
}
#endif // FMT_USE_FILE_DESCRIPTORS

View File

@ -13,7 +13,7 @@ using fmt::file;
void OutputRedirect::flush() {
#if EOF != -1
# error "FMT_RETRY assumes return value of -1 indicating failure"
#error "FMT_RETRY assumes return value of -1 indicating failure"
#endif
int result = 0;
FMT_RETRY(result, fflush(file_));

View File

@ -14,58 +14,59 @@
#include "fmt/core.h"
#ifndef FMT_USE_FILE_DESCRIPTORS
# define FMT_USE_FILE_DESCRIPTORS 0
#define FMT_USE_FILE_DESCRIPTORS 0
#endif
#if FMT_USE_FILE_DESCRIPTORS
# include "fmt/posix.h"
#include "fmt/posix.h"
#endif
#define FMT_TEST_THROW_(statement, expected_exception, expected_message, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::AssertionResult gtest_ar = ::testing::AssertionSuccess()) { \
std::string gtest_expected_message = expected_message; \
bool gtest_caught_expected = false; \
try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} \
catch (expected_exception const& e) { \
if (gtest_expected_message != e.what()) { \
gtest_ar \
<< #statement " throws an exception with a different message.\n" \
<< "Expected: " << gtest_expected_message << "\n" \
<< " Actual: " << e.what(); \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
gtest_caught_expected = true; \
} \
catch (...) { \
gtest_ar << \
"Expected: " #statement " throws an exception of type " \
#expected_exception ".\n Actual: it throws a different type."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
if (!gtest_caught_expected) { \
gtest_ar << \
"Expected: " #statement " throws an exception of type " \
#expected_exception ".\n Actual: it throws nothing."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
fail(gtest_ar.failure_message())
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::AssertionResult gtest_ar = ::testing::AssertionSuccess()) { \
std::string gtest_expected_message = expected_message; \
bool gtest_caught_expected = false; \
try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} catch (expected_exception const &e) { \
if (gtest_expected_message != e.what()) { \
gtest_ar << #statement \
" throws an exception with a different message.\n" \
<< "Expected: " << gtest_expected_message << "\n" \
<< " Actual: " << e.what(); \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
gtest_caught_expected = true; \
} catch (...) { \
gtest_ar << "Expected: " #statement \
" throws an exception of type " #expected_exception \
".\n Actual: it throws a different type."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
if (!gtest_caught_expected) { \
gtest_ar << "Expected: " #statement \
" throws an exception of type " #expected_exception \
".\n Actual: it throws nothing."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__) \
: fail(gtest_ar.failure_message())
// Tests that the statement throws the expected exception and the exception's
// what() method returns expected message.
#define EXPECT_THROW_MSG(statement, expected_exception, expected_message) \
FMT_TEST_THROW_(statement, expected_exception, \
expected_message, GTEST_NONFATAL_FAILURE_)
FMT_TEST_THROW_( \
statement, \
expected_exception, \
expected_message, \
GTEST_NONFATAL_FAILURE_)
std::string format_system_error(int error_code, fmt::string_view message);
#define EXPECT_SYSTEM_ERROR(statement, error_code, message) \
EXPECT_THROW_MSG(statement, fmt::system_error, \
format_system_error(error_code, message))
EXPECT_THROW_MSG( \
statement, fmt::system_error, format_system_error(error_code, message))
#if FMT_USE_FILE_DESCRIPTORS
@ -91,27 +92,26 @@ class OutputRedirect {
std::string restore_and_read();
};
#define FMT_TEST_WRITE_(statement, expected_output, file, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
#define FMT_TEST_WRITE_(statement, expected_output, file, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::AssertionResult gtest_ar = ::testing::AssertionSuccess()) { \
std::string gtest_expected_output = expected_output; \
OutputRedirect gtest_redir(file); \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
std::string gtest_output = gtest_redir.restore_and_read(); \
if (gtest_output != gtest_expected_output) { \
gtest_ar \
<< #statement " produces different output.\n" \
<< "Expected: " << gtest_expected_output << "\n" \
<< " Actual: " << gtest_output; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
fail(gtest_ar.failure_message())
std::string gtest_expected_output = expected_output; \
OutputRedirect gtest_redir(file); \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
std::string gtest_output = gtest_redir.restore_and_read(); \
if (gtest_output != gtest_expected_output) { \
gtest_ar << #statement " produces different output.\n" \
<< "Expected: " << gtest_expected_output << "\n" \
<< " Actual: " << gtest_output; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__) \
: fail(gtest_ar.failure_message())
// Tests that the statement writes the expected output to file.
#define EXPECT_WRITE(file, statement, expected_output) \
FMT_TEST_WRITE_(statement, expected_output, file, GTEST_NONFATAL_FAILURE_)
FMT_TEST_WRITE_(statement, expected_output, file, GTEST_NONFATAL_FAILURE_)
#ifdef _MSC_VER
@ -122,23 +122,27 @@ class SuppressAssert {
_invalid_parameter_handler original_handler_;
int original_report_mode_;
static void handle_invalid_parameter(const wchar_t *,
const wchar_t *, const wchar_t *, unsigned , uintptr_t) {}
static void handle_invalid_parameter(
const wchar_t *, const wchar_t *, const wchar_t *, unsigned, uintptr_t) {}
public:
SuppressAssert()
: original_handler_(_set_invalid_parameter_handler(handle_invalid_parameter)),
original_report_mode_(_CrtSetReportMode(_CRT_ASSERT, 0)) {
}
: original_handler_(
_set_invalid_parameter_handler(handle_invalid_parameter)),
original_report_mode_(_CrtSetReportMode(_CRT_ASSERT, 0)) {}
~SuppressAssert() {
_set_invalid_parameter_handler(original_handler_);
_CrtSetReportMode(_CRT_ASSERT, original_report_mode_);
}
};
# define SUPPRESS_ASSERT(statement) { SuppressAssert sa; statement; }
#define SUPPRESS_ASSERT(statement) \
{ \
SuppressAssert sa; \
statement; \
}
#else
# define SUPPRESS_ASSERT(statement) statement
#define SUPPRESS_ASSERT(statement) statement
#endif // _MSC_VER
#define EXPECT_SYSTEM_ERROR_NOASSERT(statement, error_code, message) \

View File

@ -8,8 +8,8 @@
#ifndef FMT_MOCK_ALLOCATOR_H_
#define FMT_MOCK_ALLOCATOR_H_
#include "gmock.h"
#include "fmt/format.h"
#include "gmock.h"
template <typename T>
class mock_allocator {
@ -17,8 +17,8 @@ class mock_allocator {
mock_allocator() {}
mock_allocator(const mock_allocator &) {}
typedef T value_type;
MOCK_METHOD1_T(allocate, T* (std::size_t n));
MOCK_METHOD2_T(deallocate, void (T* p, std::size_t n));
MOCK_METHOD1_T(allocate, T *(std::size_t n));
MOCK_METHOD2_T(deallocate, void(T *p, std::size_t n));
};
template <typename Allocator>
@ -39,13 +39,13 @@ class allocator_ref {
allocator_ref(const allocator_ref &other) : alloc_(other.alloc_) {}
allocator_ref(allocator_ref &&other) { move(other); }
allocator_ref& operator=(allocator_ref &&other) {
allocator_ref &operator=(allocator_ref &&other) {
assert(this != &other);
move(other);
return *this;
}
allocator_ref& operator=(const allocator_ref &other) {
allocator_ref &operator=(const allocator_ref &other) {
alloc_ = other.alloc_;
return *this;
}
@ -53,10 +53,10 @@ class allocator_ref {
public:
Allocator *get() const { return alloc_; }
value_type* allocate(std::size_t n) {
value_type *allocate(std::size_t n) {
return fmt::internal::allocate(*alloc_, n);
}
void deallocate(value_type* p, std::size_t n) { alloc_->deallocate(p, n); }
void deallocate(value_type *p, std::size_t n) { alloc_->deallocate(p, n); }
};
#endif // FMT_MOCK_ALLOCATOR_H_

View File

@ -35,7 +35,7 @@ static std::wostream &operator<<(std::wostream &os, TestEnum) {
return os << L"TestEnum";
}
enum TestEnum2 {A};
enum TestEnum2 { A };
TEST(OStreamTest, Enum) {
EXPECT_FALSE((fmt::convert_to_int<TestEnum, char>::value));
@ -48,9 +48,9 @@ TEST(OStreamTest, Enum) {
typedef fmt::back_insert_range<fmt::internal::buffer> range;
struct test_arg_formatter: fmt::arg_formatter<range> {
struct test_arg_formatter : fmt::arg_formatter<range> {
test_arg_formatter(fmt::format_context &ctx, fmt::format_specs &s)
: fmt::arg_formatter<range>(ctx, &s) {}
: fmt::arg_formatter<range>(ctx, &s) {}
};
TEST(OStreamTest, CustomArg) {
@ -68,27 +68,39 @@ TEST(OStreamTest, Format) {
std::string s = format("The date is {0}", Date(2012, 12, 9));
EXPECT_EQ("The date is 2012-12-9", s);
Date date(2012, 12, 9);
EXPECT_EQ(L"The date is 2012-12-9",
format(L"The date is {0}", Date(2012, 12, 9)));
EXPECT_EQ(
L"The date is 2012-12-9", format(L"The date is {0}", Date(2012, 12, 9)));
}
TEST(OStreamTest, FormatSpecs) {
EXPECT_EQ("def ", format("{0:<5}", TestString("def")));
EXPECT_EQ(" def", format("{0:>5}", TestString("def")));
EXPECT_THROW_MSG(format("{0:=5}", TestString("def")),
format_error, "format specifier requires numeric argument");
EXPECT_THROW_MSG(
format("{0:=5}", TestString("def")),
format_error,
"format specifier requires numeric argument");
EXPECT_EQ(" def ", format("{0:^5}", TestString("def")));
EXPECT_EQ("def**", format("{0:*<5}", TestString("def")));
EXPECT_THROW_MSG(format("{0:+}", TestString()),
format_error, "format specifier requires numeric argument");
EXPECT_THROW_MSG(format("{0:-}", TestString()),
format_error, "format specifier requires numeric argument");
EXPECT_THROW_MSG(format("{0: }", TestString()),
format_error, "format specifier requires numeric argument");
EXPECT_THROW_MSG(format("{0:#}", TestString()),
format_error, "format specifier requires numeric argument");
EXPECT_THROW_MSG(format("{0:05}", TestString()),
format_error, "format specifier requires numeric argument");
EXPECT_THROW_MSG(
format("{0:+}", TestString()),
format_error,
"format specifier requires numeric argument");
EXPECT_THROW_MSG(
format("{0:-}", TestString()),
format_error,
"format specifier requires numeric argument");
EXPECT_THROW_MSG(
format("{0: }", TestString()),
format_error,
"format specifier requires numeric argument");
EXPECT_THROW_MSG(
format("{0:#}", TestString()),
format_error,
"format specifier requires numeric argument");
EXPECT_THROW_MSG(
format("{0:05}", TestString()),
format_error,
"format specifier requires numeric argument");
EXPECT_EQ("test ", format("{0:13}", TestString("test")));
EXPECT_EQ("test ", format("{0:{1}}", TestString("test"), 13));
EXPECT_EQ("te", format("{0:.2}", TestString("test")));
@ -134,7 +146,7 @@ TEST(OStreamTest, WriteToOStreamMaxSize) {
} buffer(max_size);
struct mock_streambuf : std::streambuf {
MOCK_METHOD2(xsputn, std::streamsize (const void *s, std::streamsize n));
MOCK_METHOD2(xsputn, std::streamsize(const void *s, std::streamsize n));
std::streamsize xsputn(const char *s, std::streamsize n) {
const void *v = s;
return xsputn(v, n);
@ -173,11 +185,12 @@ TEST(OStreamTest, ConstexprString) {
namespace fmt_test {
struct ABC {};
template <typename Output> Output &operator<<(Output &out, ABC) {
template <typename Output>
Output &operator<<(Output &out, ABC) {
out << "ABC";
return out;
}
} // namespace fmt_test
} // namespace fmt_test
TEST(FormatTest, FormatToN) {
char buffer[4];

View File

@ -7,7 +7,7 @@
// Disable bogus MSVC warnings.
#ifdef _MSC_VER
# define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "posix-mock.h"
@ -18,9 +18,9 @@
#include <climits>
#ifdef _WIN32
# include <io.h>
# undef max
# undef ERROR
#include <io.h>
#undef max
#undef ERROR
#endif
#include "gmock.h"
@ -31,10 +31,10 @@ using fmt::buffered_file;
using fmt::error_code;
using fmt::file;
using testing::internal::scoped_ptr;
using testing::_;
using testing::StrEq;
using testing::Return;
using testing::StrEq;
using testing::internal::scoped_ptr;
namespace {
int open_count;
@ -53,14 +53,14 @@ std::size_t write_nbyte;
bool sysconf_error;
enum FStatSimulation { NONE, MAX_SIZE, ERROR } fstat_sim;
}
} // namespace
#define EMULATE_EINTR(func, error_result) \
if (func##_count != 0) { \
if (func##_count++ != 3) { \
errno = EINTR; \
return error_result; \
} \
if (func##_count != 0) { \
if (func##_count++ != 3) { \
errno = EINTR; \
return error_result; \
} \
}
#ifndef _MSC_VER
@ -70,7 +70,7 @@ int test::open(const char *path, int oflag, int mode) {
}
#else
errno_t test::sopen_s(
int* pfh, const char *filename, int oflag, int shflag, int pmode) {
int *pfh, const char *filename, int oflag, int shflag, int pmode) {
EMULATE_EINTR(open, EINTR);
return _sopen_s(pfh, filename, oflag, shflag, pmode);
}
@ -171,7 +171,7 @@ int test::fclose(FILE *stream) {
return ::fclose(stream);
}
int (test::fileno)(FILE *stream) {
int(test::fileno)(FILE *stream) {
EMULATE_EINTR(fileno, -1);
#ifdef fileno
return FMT_POSIX(fileno(stream));
@ -181,18 +181,18 @@ int (test::fileno)(FILE *stream) {
}
#ifndef _WIN32
# define EXPECT_RETRY(statement, func, message) \
func##_count = 1; \
statement; \
EXPECT_EQ(4, func##_count); \
func##_count = 0;
# define EXPECT_EQ_POSIX(expected, actual) EXPECT_EQ(expected, actual)
#define EXPECT_RETRY(statement, func, message) \
func##_count = 1; \
statement; \
EXPECT_EQ(4, func##_count); \
func##_count = 0;
#define EXPECT_EQ_POSIX(expected, actual) EXPECT_EQ(expected, actual)
#else
# define EXPECT_RETRY(statement, func, message) \
func##_count = 1; \
EXPECT_SYSTEM_ERROR(statement, EINTR, message); \
func##_count = 0;
# define EXPECT_EQ_POSIX(expected, actual)
#define EXPECT_RETRY(statement, func, message) \
func##_count = 1; \
EXPECT_SYSTEM_ERROR(statement, EINTR, message); \
func##_count = 0;
#define EXPECT_EQ_POSIX(expected, actual)
#endif
static void write_file(fmt::cstring_view filename, fmt::string_view content) {
@ -217,8 +217,8 @@ TEST(UtilTest, GetPageSize) {
TEST(FileTest, OpenRetry) {
write_file("test", "there must be something here");
scoped_ptr<file> f{FMT_NULL};
EXPECT_RETRY(f.reset(new file("test", file::RDONLY)),
open, "cannot open file test");
EXPECT_RETRY(
f.reset(new file("test", file::RDONLY)), open, "cannot open file test");
#ifndef _WIN32
char c = 0;
f->read(&c, 1);
@ -230,12 +230,15 @@ TEST(FileTest, CloseNoRetryInDtor) {
file::pipe(read_end, write_end);
scoped_ptr<file> f(new file(std::move(read_end)));
int saved_close_count = 0;
EXPECT_WRITE(stderr, {
close_count = 1;
f.reset(FMT_NULL);
saved_close_count = close_count;
close_count = 0;
}, format_system_error(EINTR, "cannot close file") + "\n");
EXPECT_WRITE(
stderr,
{
close_count = 1;
f.reset(FMT_NULL);
saved_close_count = close_count;
close_count = 0;
},
format_system_error(EINTR, "cannot close file") + "\n");
EXPECT_EQ(2, saved_close_count);
}
@ -284,8 +287,8 @@ TEST(FileTest, ReadRetry) {
write_end.close();
char buffer[SIZE];
std::size_t count = 0;
EXPECT_RETRY(count = read_end.read(buffer, SIZE),
read, "cannot read from file");
EXPECT_RETRY(
count = read_end.read(buffer, SIZE), read, "cannot read from file");
EXPECT_EQ_POSIX(static_cast<std::streamsize>(SIZE), count);
}
@ -294,8 +297,8 @@ TEST(FileTest, WriteRetry) {
file::pipe(read_end, write_end);
enum { SIZE = 4 };
std::size_t count = 0;
EXPECT_RETRY(count = write_end.write("test", SIZE),
write, "cannot write to file");
EXPECT_RETRY(
count = write_end.write("test", SIZE), write, "cannot write to file");
write_end.close();
#ifndef _WIN32
EXPECT_EQ(static_cast<std::streamsize>(SIZE), count);
@ -339,7 +342,9 @@ TEST(FileTest, ConvertWriteCount) {
TEST(FileTest, DupNoRetry) {
int stdout_fd = FMT_POSIX(fileno(stdout));
dup_count = 1;
EXPECT_SYSTEM_ERROR(file::dup(stdout_fd), EINTR,
EXPECT_SYSTEM_ERROR(
file::dup(stdout_fd),
EINTR,
fmt::format("cannot duplicate file descriptor {}", stdout_fd));
dup_count = 0;
}
@ -347,9 +352,13 @@ TEST(FileTest, DupNoRetry) {
TEST(FileTest, Dup2Retry) {
int stdout_fd = FMT_POSIX(fileno(stdout));
file f1 = file::dup(stdout_fd), f2 = file::dup(stdout_fd);
EXPECT_RETRY(f1.dup2(f2.descriptor()), dup2,
fmt::format("cannot duplicate file descriptor {} to {}",
f1.descriptor(), f2.descriptor()));
EXPECT_RETRY(
f1.dup2(f2.descriptor()),
dup2,
fmt::format(
"cannot duplicate file descriptor {} to {}",
f1.descriptor(),
f2.descriptor()));
}
TEST(FileTest, Dup2NoExceptRetry) {
@ -378,16 +387,18 @@ TEST(FileTest, FdopenNoRetry) {
file read_end, write_end;
file::pipe(read_end, write_end);
fdopen_count = 1;
EXPECT_SYSTEM_ERROR(read_end.fdopen("r"),
EINTR, "cannot associate stream with file descriptor");
EXPECT_SYSTEM_ERROR(
read_end.fdopen("r"),
EINTR,
"cannot associate stream with file descriptor");
fdopen_count = 0;
}
TEST(BufferedFileTest, OpenRetry) {
write_file("test", "there must be something here");
scoped_ptr<buffered_file> f{FMT_NULL};
EXPECT_RETRY(f.reset(new buffered_file("test", "r")),
fopen, "cannot open file test");
EXPECT_RETRY(
f.reset(new buffered_file("test", "r")), fopen, "cannot open file test");
#ifndef _WIN32
char c = 0;
if (fread(&c, 1, 1, f->get()) < 1)
@ -400,12 +411,15 @@ TEST(BufferedFileTest, CloseNoRetryInDtor) {
file::pipe(read_end, write_end);
scoped_ptr<buffered_file> f(new buffered_file(read_end.fdopen("r")));
int saved_fclose_count = 0;
EXPECT_WRITE(stderr, {
fclose_count = 1;
f.reset(FMT_NULL);
saved_fclose_count = fclose_count;
fclose_count = 0;
}, format_system_error(EINTR, "cannot close file") + "\n");
EXPECT_WRITE(
stderr,
{
fclose_count = 1;
f.reset(FMT_NULL);
saved_fclose_count = fclose_count;
fclose_count = 0;
},
format_system_error(EINTR, "cannot close file") + "\n");
EXPECT_EQ(2, saved_fclose_count);
}
@ -431,7 +445,7 @@ TEST(BufferedFileTest, FilenoNoRetry) {
struct TestMock {
static TestMock *instance;
} *TestMock::instance;
} * TestMock::instance;
TEST(ScopedMock, Scope) {
{
@ -449,17 +463,18 @@ typedef fmt::Locale::Type LocaleType;
struct LocaleMock {
static LocaleMock *instance;
MOCK_METHOD3(newlocale, LocaleType (int category_mask, const char *locale,
LocaleType base));
MOCK_METHOD1(freelocale, void (LocaleType locale));
MOCK_METHOD3(
newlocale,
LocaleType(int category_mask, const char *locale, LocaleType base));
MOCK_METHOD1(freelocale, void(LocaleType locale));
MOCK_METHOD3(strtod_l, double (const char *nptr, char **endptr,
LocaleType locale));
} *LocaleMock::instance;
MOCK_METHOD3(
strtod_l, double(const char *nptr, char **endptr, LocaleType locale));
} * LocaleMock::instance;
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4273)
#pragma warning(push)
#pragma warning(disable : 4273)
_locale_t _create_locale(int category, const char *locale) {
return LocaleMock::instance->newlocale(category, locale, 0);
@ -472,7 +487,7 @@ void _free_locale(_locale_t locale) {
double _strtod_l(const char *nptr, char **endptr, _locale_t locale) {
return LocaleMock::instance->strtod_l(nptr, endptr, locale);
}
# pragma warning(pop)
#pragma warning(pop)
#endif
#if defined(__THROW) && FMT_GCC_VERSION > 0 && FMT_GCC_VERSION <= 408
@ -481,7 +496,8 @@ double _strtod_l(const char *nptr, char **endptr, _locale_t locale) {
#define FMT_LOCALE_THROW
#endif
LocaleType newlocale(int category_mask, const char *locale, LocaleType base) FMT_LOCALE_THROW {
LocaleType newlocale(int category_mask, const char *locale, LocaleType base)
FMT_LOCALE_THROW {
return LocaleMock::instance->newlocale(category_mask, locale, base);
}
@ -496,7 +512,8 @@ FreeLocaleResult freelocale(LocaleType locale) FMT_LOCALE_THROW {
return FreeLocaleResult();
}
double strtod_l(const char *nptr, char **endptr, LocaleType locale) FMT_LOCALE_THROW {
double strtod_l(const char *nptr, char **endptr, LocaleType locale)
FMT_LOCALE_THROW {
return LocaleMock::instance->strtod_l(nptr, endptr, locale);
}

View File

@ -12,10 +12,10 @@
#include <stdio.h>
#ifdef _WIN32
# include <windows.h>
#include <windows.h>
#else
# include <sys/param.h> // for FreeBSD version
# include <sys/types.h> // for ssize_t
#include <sys/param.h> // for FreeBSD version
#include <sys/types.h> // for ssize_t
#endif
#ifndef _MSC_VER
@ -34,7 +34,7 @@ int fstat(int fd, struct stat *buf);
typedef unsigned size_t;
typedef int ssize_t;
errno_t sopen_s(
int* pfh, const char *filename, int oflag, int shflag, int pmode);
int *pfh, const char *filename, int oflag, int shflag, int pmode);
#endif
#ifndef _WIN32
@ -61,7 +61,7 @@ int pipe(int *pfds, unsigned psize, int textmode);
FILE *fopen(const char *filename, const char *mode);
int fclose(FILE *stream);
int (fileno)(FILE *stream);
int(fileno)(FILE *stream);
} // namespace test
#define FMT_SYSTEM(call) test::call

View File

@ -13,7 +13,7 @@
#include "util.h"
#ifdef fileno
# undef fileno
#undef fileno
#endif
using fmt::buffered_file;
@ -120,14 +120,17 @@ TEST(BufferedFileTest, CloseFileInDtor) {
TEST(BufferedFileTest, CloseErrorInDtor) {
scoped_ptr<buffered_file> f(new buffered_file(open_buffered_file()));
EXPECT_WRITE(stderr, {
// The close function must be called inside EXPECT_WRITE, otherwise
// the system may recycle closed file descriptor when redirecting the
// output in EXPECT_STDERR and the second close will break output
// redirection.
FMT_POSIX(close(f->fileno()));
SUPPRESS_ASSERT(f.reset(FMT_NULL));
}, format_system_error(EBADF, "cannot close file") + "\n");
EXPECT_WRITE(
stderr,
{
// The close function must be called inside EXPECT_WRITE, otherwise
// the system may recycle closed file descriptor when redirecting the
// output in EXPECT_STDERR and the second close will break output
// redirection.
FMT_POSIX(close(f->fileno()));
SUPPRESS_ASSERT(f.reset(FMT_NULL));
},
format_system_error(EBADF, "cannot close file") + "\n");
}
TEST(BufferedFileTest, Close) {
@ -150,13 +153,15 @@ TEST(BufferedFileTest, Fileno) {
#ifndef __COVERITY__
// fileno on a null FILE pointer either crashes or returns an error.
// Disable Coverity because this is intentional.
EXPECT_DEATH_IF_SUPPORTED({
try {
f.fileno();
} catch (const fmt::system_error&) {
std::exit(1);
}
}, "");
EXPECT_DEATH_IF_SUPPORTED(
{
try {
f.fileno();
} catch (const fmt::system_error &) {
std::exit(1);
}
},
"");
#endif
f = open_buffered_file();
EXPECT_TRUE(f.fileno() != -1);
@ -178,8 +183,10 @@ TEST(FileTest, OpenBufferedFileInCtor) {
}
TEST(FileTest, OpenBufferedFileError) {
EXPECT_SYSTEM_ERROR(file("nonexistent", file::RDONLY),
ENOENT, "cannot open file nonexistent");
EXPECT_SYSTEM_ERROR(
file("nonexistent", file::RDONLY),
ENOENT,
"cannot open file nonexistent");
}
TEST(FileTest, MoveCtor) {
@ -247,14 +254,17 @@ TEST(FileTest, CloseFileInDtor) {
TEST(FileTest, CloseErrorInDtor) {
scoped_ptr<file> f(new file(open_file()));
EXPECT_WRITE(stderr, {
// The close function must be called inside EXPECT_WRITE, otherwise
// the system may recycle closed file descriptor when redirecting the
// output in EXPECT_STDERR and the second close will break output
// redirection.
FMT_POSIX(close(f->descriptor()));
SUPPRESS_ASSERT(f.reset(FMT_NULL));
}, format_system_error(EBADF, "cannot close file") + "\n");
EXPECT_WRITE(
stderr,
{
// The close function must be called inside EXPECT_WRITE, otherwise
// the system may recycle closed file descriptor when redirecting the
// output in EXPECT_STDERR and the second close will break output
// redirection.
FMT_POSIX(close(f->descriptor()));
SUPPRESS_ASSERT(f.reset(FMT_NULL));
},
format_system_error(EBADF, "cannot close file") + "\n");
}
TEST(FileTest, Close) {
@ -310,8 +320,8 @@ TEST(FileTest, Dup) {
#ifndef __COVERITY__
TEST(FileTest, DupError) {
int value = -1;
EXPECT_SYSTEM_ERROR_NOASSERT(file::dup(value),
EBADF, "cannot duplicate file descriptor -1");
EXPECT_SYSTEM_ERROR_NOASSERT(
file::dup(value), EBADF, "cannot duplicate file descriptor -1");
}
#endif
@ -325,8 +335,10 @@ TEST(FileTest, Dup2) {
TEST(FileTest, Dup2Error) {
file f = open_file();
EXPECT_SYSTEM_ERROR_NOASSERT(f.dup2(-1), EBADF,
fmt::format("cannot duplicate file descriptor {} to -1", f.descriptor()));
EXPECT_SYSTEM_ERROR_NOASSERT(
f.dup2(-1),
EBADF,
fmt::format("cannot duplicate file descriptor {} to -1", f.descriptor()));
}
TEST(FileTest, Dup2NoExcept) {

View File

@ -43,9 +43,9 @@ std::wstring test_sprintf(fmt::wstring_view format, const Args &... args) {
return fmt::sprintf(format, args...);
}
#define EXPECT_PRINTF(expected_output, format, arg) \
#define EXPECT_PRINTF(expected_output, format, arg) \
EXPECT_EQ(expected_output, test_sprintf(format, arg)) \
<< "format: " << format; \
<< "format: " << format; \
EXPECT_EQ(expected_output, fmt::sprintf(make_positional(format), arg))
TEST(PrintfTest, NoArgs) {
@ -69,11 +69,10 @@ TEST(PrintfTest, Escape) {
TEST(PrintfTest, PositionalArgs) {
EXPECT_EQ("42", test_sprintf("%1$d", 42));
EXPECT_EQ("before 42", test_sprintf("before %1$d", 42));
EXPECT_EQ("42 after", test_sprintf("%1$d after",42));
EXPECT_EQ("42 after", test_sprintf("%1$d after", 42));
EXPECT_EQ("before 42 after", test_sprintf("before %1$d after", 42));
EXPECT_EQ("answer = 42", test_sprintf("%1$s = %2$d", "answer", 42));
EXPECT_EQ("42 is the answer",
test_sprintf("%2$d is the %1$s", "answer", 42));
EXPECT_EQ("42 is the answer", test_sprintf("%2$d is the %1$s", "answer", 42));
EXPECT_EQ("abracadabra", test_sprintf("%1$s%2$s%1$s", "abra", "cad"));
}
@ -82,46 +81,68 @@ TEST(PrintfTest, AutomaticArgIndexing) {
}
TEST(PrintfTest, NumberIsTooBigInArgIndex) {
EXPECT_THROW_MSG(test_sprintf(format("%{}$", BIG_NUM)),
format_error, "number is too big");
EXPECT_THROW_MSG(test_sprintf(format("%{}$d", BIG_NUM)),
format_error, "number is too big");
EXPECT_THROW_MSG(
test_sprintf(format("%{}$", BIG_NUM)), format_error, "number is too big");
EXPECT_THROW_MSG(
test_sprintf(format("%{}$d", BIG_NUM)),
format_error,
"number is too big");
}
TEST(PrintfTest, SwitchArgIndexing) {
EXPECT_THROW_MSG(test_sprintf("%1$d%", 1, 2),
format_error, "cannot switch from manual to automatic argument indexing");
EXPECT_THROW_MSG(test_sprintf(format("%1$d%{}d", BIG_NUM), 1, 2),
format_error, "number is too big");
EXPECT_THROW_MSG(test_sprintf("%1$d%d", 1, 2),
format_error, "cannot switch from manual to automatic argument indexing");
EXPECT_THROW_MSG(
test_sprintf("%1$d%", 1, 2),
format_error,
"cannot switch from manual to automatic argument indexing");
EXPECT_THROW_MSG(
test_sprintf(format("%1$d%{}d", BIG_NUM), 1, 2),
format_error,
"number is too big");
EXPECT_THROW_MSG(
test_sprintf("%1$d%d", 1, 2),
format_error,
"cannot switch from manual to automatic argument indexing");
EXPECT_THROW_MSG(test_sprintf("%d%1$", 1, 2),
format_error, "cannot switch from automatic to manual argument indexing");
EXPECT_THROW_MSG(test_sprintf(format("%d%{}$d", BIG_NUM), 1, 2),
format_error, "number is too big");
EXPECT_THROW_MSG(test_sprintf("%d%1$d", 1, 2),
format_error, "cannot switch from automatic to manual argument indexing");
EXPECT_THROW_MSG(
test_sprintf("%d%1$", 1, 2),
format_error,
"cannot switch from automatic to manual argument indexing");
EXPECT_THROW_MSG(
test_sprintf(format("%d%{}$d", BIG_NUM), 1, 2),
format_error,
"number is too big");
EXPECT_THROW_MSG(
test_sprintf("%d%1$d", 1, 2),
format_error,
"cannot switch from automatic to manual argument indexing");
// Indexing errors override width errors.
EXPECT_THROW_MSG(test_sprintf(format("%d%1${}d", BIG_NUM), 1, 2),
format_error, "number is too big");
EXPECT_THROW_MSG(test_sprintf(format("%1$d%{}d", BIG_NUM), 1, 2),
format_error, "number is too big");
EXPECT_THROW_MSG(
test_sprintf(format("%d%1${}d", BIG_NUM), 1, 2),
format_error,
"number is too big");
EXPECT_THROW_MSG(
test_sprintf(format("%1$d%{}d", BIG_NUM), 1, 2),
format_error,
"number is too big");
}
TEST(PrintfTest, InvalidArgIndex) {
EXPECT_THROW_MSG(test_sprintf("%0$d", 42), format_error,
EXPECT_THROW_MSG(
test_sprintf("%0$d", 42), format_error, "argument index out of range");
EXPECT_THROW_MSG(
test_sprintf("%2$d", 42), format_error, "argument index out of range");
EXPECT_THROW_MSG(
test_sprintf(format("%{}$d", INT_MAX), 42),
format_error,
"argument index out of range");
EXPECT_THROW_MSG(test_sprintf("%2$d", 42), format_error,
"argument index out of range");
EXPECT_THROW_MSG(test_sprintf(format("%{}$d", INT_MAX), 42),
format_error, "argument index out of range");
EXPECT_THROW_MSG(test_sprintf("%2$", 42),
format_error, "argument index out of range");
EXPECT_THROW_MSG(test_sprintf(format("%{}$d", BIG_NUM), 42),
format_error, "number is too big");
EXPECT_THROW_MSG(
test_sprintf("%2$", 42), format_error, "argument index out of range");
EXPECT_THROW_MSG(
test_sprintf(format("%{}$d", BIG_NUM), 42),
format_error,
"number is too big");
}
TEST(PrintfTest, DefaultAlignRight) {
@ -176,7 +197,7 @@ TEST(PrintfTest, HashFlag) {
EXPECT_PRINTF("0x42", "%#x", 0x42);
EXPECT_PRINTF("0X42", "%#X", 0x42);
EXPECT_PRINTF(
fmt::format("0x{:x}", static_cast<unsigned>(-0x42)), "%#x", -0x42);
fmt::format("0x{:x}", static_cast<unsigned>(-0x42)), "%#x", -0x42);
EXPECT_PRINTF("0", "%#x", 0);
EXPECT_PRINTF("0x0042", "%#06x", 0x42);
@ -207,24 +228,28 @@ TEST(PrintfTest, Width) {
EXPECT_PRINTF(" abc", "%5s", "abc");
// Width cannot be specified twice.
EXPECT_THROW_MSG(test_sprintf("%5-5d", 42), format_error,
"invalid type specifier");
EXPECT_THROW_MSG(
test_sprintf("%5-5d", 42), format_error, "invalid type specifier");
EXPECT_THROW_MSG(test_sprintf(format("%{}d", BIG_NUM), 42),
format_error, "number is too big");
EXPECT_THROW_MSG(test_sprintf(format("%1${}d", BIG_NUM), 42),
format_error, "number is too big");
EXPECT_THROW_MSG(
test_sprintf(format("%{}d", BIG_NUM), 42),
format_error,
"number is too big");
EXPECT_THROW_MSG(
test_sprintf(format("%1${}d", BIG_NUM), 42),
format_error,
"number is too big");
}
TEST(PrintfTest, DynamicWidth) {
EXPECT_EQ(" 42", test_sprintf("%*d", 5, 42));
EXPECT_EQ("42 ", test_sprintf("%*d", -5, 42));
EXPECT_THROW_MSG(test_sprintf("%*d", 5.0, 42), format_error,
"width is not integer");
EXPECT_THROW_MSG(test_sprintf("%*d"), format_error,
"argument index out of range");
EXPECT_THROW_MSG(test_sprintf("%*d", BIG_NUM, 42), format_error,
"number is too big");
EXPECT_THROW_MSG(
test_sprintf("%*d", 5.0, 42), format_error, "width is not integer");
EXPECT_THROW_MSG(
test_sprintf("%*d"), format_error, "argument index out of range");
EXPECT_THROW_MSG(
test_sprintf("%*d", BIG_NUM, 42), format_error, "number is too big");
}
TEST(PrintfTest, IntPrecision) {
@ -266,25 +291,29 @@ TEST(PrintfTest, IgnorePrecisionForNonNumericArg) {
TEST(PrintfTest, DynamicPrecision) {
EXPECT_EQ("00042", test_sprintf("%.*d", 5, 42));
EXPECT_EQ("42", test_sprintf("%.*d", -5, 42));
EXPECT_THROW_MSG(test_sprintf("%.*d", 5.0, 42), format_error,
"precision is not integer");
EXPECT_THROW_MSG(test_sprintf("%.*d"), format_error,
"argument index out of range");
EXPECT_THROW_MSG(test_sprintf("%.*d", BIG_NUM, 42), format_error,
"number is too big");
EXPECT_THROW_MSG(
test_sprintf("%.*d", 5.0, 42), format_error, "precision is not integer");
EXPECT_THROW_MSG(
test_sprintf("%.*d"), format_error, "argument index out of range");
EXPECT_THROW_MSG(
test_sprintf("%.*d", BIG_NUM, 42), format_error, "number is too big");
if (sizeof(long long) != sizeof(int)) {
long long prec = static_cast<long long>(INT_MIN) - 1;
EXPECT_THROW_MSG(test_sprintf("%.*d", prec, 42), format_error,
"number is too big");
}
EXPECT_THROW_MSG(
test_sprintf("%.*d", prec, 42), format_error, "number is too big");
}
}
template <typename T>
struct make_signed { typedef T type; };
struct make_signed {
typedef T type;
};
#define SPECIALIZE_MAKE_SIGNED(T, S) \
template <> \
struct make_signed<T> { typedef S type; }
template <> \
struct make_signed<T> { \
typedef S type; \
}
SPECIALIZE_MAKE_SIGNED(char, signed char);
SPECIALIZE_MAKE_SIGNED(unsigned char, signed char);
@ -419,7 +448,7 @@ TEST(PrintfTest, Float) {
TEST(PrintfTest, Inf) {
double inf = std::numeric_limits<double>::infinity();
for (const char* type = "fega"; *type; ++type) {
for (const char *type = "fega"; *type; ++type) {
EXPECT_PRINTF("inf", fmt::format("%{}", *type), inf);
char upper = static_cast<char>(std::toupper(*type));
EXPECT_PRINTF("INF", fmt::format("%{}", upper), inf);
@ -430,7 +459,7 @@ TEST(PrintfTest, Char) {
EXPECT_PRINTF("x", "%c", 'x');
int max = std::numeric_limits<int>::max();
EXPECT_PRINTF(fmt::format("{}", static_cast<char>(max)), "%c", max);
//EXPECT_PRINTF("x", "%lc", L'x');
// EXPECT_PRINTF("x", "%lc", L'x');
EXPECT_PRINTF(L"x", L"%c", L'x');
EXPECT_PRINTF(fmt::format(L"{}", static_cast<wchar_t>(max)), L"%c", max);
}
@ -475,17 +504,17 @@ TEST(PrintfTest, Location) {
enum E { A = 42 };
TEST(PrintfTest, Enum) {
EXPECT_PRINTF("42", "%d", A);
}
TEST(PrintfTest, Enum) { EXPECT_PRINTF("42", "%d", A); }
#if FMT_USE_FILE_DESCRIPTORS
TEST(PrintfTest, Examples) {
const char *weekday = "Thursday";
const char *month = "August";
int day = 21;
EXPECT_WRITE(stdout, fmt::printf("%1$s, %3$d %2$s", weekday, month, day),
"Thursday, 21 August");
EXPECT_WRITE(
stdout,
fmt::printf("%1$s, %3$d %2$s", weekday, month, day),
"Thursday, 21 August");
}
TEST(PrintfTest, PrintfError) {
@ -496,9 +525,7 @@ TEST(PrintfTest, PrintfError) {
}
#endif
TEST(PrintfTest, WideString) {
EXPECT_EQ(L"abc", fmt::sprintf(L"%s", L"abc"));
}
TEST(PrintfTest, WideString) { EXPECT_EQ(L"abc", fmt::sprintf(L"%s", L"abc")); }
TEST(PrintfTest, PrintfCustom) {
EXPECT_EQ("abc", test_sprintf("%s", TestString("abc")));
@ -520,8 +547,8 @@ TEST(PrintfTest, VPrintf) {
EXPECT_WRITE(stdout, fmt::vfprintf(std::cout, "%d", args), "42");
}
template<typename... Args>
void check_format_string_regression(fmt::string_view s, const Args&... args) {
template <typename... Args>
void check_format_string_regression(fmt::string_view s, const Args &... args) {
fmt::sprintf(s, args...);
}
@ -530,17 +557,16 @@ TEST(PrintfTest, CheckFormatStringRegression) {
}
TEST(PrintfTest, VSPrintfMakeArgsExample) {
fmt::format_arg_store<fmt::printf_context, int, const char *> as{
42, "something"};
fmt::format_arg_store<fmt::printf_context, int, const char *> as{42,
"something"};
fmt::basic_format_args<fmt::printf_context> args(as);
EXPECT_EQ(
"[42] something happened", fmt::vsprintf("[%d] %s happened", args));
EXPECT_EQ("[42] something happened", fmt::vsprintf("[%d] %s happened", args));
auto as2 = fmt::make_printf_args(42, "something");
fmt::basic_format_args<fmt::printf_context> args2(as2);
EXPECT_EQ(
"[42] something happened", fmt::vsprintf("[%d] %s happened", args2));
//the older gcc versions can't cast the return value
#if !defined(__GNUC__) || (__GNUC__ > 4)
// the older gcc versions can't cast the return value
#if !defined(__GNUC__) || (__GNUC__ > 4)
EXPECT_EQ(
"[42] something happened",
fmt::vsprintf(
@ -550,12 +576,11 @@ TEST(PrintfTest, VSPrintfMakeArgsExample) {
TEST(PrintfTest, VSPrintfMakeWArgsExample) {
fmt::format_arg_store<fmt::wprintf_context, int, const wchar_t *> as{
42, L"something"};
42, L"something"};
fmt::basic_format_args<fmt::wprintf_context> args(as);
EXPECT_EQ(
L"[42] something happened",
fmt::vsprintf(L"[%d] %s happened", args));
auto as2 = fmt::make_wprintf_args(42, L"something");
L"[42] something happened", fmt::vsprintf(L"[%d] %s happened", args));
auto as2 = fmt::make_wprintf_args(42, L"something");
fmt::basic_format_args<fmt::wprintf_context> args2(as2);
EXPECT_EQ(
L"[42] something happened", fmt::vsprintf(L"[%d] %s happened", args2));

View File

@ -16,10 +16,10 @@
#include "fmt/ranges.h"
#include "gtest.h"
#include <vector>
#include <array>
#include <map>
#include <string>
#include <vector>
TEST(RangesTest, FormatVector) {
std::vector<int32_t> iv{1, 2, 3, 5, 7, 11};
@ -44,8 +44,8 @@ TEST(RangesTest, FormatPair) {
}
TEST(RangesTest, FormatTuple) {
std::tuple<int64_t, float, std::string, char> tu1{42, 3.14159265358979f,
"this is tuple", 'i'};
std::tuple<int64_t, float, std::string, char> tu1{
42, 3.14159265358979f, "this is tuple", 'i'};
EXPECT_EQ("(42, 3.14159, \"this is tuple\", 'i')", fmt::format("{}", tu1));
}

View File

@ -17,7 +17,8 @@ class assertion_failure : public std::logic_error {
};
#define FMT_ASSERT(condition, message) \
if (!(condition)) throw assertion_failure(message);
if (!(condition)) \
throw assertion_failure(message);
// Expects an assertion failure.
#define EXPECT_ASSERT(stmt, message) \

View File

@ -9,14 +9,14 @@
#include "gtest.h"
#ifdef _WIN32
# include <windows.h>
#include <windows.h>
#endif
#ifdef _MSC_VER
# include <crtdbg.h>
#include <crtdbg.h>
#else
# define _CrtSetReportFile(a, b)
# define _CrtSetReportMode(a, b)
#define _CrtSetReportFile(a, b)
#define _CrtSetReportMode(a, b)
#endif
int main(int argc, char **argv) {
@ -24,8 +24,8 @@ int main(int argc, char **argv) {
// Don't display any error dialogs. This also suppresses message boxes
// on assertion failures in MinGW where _set_error_mode/CrtSetReportMode
// doesn't help.
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
SEM_NOOPENFILEERRORBOX);
SetErrorMode(
SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
#endif
// Disable message boxes on assertion failures.
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);

View File

@ -9,23 +9,22 @@
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "gmock.h"
#include "fmt/locale.h"
#include "fmt/time.h"
#include "fmt/locale.h"
#include "gmock.h"
TEST(TimeTest, Format) {
std::tm tm = std::tm();
tm.tm_year = 116;
tm.tm_mon = 3;
tm.tm_mon = 3;
tm.tm_mday = 25;
EXPECT_EQ("The date is 2016-04-25.",
fmt::format("The date is {:%Y-%m-%d}.", tm));
EXPECT_EQ(
"The date is 2016-04-25.", fmt::format("The date is {:%Y-%m-%d}.", tm));
}
TEST(TimeTest, GrowBuffer) {
std::string s = "{:";
for (int i = 0; i < 30; ++i)
s += "%c";
for (int i = 0; i < 30; ++i) s += "%c";
s += "}\n";
std::time_t t = std::time(FMT_NULL);
fmt::format(s, *std::localtime(&t));
@ -39,19 +38,13 @@ TEST(TimeTest, FormatToEmptyContainer) {
EXPECT_EQ(s, "42");
}
TEST(TimeTest, EmptyResult) {
EXPECT_EQ("", fmt::format("{}", std::tm()));
}
TEST(TimeTest, EmptyResult) { EXPECT_EQ("", fmt::format("{}", std::tm())); }
static bool EqualTime(const std::tm &lhs, const std::tm &rhs) {
return lhs.tm_sec == rhs.tm_sec &&
lhs.tm_min == rhs.tm_min &&
lhs.tm_hour == rhs.tm_hour &&
lhs.tm_mday == rhs.tm_mday &&
lhs.tm_mon == rhs.tm_mon &&
lhs.tm_year == rhs.tm_year &&
lhs.tm_wday == rhs.tm_wday &&
lhs.tm_yday == rhs.tm_yday &&
return lhs.tm_sec == rhs.tm_sec && lhs.tm_min == rhs.tm_min &&
lhs.tm_hour == rhs.tm_hour && lhs.tm_mday == rhs.tm_mday &&
lhs.tm_mon == rhs.tm_mon && lhs.tm_year == rhs.tm_year &&
lhs.tm_wday == rhs.tm_wday && lhs.tm_yday == rhs.tm_yday &&
lhs.tm_isdst == rhs.tm_isdst;
}

View File

@ -11,12 +11,12 @@
#include "fmt/posix.h"
enum {BUFFER_SIZE = 256};
enum { BUFFER_SIZE = 256 };
#ifdef _MSC_VER
# define FMT_VSNPRINTF vsprintf_s
#define FMT_VSNPRINTF vsprintf_s
#else
# define FMT_VSNPRINTF vsnprintf
#define FMT_VSNPRINTF vsnprintf
#endif
template <std::size_t SIZE>
@ -76,6 +76,7 @@ std::basic_ostream<Char> &operator<<(
class Date {
int year_, month_, day_;
public:
Date(int year, int month, int day) : year_(year), month_(month), day_(day) {}