Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into fuzz
Browse files Browse the repository at this point in the history
# Conflicts:
#	include/fmt/chrono.h
  • Loading branch information
pauldreik committed Jun 3, 2019
2 parents 1c25840 + d54e64b commit 2740241
Show file tree
Hide file tree
Showing 17 changed files with 325 additions and 283 deletions.
46 changes: 28 additions & 18 deletions include/fmt/chrono.h
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,17 @@ inline T mod(T x, int y) {
return std::fmod(x, y);
}

// If T is an integral type, maps T to its unsigned counterpart, otherwise
// leaves it unchanged (unlike std::make_unsigned).
template <typename T, bool INTEGRAL = std::is_integral<T>::value>
struct make_unsigned_or_unchanged {
using type = T;
};

template <typename T> struct make_unsigned_or_unchanged<T, true> {
using type = typename std::make_unsigned<T>::type;
};

template <typename Rep, typename Period,
typename std::enable_if<std::is_integral<Rep>::value, int>::type = 0>
inline std::chrono::duration<Rep, std::milli> get_milliseconds(
Expand Down Expand Up @@ -484,40 +495,39 @@ struct chrono_formatter {
FormatContext& context;
OutputIt out;
int precision;
typedef typename std::conditional<std::is_integral<Rep>::value &&
sizeof(Rep) < sizeof(int),
int, Rep>::type rep;
// rep is unsigned to avoid overflow.
using rep = typename std::conditional<
std::is_integral<Rep>::value && sizeof(Rep) < sizeof(int), unsigned,
typename make_unsigned_or_unchanged<Rep>::type>::type;
rep val;
typedef std::chrono::duration<rep> seconds;
seconds s;
typedef std::chrono::duration<rep, std::milli> milliseconds;
bool negative;

typedef typename FormatContext::char_type char_type;

explicit chrono_formatter(FormatContext& ctx, OutputIt o,
std::chrono::duration<Rep, Period> d)
: context(ctx), out(o), val(d.count()) {
if (d.count() < 0) {
//protect against signed integer overflow
using TT=std::numeric_limits<Rep>;
if(TT::is_integer && TT::is_signed) {
if(d.count()==TT::min()) {
FMT_THROW(format_error("value would cause UB"));
}
}
d = -d;
}
: context(ctx), out(o), val(d.count()), negative(false) {
if (d.count() < 0) {
val = -val;
negative = true;
}

// this may overflow and/or the result may not fit in the
// target type.
#ifdef FMT_SAFE_DURATION_CAST
int ec;
s = safe_duration_cast::safe_duration_cast<seconds>(d, ec);
// might need checked conversion (rep!=Rep)
auto tmpval=std::chrono::duration<rep, Period>(val);
s = safe_duration_cast::safe_duration_cast<seconds>(tmpval, ec);
if (ec) {
FMT_THROW(format_error("value would cause UB or the wrong result"));
}
#else
s = std::chrono::duration_cast<seconds>(d);
s = std::chrono::duration_cast<seconds>(
std::chrono::duration<rep, Period>(val));
#endif
}

Expand Down Expand Up @@ -558,9 +568,9 @@ struct chrono_formatter {
}

void write_sign() {
if (val < 0) {
if (negative) {
*out++ = '-';
val = -val;
negative = false;
}
}

Expand Down
41 changes: 19 additions & 22 deletions include/fmt/color.h
Original file line number Diff line number Diff line change
Expand Up @@ -526,9 +526,9 @@ template <> struct is_string<std::FILE*> : std::false_type {};
template <> struct is_string<const std::FILE*> : std::false_type {};

template <typename Char>
std::basic_string<Char> vformat(
const text_style& ts, basic_string_view<Char> format_str,
basic_format_args<typename buffer_context<Char>::type> args) {
std::basic_string<Char> vformat(const text_style& ts,
basic_string_view<Char> format_str,
basic_format_args<buffer_context<Char> > args) {
basic_memory_buffer<Char> buffer;
bool has_style = false;
if (ts.has_emphasis()) {
Expand Down Expand Up @@ -556,9 +556,9 @@ std::basic_string<Char> vformat(
}
} // namespace internal

template <typename S, typename Char = typename internal::char_t<S>::type>
template <typename S, typename Char = char_t<S> >
void vprint(std::FILE* f, const text_style& ts, const S& format,
basic_format_args<typename buffer_context<Char>::type> args) {
basic_format_args<buffer_context<Char> > args) {
bool has_style = false;
if (ts.has_emphasis()) {
has_style = true;
Expand Down Expand Up @@ -587,15 +587,14 @@ void vprint(std::FILE* f, const text_style& ts, const S& format,
fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
"Elapsed time: {0:.2f} seconds", 1.23);
*/
template <typename String, typename... Args,
FMT_ENABLE_IF(internal::is_string<String>::value)>
void print(std::FILE* f, const text_style& ts, const String& format_str,
template <typename S, typename... Args,
FMT_ENABLE_IF(internal::is_string<S>::value)>
void print(std::FILE* f, const text_style& ts, const S& format_str,
const Args&... args) {
internal::check_format_string<Args...>(format_str);
typedef typename internal::char_t<String>::type char_t;
typedef typename buffer_context<char_t>::type context_t;
format_arg_store<context_t, Args...> as{args...};
vprint(f, ts, format_str, basic_format_args<context_t>(as));
using context = buffer_context<char_t<S> >;
format_arg_store<context, Args...> as{args...};
vprint(f, ts, format_str, basic_format_args<context>(as));
}

/**
Expand All @@ -605,17 +604,16 @@ void print(std::FILE* f, const text_style& ts, const String& format_str,
fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
"Elapsed time: {0:.2f} seconds", 1.23);
*/
template <typename String, typename... Args,
FMT_ENABLE_IF(internal::is_string<String>::value)>
void print(const text_style& ts, const String& format_str,
const Args&... args) {
template <typename S, typename... Args,
FMT_ENABLE_IF(internal::is_string<S>::value)>
void print(const text_style& ts, const S& format_str, const Args&... args) {
return print(stdout, ts, format_str, args...);
}

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

Expand All @@ -631,10 +629,9 @@ inline std::basic_string<Char> vformat(
"The answer is {}", 42);
\endrst
*/
template <typename S, typename... Args>
inline std::basic_string<FMT_CHAR(S)> format(const text_style& ts,
const S& format_str,
const Args&... args) {
template <typename S, typename... Args, typename Char = char_t<S> >
inline std::basic_string<Char> format(const text_style& ts, const S& format_str,
const Args&... args) {
return internal::vformat(ts, to_string_view(format_str),
{internal::make_args_checked(format_str, args...)});
}
Expand Down
Loading

0 comments on commit 2740241

Please sign in to comment.