Skip to content

Commit

Permalink
Merge branch 'fmtlib:master' into zig-pkg
Browse files Browse the repository at this point in the history
  • Loading branch information
kassane authored Apr 29, 2024
2 parents 46d6f8b + cf1f55f commit 27b975b
Show file tree
Hide file tree
Showing 11 changed files with 75 additions and 53 deletions.
11 changes: 9 additions & 2 deletions doc/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,14 @@ Base API
for ``char``/UTF-8 with C++20 compile-time checks. It has minimal include
dependencies for better compile times. This header is only beneficial when
using {fmt} as a library (the default) and not in the header-only mode.
It also provides ``formatter`` specializations for built-in and string types.
It also provides ``formatter`` specializations for the following types:

* ``int``, ``unsigned``, ``long long``, ``unsigned long long``
* ``float``, ``double``, ``long double``
* ``bool``
* ``char``
* ``const char*``, ``fmt::string_view``
* ``const void*``

The following functions use :ref:`format string syntax <syntax>`
similar to that of Python's `str.format
Expand Down Expand Up @@ -66,7 +73,7 @@ specified otherwise.

.. _format:

.. doxygenfunction:: format_to(OutputIt out, format_string<T...> fmt, T&&... args) -> OutputIt
.. doxygenfunction:: format_to(OutputIt&& out, format_string<T...> fmt, T&&... args) -> remove_cvref_t<OutputIt>
.. doxygenfunction:: format_to_n(OutputIt out, size_t n, format_string<T...> fmt, T&&... args) -> format_to_n_result<OutputIt>
.. doxygenfunction:: formatted_size(format_string<T...> fmt, T&&... args) -> size_t

Expand Down
22 changes: 11 additions & 11 deletions include/fmt/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ import std;
#elif defined(__NVCOMPILER)
# define FMT_USE_NONTYPE_TEMPLATE_ARGS 0
#elif FMT_GCC_VERSION >= 903 && FMT_CPLUSPLUS >= 201709L
# define FMT_USE_NONTYPE_TEMPLATE_ARGS 0
# define FMT_USE_NONTYPE_TEMPLATE_ARGS 1
#elif defined(__cpp_nontype_template_args) && \
__cpp_nontype_template_args >= 201911L
# define FMT_USE_NONTYPE_TEMPLATE_ARGS 1
Expand Down Expand Up @@ -371,17 +371,17 @@ template <typename T> constexpr auto const_check(T value) -> T { return value; }
FMT_NORETURN FMT_API void assert_fail(const char* file, int line,
const char* message);

#ifndef FMT_ASSERT
# ifdef NDEBUG
#if defined(FMT_ASSERT)
// Use the provided definition.
#elif defined(NDEBUG)
// FMT_ASSERT is not empty to avoid -Wempty-body.
# define FMT_ASSERT(condition, message) \
fmt::detail::ignore_unused((condition), (message))
# else
# define FMT_ASSERT(condition, message) \
((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \
? (void)0 \
: fmt::detail::assert_fail(__FILE__, __LINE__, (message)))
# endif
# define FMT_ASSERT(condition, message) \
fmt::detail::ignore_unused((condition), (message))
#else
# define FMT_ASSERT(condition, message) \
((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \
? (void)0 \
: fmt::detail::assert_fail(__FILE__, __LINE__, (message)))
#endif

#ifdef FMT_USE_INT128
Expand Down
5 changes: 4 additions & 1 deletion include/fmt/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -4017,11 +4017,14 @@ FMT_FORMAT_AS(unsigned short, unsigned);
FMT_FORMAT_AS(long, detail::long_type);
FMT_FORMAT_AS(unsigned long, detail::ulong_type);
FMT_FORMAT_AS(Char*, const Char*);
FMT_FORMAT_AS(std::basic_string<Char>, basic_string_view<Char>);
FMT_FORMAT_AS(std::nullptr_t, const void*);
FMT_FORMAT_AS(detail::std_string_view<Char>, basic_string_view<Char>);
FMT_FORMAT_AS(void*, const void*);

template <typename Char, typename Traits, typename Allocator>
class formatter<std::basic_string<Char, Traits, Allocator>, Char>
: public formatter<basic_string_view<Char>, Char> {};

template <typename Char, size_t N>
struct formatter<Char[N], Char> : formatter<basic_string_view<Char>, Char> {};

Expand Down
2 changes: 1 addition & 1 deletion include/fmt/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ class file_buffer final : public buffer<char> {

public:
FMT_API file_buffer(cstring_view path, const ostream_params& params);
FMT_API file_buffer(file_buffer&& other);
FMT_API file_buffer(file_buffer&& other) noexcept;
FMT_API ~file_buffer();

void flush() {
Expand Down
28 changes: 6 additions & 22 deletions include/fmt/ranges.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@ struct has_member_fn_begin_end_t<T, void_t<decltype(std::declval<T>().begin()),
decltype(std::declval<T>().end())>>
: std::true_type {};

// Member function overload
// Member function overloads.
template <typename T>
auto range_begin(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).begin());
template <typename T>
auto range_end(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).end());

// ADL overload. Only participates in overload resolution if member functions
// ADL overloads. Only participate in overload resolution if member functions
// are not found.
template <typename T>
auto range_begin(T&& rng)
Expand Down Expand Up @@ -619,22 +619,6 @@ auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {
return {begin, end, sep};
}

namespace detail {
// ADL helpers for fmt::join()
namespace adl {
using std::begin;
using std::end;

template <typename Range> auto adlbegin(Range& r) -> decltype(begin(r)) {
return begin(r);
}

template <typename Range> auto adlend(Range& r) -> decltype(end(r)) {
return end(r);
}
} // namespace adl
} // namespace detail

/**
\rst
Returns a view that formats `range` with elements separated by `sep`.
Expand All @@ -652,10 +636,10 @@ template <typename Range> auto adlend(Range& r) -> decltype(end(r)) {
\endrst
*/
template <typename Range>
auto join(Range&& range, string_view sep)
-> join_view<decltype(detail::adl::adlbegin(range)),
decltype(detail::adl::adlend(range))> {
return join(detail::adl::adlbegin(range), detail::adl::adlend(range), sep);
auto join(Range&& r, string_view sep)
-> join_view<decltype(detail::range_begin(r)),
decltype(detail::range_end(r))> {
return {detail::range_begin(r), detail::range_end(r), sep};
}

template <typename Char, typename... T> struct tuple_join_view : detail::view {
Expand Down
12 changes: 10 additions & 2 deletions include/fmt/xchar.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ auto format(wformat_string<T...> fmt, T&&... args) -> std::wstring {
return vformat(fmt::wstring_view(fmt), fmt::make_wformat_args(args...));
}

template <typename OutputIt, typename... T>
auto format_to(OutputIt out, wformat_string<T...> fmt, T&&... args)
-> OutputIt {
return vformat_to(out, fmt::wstring_view(fmt),
fmt::make_wformat_args(args...));
}

// Pass char_t as a default template parameter instead of using
// std::basic_string<char_t<S>> to reduce the symbol size.
template <typename S, typename... T,
Expand Down Expand Up @@ -186,8 +193,9 @@ auto vformat_to(OutputIt out, const S& format_str,

template <typename OutputIt, typename S, typename... T,
typename Char = detail::format_string_char_t<S>,
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
detail::is_exotic_char<Char>::value)>
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value &&
!std::is_same<Char, char>::value &&
!std::is_same<Char, wchar_t>::value)>
inline auto format_to(OutputIt out, const S& fmt, T&&... args) -> OutputIt {
return vformat_to(out, detail::to_string_view(fmt),
fmt::make_format_args<buffered_context<Char>>(args...));
Expand Down
2 changes: 1 addition & 1 deletion src/os.cc
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ file_buffer::file_buffer(cstring_view path, const ostream_params& params)
set(new char[params.buffer_size], params.buffer_size);
}

file_buffer::file_buffer(file_buffer&& other)
file_buffer::file_buffer(file_buffer&& other) noexcept
: buffer<char>(grow, other.data(), other.size(), other.capacity()),
file_(std::move(other.file_)) {
other.clear();
Expand Down
18 changes: 12 additions & 6 deletions test/format-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <iterator> // std::back_inserter
#include <list> // std::list
#include <mutex> // std::mutex
#include <string> // std::string
#include <thread> // std::thread
#include <type_traits> // std::is_default_constructible

Expand Down Expand Up @@ -2222,16 +2223,21 @@ template <typename Char, typename... T> void check_enabled_formatters() {
}

TEST(format_test, test_formatters_enabled) {
using custom_string =
std::basic_string<char, std::char_traits<char>, mock_allocator<char>>;
using custom_wstring = std::basic_string<wchar_t, std::char_traits<wchar_t>,
mock_allocator<wchar_t>>;

check_enabled_formatters<char, bool, char, signed char, unsigned char, short,
unsigned short, int, unsigned, long, unsigned long,
long long, unsigned long long, float, double,
long double, void*, const void*, char*, const char*,
std::string, std::nullptr_t>();
check_enabled_formatters<wchar_t, bool, wchar_t, signed char, unsigned char,
short, unsigned short, int, unsigned, long,
unsigned long, long long, unsigned long long, float,
double, long double, void*, const void*, wchar_t*,
const wchar_t*, std::wstring, std::nullptr_t>();
std::string, custom_string, std::nullptr_t>();
check_enabled_formatters<
wchar_t, bool, wchar_t, signed char, unsigned char, short, unsigned short,
int, unsigned, long, unsigned long, long long, unsigned long long, float,
double, long double, void*, const void*, wchar_t*, const wchar_t*,
std::wstring, custom_wstring, std::nullptr_t>();
}

TEST(format_int_test, data) {
Expand Down
10 changes: 10 additions & 0 deletions test/mock-allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ template <typename T> class mock_allocator {
using value_type = T;
using size_type = size_t;

using pointer = T*;
using const_pointer = const T*;
using reference = T&;
using const_reference = const T&;
using difference_type = ptrdiff_t;

template <typename U> struct rebind {
using other = mock_allocator<U>;
};

mock_allocator() {}
mock_allocator(const mock_allocator&) {}

Expand Down
12 changes: 5 additions & 7 deletions test/ranges-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -462,18 +462,16 @@ TEST(ranges_test, join_range) {
}

namespace adl {
struct vec : std::vector<int> {
using std::vector<int>::vector; // inherit all constructors
struct vec {
int n[2] = {42, 43};
};

// ADL-found begin() and end() skip the first and last element
auto begin(vec& v) -> typename vec::iterator { return v.begin() + 1; }
auto end(vec& v) -> typename vec::iterator { return v.end() - 1; }
auto begin(const vec& v) -> const int* { return v.n; }
auto end(const vec& v) -> const int* { return v.n + 2; }
}

TEST(ranges_test, format_join_adl_begin_end) {
auto v = adl::vec{41, 42, 43, 44};
EXPECT_EQ(fmt::format("{}", fmt::join(v, "/")), "42/43");
EXPECT_EQ(fmt::format("{}", fmt::join(adl::vec(), "/")), "42/43");
}

#endif // FMT_RANGES_TEST_ENABLE_JOIN
Expand Down
6 changes: 6 additions & 0 deletions test/xchar-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,12 @@ TEST(xchar_test, format_to) {
EXPECT_STREQ(buf.data(), L"42");
}

TEST(xchar_test, compile_time_string_format_to) {
std::wstring ws;
fmt::format_to(std::back_inserter(ws), FMT_STRING(L"{}"), 42);
EXPECT_EQ(L"42", ws);
}

TEST(xchar_test, vformat_to) {
int n = 42;
auto args = fmt::make_wformat_args(n);
Expand Down

0 comments on commit 27b975b

Please sign in to comment.