Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into fuzz
Browse files Browse the repository at this point in the history
  • Loading branch information
pauldreik committed Jun 12, 2019
2 parents 8feb8a3 + e5422db commit 90cab5a
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 90 deletions.
77 changes: 36 additions & 41 deletions include/fmt/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ using enable_if_t = typename std::enable_if<B, T>::type;
template <bool B, class T, class F>
using conditional_t = typename std::conditional<B, T, F>::type;
template <bool B> using bool_constant = std::integral_constant<bool, B>;
template <typename T>
using remove_reference_t = typename std::remove_reference<T>::type;

struct monostate {};

Expand Down Expand Up @@ -714,7 +716,7 @@ template <typename Context> class value {
custom.format = format_custom_arg<
T, conditional_t<has_formatter<T, Context>::value,
typename Context::template formatter_type<T>,
internal::fallback_formatter<T, char_type>>>;
fallback_formatter<T, char_type>>>;
}

value(const named_arg_base<char_type>& val) { named_arg = &val; }
Expand Down Expand Up @@ -779,7 +781,7 @@ template <typename Context> struct arg_mapper {
template <typename T,
FMT_ENABLE_IF(
std::is_constructible<basic_string_view<char_type>, T>::value &&
!internal::is_string<T>::value)>
!is_string<T>::value)>
FMT_CONSTEXPR basic_string_view<char_type> map(const T& val) {
return basic_string_view<char_type>(val);
}
Expand Down Expand Up @@ -989,12 +991,12 @@ class locale_ref {
template <typename Locale> Locale get() const;
};

template <typename> constexpr unsigned long long get_types() { return 0; }
template <typename> constexpr unsigned long long encode_types() { return 0; }

template <typename Context, typename Arg, typename... Args>
constexpr unsigned long long get_types() {
constexpr unsigned long long encode_types() {
return mapped_type_constant<Arg, Context>::value |
(get_types<Context, Args...>() << 4);
(encode_types<Context, Args...>() << 4);
}

template <typename Context, typename T>
Expand Down Expand Up @@ -1094,9 +1096,10 @@ template <typename Context, typename... Args> class format_arg_store {
friend class basic_format_args<Context>;

public:
static constexpr unsigned long long TYPES =
is_packed ? internal::get_types<Context, Args...>()
static constexpr unsigned long long types =
is_packed ? internal::encode_types<Context, Args...>()
: internal::is_unpacked_bit | num_args;
FMT_DEPRECATED static constexpr unsigned long long TYPES = types;

format_arg_store(const Args&... args)
: data_{internal::make_arg<is_packed, Context>(args)...} {}
Expand Down Expand Up @@ -1138,10 +1141,9 @@ template <typename Context> class basic_format_args {

bool is_packed() const { return (types_ & internal::is_unpacked_bit) == 0; }

typename internal::type type(unsigned index) const {
internal::type type(unsigned index) const {
unsigned shift = index * 4;
return static_cast<typename internal::type>((types_ & (0xfull << shift)) >>
shift);
return static_cast<internal::type>((types_ & (0xfull << shift)) >> shift);
}

friend class internal::arg_map<Context>;
Expand Down Expand Up @@ -1174,7 +1176,7 @@ template <typename Context> class basic_format_args {
*/
template <typename... Args>
basic_format_args(const format_arg_store<Context, Args...>& store)
: types_(static_cast<unsigned long long>(store.TYPES)) {
: types_(static_cast<unsigned long long>(store.types)) {
set_data(store.data_);
}

Expand Down Expand Up @@ -1207,22 +1209,30 @@ template <typename Context> class basic_format_args {
// It is a separate type rather than an alias to make symbols readable.
struct format_args : basic_format_args<format_context> {
template <typename... Args>
format_args(Args&&... arg)
: basic_format_args<format_context>(std::forward<Args>(arg)...) {}
format_args(Args&&... args)
: basic_format_args<format_context>(std::forward<Args>(args)...) {}
};
struct wformat_args : basic_format_args<wformat_context> {
template <typename... Args>
wformat_args(Args&&... arg)
: basic_format_args<wformat_context>(std::forward<Args>(arg)...) {}
wformat_args(Args&&... args)
: basic_format_args<wformat_context>(std::forward<Args>(args)...) {}
};

template <typename Container> struct is_contiguous : std::false_type {};

template <typename Char>
struct is_contiguous<std::basic_string<Char>> : std::true_type {};

template <typename Char>
struct is_contiguous<internal::buffer<Char>> : std::true_type {};

namespace internal {
template <typename Context>
FMT_CONSTEXPR typename Context::format_arg get_arg(Context& ctx, unsigned id) {
auto arg = ctx.arg(id);
if (!arg) ctx.on_error("argument index out of range");
return arg;
}

template <typename OutputIt>
struct is_contiguous_back_insert_iterator : std::false_type {};
template <typename Container>
struct is_contiguous_back_insert_iterator<std::back_insert_iterator<Container>>
: is_contiguous<Container> {};

template <typename Char> struct named_arg_base {
basic_string_view<Char> name;
Expand Down Expand Up @@ -1254,7 +1264,7 @@ void check_format_string(S);
template <typename S, typename... Args, typename Char = char_t<S>>
inline format_arg_store<buffer_context<Char>, Args...> make_args_checked(
const S& format_str, const Args&... args) {
internal::check_format_string<Args...>(format_str);
check_format_string<Args...>(format_str);
return {args...};
}

Expand All @@ -1264,7 +1274,7 @@ std::basic_string<Char> vformat(basic_string_view<Char> format_str,

template <typename Char>
typename buffer_context<Char>::iterator vformat_to(
internal::buffer<Char>& buf, basic_string_view<Char> format_str,
buffer<Char>& buf, basic_string_view<Char> format_str,
basic_format_args<buffer_context<Char>> args);
} // namespace internal

Expand Down Expand Up @@ -1293,30 +1303,15 @@ inline internal::named_arg<T, Char> arg(const S& name, const T& arg) {
template <typename S, typename T, typename Char>
void arg(S, internal::named_arg<T, Char>) = delete;

template <typename Container> struct is_contiguous : std::false_type {};

template <typename Char>
struct is_contiguous<std::basic_string<Char>> : std::true_type {};

template <typename Char>
struct is_contiguous<internal::buffer<Char>> : std::true_type {};

template <typename OutputIt>
struct is_contiguous_back_insert_iterator : std::false_type {};

template <typename Container>
struct is_contiguous_back_insert_iterator<std::back_insert_iterator<Container>>
: is_contiguous<Container> {};

/** Formats a string and writes the output to ``out``. */
// GCC 8 and earlier cannot handle std::back_insert_iterator<Container> with
// vformat_to<ArgFormatter>(...) overload, so SFINAE on iterator type instead.
template <typename OutputIt, typename S, typename Char = char_t<S>,
FMT_ENABLE_IF(is_contiguous_back_insert_iterator<OutputIt>::value)>
FMT_ENABLE_IF(
internal::is_contiguous_back_insert_iterator<OutputIt>::value)>
OutputIt vformat_to(OutputIt out, const S& format_str,
basic_format_args<buffer_context<Char>> args) {
using container = typename std::remove_reference<decltype(
internal::get_container(out))>::type;
using container = remove_reference_t<decltype(internal::get_container(out))>;
internal::container_buffer<container> buf((internal::get_container(out)));
internal::vformat_to(buf, to_string_view(format_str), args);
return out;
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 @@ -236,7 +236,7 @@ FMT_FUNC void system_error::init(int err_code, string_view format_str,

namespace internal {

template <> FMT_FUNC int count_digits<4>(internal::uintptr_t n) {
template <> FMT_FUNC int count_digits<4>(internal::uintptr n) {
// Assume little endian; pointer formatting is implementation-defined anyway.
int i = static_cast<int>(sizeof(void*)) - 1;
while (i > 0 && n.value[i] == 0) --i;
Expand Down
58 changes: 23 additions & 35 deletions include/fmt/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
#include <memory>
#include <stdexcept>

#include "core.h"

#ifdef __clang__
# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
#else
Expand All @@ -57,8 +59,6 @@
# define FMT_CUDA_VERSION 0
#endif

#include "core.h"

#if FMT_GCC_VERSION >= 406 || FMT_CLANG_VERSION
# pragma GCC diagnostic push

Expand Down Expand Up @@ -243,13 +243,14 @@ namespace internal {
#endif

// A fallback implementation of uintptr_t for systems that lack it.
namespace uintptr {
struct uintptr_t {
struct uintptr {
unsigned char value[sizeof(void*)];
};
} // namespace uintptr
using uintptr::uintptr_t;
typedef std::numeric_limits<uintptr_t> numutil;
#ifdef UINTPTR_MAX
using uintptr_t = ::uintptr_t;
#else
using uintptr_t = uintptr;
#endif

template <typename T> inline bool use_grisu() {
return FMT_USE_GRISU && std::numeric_limits<double>::is_iec559 &&
Expand Down Expand Up @@ -303,25 +304,7 @@ typename Allocator::value_type* allocate(Allocator& alloc, std::size_t n) {
#endif
}
} // namespace internal
FMT_END_NAMESPACE

namespace std {
using namespace fmt::v5::internal::uintptr;
// Standard permits specialization of std::numeric_limits. This specialization
// is used to detect presence of uintptr_t.
template <>
class numeric_limits<fmt::internal::uintptr_t>
: public std::numeric_limits<int> {
public:
typedef uintptr_t uintptr_type;

static uintptr_type to_uint(const void* p) {
return fmt::internal::bit_cast<uintptr_type>(p);
}
};
} // namespace std

FMT_BEGIN_NAMESPACE
template <typename Range> class basic_writer;

template <typename OutputIt, typename T = typename OutputIt::value_type>
Expand Down Expand Up @@ -756,7 +739,7 @@ template <unsigned BITS, typename UInt> inline int count_digits(UInt n) {
return num_digits;
}

template <> int count_digits<4>(internal::uintptr_t n);
template <> int count_digits<4>(internal::uintptr n);

template <typename Char>
inline size_t count_code_points(basic_string_view<Char> s) {
Expand Down Expand Up @@ -985,7 +968,7 @@ inline Char* format_uint(Char* buffer, UInt value, int num_digits,
}

template <unsigned BASE_BITS, typename Char>
Char* format_uint(Char* buffer, internal::uintptr_t n, int num_digits,
Char* format_uint(Char* buffer, internal::uintptr n, int num_digits,
bool = false) {
auto char_digits = std::numeric_limits<unsigned char>::digits / 4;
int start = (num_digits + char_digits - 1) / char_digits - 1;
Expand Down Expand Up @@ -1422,7 +1405,7 @@ class arg_formatter_base {
}

void write_pointer(const void* p) {
writer_.write_pointer(internal::numutil::to_uint(p), specs_);
writer_.write_pointer(internal::bit_cast<internal::uintptr_t>(p), specs_);
}

protected:
Expand Down Expand Up @@ -1748,6 +1731,13 @@ FMT_CONSTEXPR void set_dynamic_spec(T& value, FormatArg arg, ErrorHandler eh) {

struct auto_id {};

template <typename Context>
FMT_CONSTEXPR typename Context::format_arg get_arg(Context& ctx, unsigned id) {
auto arg = ctx.arg(id);
if (!arg) ctx.on_error("argument index out of range");
return arg;
}

// The standard format specifier handler with checking.
template <typename ParseContext, typename Context>
class specs_handler : public specs_setter<typename Context::char_type> {
Expand Down Expand Up @@ -2274,10 +2264,7 @@ void handle_dynamic_spec(Spec& value, arg_ref<typename Context::char_type> ref,

/** The default argument formatter. */
template <typename Range>
class arg_formatter
: public internal::function<
typename internal::arg_formatter_base<Range>::iterator>,
public internal::arg_formatter_base<Range> {
class arg_formatter : public internal::arg_formatter_base<Range> {
private:
typedef typename Range::value_type char_type;
typedef internal::arg_formatter_base<Range> base;
Expand Down Expand Up @@ -3464,7 +3451,7 @@ template <typename It> class is_output_iterator {
template <typename U> static const char& test(...);

typedef decltype(test<It>(typename it_category<It>::type{})) type;
typedef typename std::remove_reference<type>::type result;
typedef remove_reference_t<type> result;

public:
static const bool value = !std::is_const<result>::value;
Expand All @@ -3485,8 +3472,9 @@ struct format_args_t {
};

template <typename S, typename OutputIt, typename... Args,
FMT_ENABLE_IF(internal::is_output_iterator<OutputIt>::value &&
!is_contiguous_back_insert_iterator<OutputIt>::value)>
FMT_ENABLE_IF(
internal::is_output_iterator<OutputIt>::value &&
!internal::is_contiguous_back_insert_iterator<OutputIt>::value)>
inline OutputIt vformat_to(
OutputIt out, const S& format_str,
typename format_args_t<OutputIt, char_t<S>>::type args) {
Expand Down
18 changes: 11 additions & 7 deletions include/fmt/prepare.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ class prepared_format {
std::basic_string<char_type> format(const Args&... args) const {
basic_memory_buffer<char_type> buffer;
typedef back_insert_range<internal::buffer<char_type>> range;
this->vformat_to(range(buffer), make_args_checked(format_, args...));
this->vformat_to(range(buffer), basic_format_args<context>{
make_args_checked(format_, args...)});
return to_string(buffer);
}

Expand All @@ -226,7 +227,8 @@ class prepared_format {
std::back_insert_iterator<Container> out, const Args&... args) const {
internal::container_buffer<Container> buffer(internal::get_container(out));
typedef back_insert_range<internal::buffer<char_type>> range;
this->vformat_to(range(buffer), make_args_checked(format_, args...));
this->vformat_to(range(buffer), basic_format_args<context>{
make_args_checked(format_, args...)});
return out;
}

Expand All @@ -242,18 +244,20 @@ class prepared_format {
inline typename buffer_context<char_type>::iterator format_to(
basic_memory_buffer<char_type, SIZE>& buf, const Args&... args) const {
typedef back_insert_range<internal::buffer<char_type>> range;
return this->vformat_to(range(buf), make_args_checked(format_, args...));
return this->vformat_to(
range(buf),
basic_format_args<context>{make_args_checked(format_, args...)});
}

private:
typedef buffer_context<char_type> context;

template <typename Range>
typename context::iterator vformat_to(Range out,
basic_format_args<context> args) const {
template <typename Range, typename Context>
auto vformat_to(Range out, basic_format_args<Context> args) const ->
typename Context::iterator {
const auto format_view = internal::to_string_view(format_);
basic_parse_context<char_type> parse_ctx(format_view);
context ctx(out.begin(), args);
Context ctx(out.begin(), args);

const auto& parts = parts_provider_.parts();
for (auto part_it = parts.begin(); part_it != parts.end(); ++part_it) {
Expand Down
5 changes: 1 addition & 4 deletions include/fmt/printf.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,7 @@ template <typename OutputIt, typename Char> class basic_printf_context;
\endrst
*/
template <typename Range>
class printf_arg_formatter
: public internal::function<
typename internal::arg_formatter_base<Range>::iterator>,
public internal::arg_formatter_base<Range> {
class printf_arg_formatter : public internal::arg_formatter_base<Range> {
public:
typedef decltype(std::declval<Range>().begin()) iterator;

Expand Down
2 changes: 1 addition & 1 deletion test/format-impl-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ TEST(UtilTest, CountDigits) {
TEST(UtilTest, WriteUIntPtr) {
fmt::memory_buffer buf;
fmt::writer writer(buf);
writer.write_pointer(fmt::internal::bit_cast<fmt::internal::uintptr_t>(
writer.write_pointer(fmt::internal::bit_cast<fmt::internal::uintptr>(
reinterpret_cast<void*>(0xface)),
nullptr);
EXPECT_EQ("0xface", to_string(buf));
Expand Down
Loading

0 comments on commit 90cab5a

Please sign in to comment.