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 May 12, 2019
2 parents b1d70b6 + f4dfd6e commit 16a442c
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 53 deletions.
10 changes: 6 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@

.. image:: https://ci.appveyor.com/api/projects/status/ehjkiefde6gucy1v
:target: https://ci.appveyor.com/project/vitaut/fmt
.. image:: https://badges.gitter.im/Join%20Chat.svg
:alt: Join the chat at https://gitter.im/fmtlib/fmt
:target: https://gitter.im/fmtlib/fmt

.. image:: https://img.shields.io/badge/stackoverflow-fmt-blue.svg
:alt: Ask questions at StackOverflow with the tag fmt
:target: http://stackoverflow.com/questions/tagged/fmt

**{fmt}** is an open-source formatting library for C++.
It can be used as a safe and fast alternative to (s)printf and iostreams.

`Documentation <http://fmtlib.net/latest/>`__

Q&A: ask questions on `StackOverflow with the tag fmt <http://stackoverflow.com/questions/tagged/fmt>`_.

Features
--------

Expand Down
19 changes: 7 additions & 12 deletions include/fmt/chrono.h
Original file line number Diff line number Diff line change
Expand Up @@ -414,9 +414,8 @@ template <
typename std::enable_if<std::is_floating_point<Rep>::value, int>::type = 0>
inline std::chrono::duration<Rep, std::milli> get_milliseconds(
std::chrono::duration<Rep, Period> d) {
auto ms =
std::chrono::duration_cast<std::chrono::duration<Rep, std::milli>>(d);
return std::chrono::duration<Rep, std::milli>(mod(ms.count(), 1000));
return std::chrono::duration<Rep, std::milli>(
mod(d.count() * Period::num / Period::den * 1000, 1000));
}

template <typename Rep, typename OutputIt>
Expand All @@ -431,12 +430,9 @@ OutputIt static format_chrono_duration_value(OutputIt out, Rep val,

template <typename Period, typename OutputIt>
static OutputIt format_chrono_duration_unit(OutputIt out) {
if (const char* unit = get_units<Period>())
return format_to(out, "{}", unit);
else if (Period::den == 1)
return format_to(out, "[{}]s", Period::num);
else
return format_to(out, "[{}/{}]s", Period::num, Period::den);
if (const char* unit = get_units<Period>()) return format_to(out, "{}", unit);
if (Period::den == 1) return format_to(out, "[{}]s", Period::num);
return format_to(out, "[{}/{}]s", Period::num, Period::den);
}

template <typename FormatContext, typename OutputIt, typename Rep,
Expand All @@ -449,7 +445,6 @@ struct chrono_formatter {
typedef std::chrono::duration<Rep> seconds;
seconds s;
typedef std::chrono::duration<Rep, std::milli> milliseconds;
milliseconds ms;

typedef typename FormatContext::char_type char_type;

Expand All @@ -465,9 +460,8 @@ struct chrono_formatter {
*out++ = '-';
}
s = std::chrono::duration_cast<seconds>(d);
ms = get_milliseconds(d);
if constexpr (is_floating_point) {
if (!std::isfinite(s.count()) || !std::isfinite(ms.count())) {
if (!std::isfinite(s.count())) {
FMT_THROW(format_error("internal overflow of floating point duration"));
}
}
Expand Down Expand Up @@ -556,6 +550,7 @@ struct chrono_formatter {
void on_second(numeric_system ns) {
if (ns == numeric_system::standard) {
write(second(), 2);
auto ms = get_milliseconds(std::chrono::duration<Rep, Period>(val));
if (ms != std::chrono::milliseconds(0)) {
*out++ = '.';
write(ms.count(), 3);
Expand Down
2 changes: 1 addition & 1 deletion include/fmt/format-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ template <int GRISU_VERSION> struct grisu_shortest_handler {
};

template <typename Double, FMT_ENABLE_IF_T(sizeof(Double) == sizeof(uint64_t))>
FMT_FUNC bool grisu_format(Double value, buffer<char>& buf, int precision,
FMT_API bool grisu_format(Double value, buffer<char>& buf, int precision,
unsigned options, int& exp) {
FMT_ASSERT(value >= 0, "value is negative");
bool fixed = (options & grisu_options::fixed) != 0;
Expand Down
41 changes: 21 additions & 20 deletions include/fmt/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,18 @@ FMT_END_NAMESPACE
# endif
#endif

// EDG C++ Front End based compilers (icc, nvcc) do not currently support UDL
// templates.
#if FMT_USE_USER_DEFINED_LITERALS && FMT_ICC_VERSION == 0 && \
FMT_CUDA_VERSION == 0 && \
((FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L) || \
(defined(FMT_CLANG_VERSION) && FMT_CLANG_VERSION >= 304))
# define FMT_UDL_TEMPLATE 1
#else
# define FMT_UDL_TEMPLATE 0
#ifndef FMT_USE_UDL_TEMPLATE
// EDG front end based compilers (icc, nvcc) do not support UDL templates yet
// and GCC 9 warns about them.
# if FMT_USE_USER_DEFINED_LITERALS && FMT_ICC_VERSION == 0 && \
FMT_CUDA_VERSION == 0 && \
((FMT_GCC_VERSION >= 600 && FMT_GCC_VERSION <= 900 && \
__cplusplus >= 201402L) || \
(defined(FMT_CLANG_VERSION) && FMT_CLANG_VERSION >= 304))
# define FMT_USE_UDL_TEMPLATE 1
# else
# define FMT_USE_UDL_TEMPLATE 0
# endif
#endif

#if FMT_HAS_GXX_CXX11 || FMT_HAS_FEATURE(cxx_trailing_return) || \
Expand Down Expand Up @@ -251,7 +254,7 @@ namespace uintptr {
struct uintptr_t {
unsigned char value[sizeof(void*)];
};
}
} // namespace uintptr
using uintptr::uintptr_t;
typedef std::numeric_limits<uintptr_t> numutil;

Expand Down Expand Up @@ -1118,10 +1121,7 @@ FMT_CONSTEXPR unsigned basic_parse_context<Char, ErrorHandler>::next_arg_id() {
namespace internal {

namespace grisu_options {
enum {
fixed = 1,
grisu3 = 2
};
enum { fixed = 1, grisu3 = 2 };
}

// Formats value using the Grisu algorithm:
Expand Down Expand Up @@ -1198,12 +1198,13 @@ It grisu_prettify(const char* digits, int size, int exp, It it,
} else if (full_exp > 0) {
// 1234e-2 -> 12.34[0+]
it = copy_str<Char>(digits, digits + full_exp, it);
*it++ = static_cast<Char>('.');
if (!params.trailing_zeros) {
// Remove trailing zeros.
while (size > full_exp && digits[size - 1] == '0') --size;
if (size != full_exp) *it++ = static_cast<Char>('.');
return copy_str<Char>(digits + full_exp, digits + size, it);
}
*it++ = static_cast<Char>('.');
it = copy_str<Char>(digits + full_exp, digits + size, it);
if (params.num_digits > size) {
// Add trailing zeros.
Expand Down Expand Up @@ -2886,7 +2887,7 @@ void basic_writer<Range>::write_double(T value, const format_specs& spec) {
(spec.type != 'a' && spec.type != 'A' && spec.type != 'e' &&
spec.type != 'E') &&
internal::grisu_format(static_cast<double>(value), buffer,
precision, options, exp);
precision, options, exp);
if (!use_grisu) internal::sprintf_format(value, buffer, spec);

if (handler.as_percentage) {
Expand Down Expand Up @@ -3583,7 +3584,7 @@ inline std::size_t formatted_size(string_view format_str, const Args&... args) {
#if FMT_USE_USER_DEFINED_LITERALS
namespace internal {

# if FMT_UDL_TEMPLATE
# if FMT_USE_UDL_TEMPLATE
template <typename Char, Char... CHARS> class udl_formatter {
public:
template <typename... Args>
Expand All @@ -3606,7 +3607,7 @@ template <typename Char> struct udl_formatter {
return format(str, std::forward<Args>(args)...);
}
};
# endif // FMT_UDL_TEMPLATE
# endif // FMT_USE_UDL_TEMPLATE

template <typename Char> struct udl_arg {
const Char* str;
Expand All @@ -3619,7 +3620,7 @@ template <typename Char> struct udl_arg {
} // namespace internal

inline namespace literals {
# if FMT_UDL_TEMPLATE
# if FMT_USE_UDL_TEMPLATE
template <typename Char, Char... CHARS>
FMT_CONSTEXPR internal::udl_formatter<Char, CHARS...> operator""_format() {
return {};
Expand All @@ -3643,7 +3644,7 @@ inline internal::udl_formatter<wchar_t> operator"" _format(const wchar_t* s,
std::size_t) {
return {s};
}
# endif // FMT_UDL_TEMPLATE
# endif // FMT_USE_UDL_TEMPLATE

/**
\rst
Expand Down
4 changes: 2 additions & 2 deletions include/fmt/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
#include "chrono.h"

#ifdef _MSC_VER
#pragma message("fmt/time.h is deprecated, use fmt/chrono.h instead")
# pragma message("fmt/time.h is deprecated, use fmt/chrono.h instead")
#else
#warning fmt/time.h is deprecated, use fmt/chrono.h instead
# warning fmt/time.h is deprecated, use fmt/chrono.h instead
#endif

#endif // FMT_TIME_H_
9 changes: 8 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,16 @@ if (NOT SUPPORTS_VARIADIC_TEMPLATES)
target_compile_definitions(gmock PUBLIC GTEST_LANG_CXX11=0)
endif ()

# Workaround a bug in implementation of variadic templates in MSVC11.
if (MSVC)
# Workaround a bug in implementation of variadic templates in MSVC11.
target_compile_definitions(gmock PUBLIC _VARIADIC_MAX=10)

# Disable MSVC warnings of _CRT_INSECURE_DEPRECATE functions.
target_compile_definitions(gmock PUBLIC _CRT_SECURE_NO_WARNINGS)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# Disable MSVC warnings of POSIX functions.
target_compile_options(gmock PUBLIC -Wno-deprecated-declarations)
endif ()
endif ()

# GTest doesn't detect <tuple> with clang.
Expand Down
4 changes: 4 additions & 0 deletions test/chrono-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,10 @@ TEST(ChronoTest, SpecialDurations) {
fmt::format("{:%I %H %M %S %R %r}", std::chrono::duration<double>(nan)));
fmt::format("{:%S}",
std::chrono::duration<float, std::atto>(1.79400457e+31f));
EXPECT_EQ(fmt::format("{}", std::chrono::duration<float, std::exa>(1)),
"1Es");
EXPECT_EQ(fmt::format("{}", std::chrono::duration<float, std::atto>(1)),
"1as");
}

TEST(ChronoTest, DurationIsFloatNaN) {
Expand Down
9 changes: 9 additions & 0 deletions test/format-impl-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,12 @@ TEST(UtilTest, CountDigits) {
test_count_digits<uint32_t>();
test_count_digits<uint64_t>();
}

TEST(UtilTest, WriteUIntPtr) {
fmt::memory_buffer buf;
fmt::writer writer(buf);
writer.write_pointer(fmt::internal::bit_cast<fmt::internal::uintptr_t>(
reinterpret_cast<void*>(0xface)),
FMT_NULL);
EXPECT_EQ("0xface", to_string(buf));
}
26 changes: 13 additions & 13 deletions test/format-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -685,15 +685,6 @@ TEST(WriterTest, WriteWideString) {
// std::declval<fmt::basic_writer<fmt::wbuffer>>().write("abc");
}

TEST(WriterTest, WriteUIntPtr) {
memory_buffer buf;
fmt::writer writer(buf);
writer.write_pointer(fmt::internal::bit_cast<fmt::internal::uintptr_t>(
reinterpret_cast<void*>(0xface)),
FMT_NULL);
EXPECT_EQ("0xface", to_string(buf));
}

TEST(FormatToTest, FormatWithoutArgs) {
std::string s;
fmt::format_to(std::back_inserter(s), "test");
Expand Down Expand Up @@ -2491,18 +2482,25 @@ TEST(FormatTest, FmtStringInTemplate) {

#endif // FMT_USE_CONSTEXPR

// C++20 feature test, since r346892 Clang considers char8_t a fundamental
// type in this mode. If this is the case __cpp_char8_t will be defined.
#ifndef __cpp_char8_t
// Locally provide type char8_t defined in format.h
using fmt::char8_t;
#endif

TEST(FormatTest, ConstructU8StringViewFromCString) {
fmt::u8string_view s("ab");
EXPECT_EQ(s.size(), 2u);
const fmt::char8_t* data = s.data();
const char8_t* data = s.data();
EXPECT_EQ(data[0], 'a');
EXPECT_EQ(data[1], 'b');
}

TEST(FormatTest, ConstructU8StringViewFromDataAndSize) {
fmt::u8string_view s("foobar", 3);
EXPECT_EQ(s.size(), 3u);
const fmt::char8_t* data = s.data();
const char8_t* data = s.data();
EXPECT_EQ(data[0], 'f');
EXPECT_EQ(data[1], 'o');
EXPECT_EQ(data[2], 'o');
Expand All @@ -2513,7 +2511,7 @@ TEST(FormatTest, U8StringViewLiteral) {
using namespace fmt::literals;
fmt::u8string_view s = "ab"_u;
EXPECT_EQ(s.size(), 2u);
const fmt::char8_t* data = s.data();
const char8_t* data = s.data();
EXPECT_EQ(data[0], 'a');
EXPECT_EQ(data[1], 'b');
EXPECT_EQ(format("{:*^5}"_u, "🤡"_u), "**🤡**"_u);
Expand All @@ -2534,8 +2532,10 @@ TEST(FormatTest, CharTraitsIsNotAmbiguous) {
// Test that we don't inject internal names into the std namespace.
using namespace std;
char_traits<char>::char_type c;
(void)c;
#if __cplusplus >= 201103L
std::string s;
begin(s);
auto lval = begin(s);
(void)lval;
#endif
}
7 changes: 7 additions & 0 deletions test/posix-mock-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,10 @@ struct LocaleMock {
# ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable : 4273)
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Winconsistent-dllimport"
# endif

_locale_t _create_locale(int category, const char* locale) {
return LocaleMock::instance->newlocale(category, locale, 0);
Expand All @@ -473,6 +477,9 @@ 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);
}
# ifdef __clang__
# pragma clang diagnostic pop
# endif
# pragma warning(pop)
# endif

Expand Down
2 changes: 2 additions & 0 deletions test/printf-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,8 @@ TEST(PrintfTest, Float) {
EXPECT_PRINTF(buffer, "%E", 392.65);
EXPECT_PRINTF("392.65", "%g", 392.65);
EXPECT_PRINTF("392.65", "%G", 392.65);
EXPECT_PRINTF("392", "%g", 392.0);
EXPECT_PRINTF("392", "%G", 392.0);
safe_sprintf(buffer, "%a", -392.65);
EXPECT_EQ(buffer, format("{:a}", -392.65));
safe_sprintf(buffer, "%A", -392.65);
Expand Down

0 comments on commit 16a442c

Please sign in to comment.