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:
#	test/chrono-test.cc
  • Loading branch information
pauldreik committed May 5, 2019
2 parents a574b21 + c1d430e commit 757319a
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 18 deletions.
37 changes: 26 additions & 11 deletions include/fmt/chrono.h
Original file line number Diff line number Diff line change
Expand Up @@ -376,13 +376,24 @@ struct chrono_format_checker {
FMT_NORETURN void on_tz_name() { report_no_date(); }
};

template <typename Int> inline int to_int(Int value) {
template <typename T> inline int to_int(T value) {
FMT_ASSERT(value >= (std::numeric_limits<int>::min)() &&
value <= (std::numeric_limits<int>::max)(),
"invalid value");
return static_cast<int>(value);
}

template <typename T,
typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
inline T mod(T x, int y) {
return x % y;
}
template <typename T, typename std::enable_if<std::is_floating_point<T>::value,
int>::type = 0>
inline T mod(T x, int y) {
return std::fmod(x, y);
}

template <typename Rep, typename OutputIt>
OutputIt static format_chrono_duration_value(OutputIt out, Rep val,
int precision) {
Expand Down Expand Up @@ -410,29 +421,33 @@ struct chrono_formatter {
OutputIt out;
int precision;
Rep val;
typedef std::chrono::duration<Rep> seconds;
seconds s;
typedef std::chrono::duration<Rep, std::milli> milliseconds;
std::chrono::seconds s;
milliseconds ms;

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()),
s(std::chrono::duration_cast<std::chrono::seconds>(d)),
ms(std::chrono::duration_cast<milliseconds>(d - s)) {}
: context(ctx), out(o), val(d.count()) {
if (d.count() < 0) {
d = -d;
*out++ = '-';
}
s = std::chrono::duration_cast<seconds>(d);
ms = std::chrono::duration_cast<milliseconds>(d - s);
}

int hour() const { return to_int((s.count() / 3600) % 24); }
int hour() const { return to_int(mod((s.count() / 3600), 24)); }

int hour12() const {
auto hour = to_int((s.count() / 3600) % 12);
auto hour = to_int(mod((s.count() / 3600), 12));
return hour > 0 ? hour : 12;
}

int minute() const { return to_int((s.count() / 60) % 60); }
int second() const { return to_int(s.count() % 60); }
int minute() const { return to_int(mod((s.count() / 60), 60)); }
int second() const { return to_int(mod(s.count(), 60)); }

std::tm time() const {
auto time = std::tm();
Expand Down
14 changes: 7 additions & 7 deletions include/fmt/ostream.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ template <class Char> class formatbuf : public std::basic_streambuf<Char> {
buffer<Char>& buffer_;

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

protected:
// The put-area is actually always empty. This makes the implementation
Expand Down Expand Up @@ -72,26 +72,26 @@ template <typename T, typename Char> class is_streamable {
// Write the content of buf to os.
template <typename Char>
void write(std::basic_ostream<Char>& os, buffer<Char>& buf) {
const Char* data = buf.data();
const Char* buf_data = buf.data();
typedef std::make_unsigned<std::streamsize>::type UnsignedStreamSize;
UnsignedStreamSize size = buf.size();
UnsignedStreamSize max_size =
internal::to_unsigned((std::numeric_limits<std::streamsize>::max)());
do {
UnsignedStreamSize n = size <= max_size ? size : max_size;
os.write(data, static_cast<std::streamsize>(n));
data += n;
os.write(buf_data, static_cast<std::streamsize>(n));
buf_data += n;
size -= n;
} while (size != 0);
}

template <typename Char, typename T>
void format_value(buffer<Char>& buffer, const T& value) {
internal::formatbuf<Char> format_buf(buffer);
void format_value(buffer<Char>& buf, const T& value) {
internal::formatbuf<Char> format_buf(buf);
std::basic_ostream<Char> output(&format_buf);
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
output << value;
buffer.resize(buffer.size());
buf.resize(buf.size());
}

// Formats an object of type T that has an overloaded ostream operator<<.
Expand Down
9 changes: 9 additions & 0 deletions test/chrono-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -305,4 +305,13 @@ TEST(ChronoTest, InvalidColons) {
EXPECT_THROW(fmt::format("{0}=:{0::", std::chrono::seconds(0)),
fmt::format_error);
}

TEST(ChronoTest, LargeDuration) {
EXPECT_EQ("40", fmt::format("{:%S}", std::chrono::duration<double>(1e20)));
}

TEST(ChronoTest, NegativeDuration) {
EXPECT_EQ("-00:01", fmt::format("{:%M:%S}", std::chrono::duration<double>(-1)));
}

#endif // FMT_STATIC_THOUSANDS_SEPARATOR

0 comments on commit 757319a

Please sign in to comment.