This commit is contained in:
Remotion 2018-05-21 13:10:15 +02:00
commit 48415bc740
15 changed files with 167 additions and 114 deletions

View File

@ -95,8 +95,8 @@ function(add_headers VAR)
endfunction() endfunction()
# Define the fmt library, its includes and the needed defines. # Define the fmt library, its includes and the needed defines.
add_headers(FMT_HEADERS core.h format.h format-inl.h locale.h ostream.h printf.h add_headers(FMT_HEADERS core.h format.h format-inl.h ostream.h printf.h time.h
time.h ranges.h) ranges.h)
set(FMT_SOURCES src/format.cc) set(FMT_SOURCES src/format.cc)
if (HAVE_OPEN) if (HAVE_OPEN)
add_headers(FMT_HEADERS posix.h) add_headers(FMT_HEADERS posix.h)

View File

@ -20,6 +20,7 @@
.. code:: c++ .. code:: c++
#include <fmt/format.h> #include <fmt/format.h>
std::string s = format(fmt("{:d}"), "foo"); std::string s = format(fmt("{:d}"), "foo");
gives a compile-time error because ``d`` is an invalid specifier for strings gives a compile-time error because ``d`` is an invalid specifier for strings
@ -133,7 +134,9 @@
vreport_error(format, fmt::make_format_args(args...)); vreport_error(format, fmt::make_format_args(args...));
} }
* Added the ``make_printf_args`` function for capturing ``printf`` arguments. * Added the ``make_printf_args`` function for capturing ``printf`` arguments (
`#687 <https://github.com/fmtlib/fmt/issues/687>`_,
`#694 <https://github.com/fmtlib/fmt/pull/694>`_).
Thanks `@Kronuz (Germán Méndez Bravo) <https://github.com/Kronuz>`_. Thanks `@Kronuz (Germán Méndez Bravo) <https://github.com/Kronuz>`_.
* Added prefix ``v`` to non-variadic functions taking ``format_args`` to * Added prefix ``v`` to non-variadic functions taking ``format_args`` to
@ -146,6 +149,34 @@
template <typename... Args> template <typename... Args>
std::string format(string_view format_str, const Args & ... args); std::string format(string_view format_str, const Args & ... args);
* Added experimental support for formatting ranges, containers and tuple-like
types in ``fmt/ranges.h`` (`#735 <https://github.com/fmtlib/fmt/pull/735>`_):
.. code:: c++
#include <fmt/ranges.h>
std::vector<int> v = {1, 2, 3};
fmt::print("{}", v); // prints {1, 2, 3}
Thanks `@Remotion (Remo) <https://github.com/Remotion>`_.
* Implemented ``wchar_t`` date and time formatting
(`#712 <https://github.com/fmtlib/fmt/pull/712>`_):
.. code:: c++
#include <fmt/time.h>
std::time_t t = std::time(nullptr);
auto s = fmt::format(L"The date is {:%Y-%m-%d}.", *std::localtime(&t));
Thanks `@DanielaE (Daniela Engert) <https://github.com/DanielaE>`_.
* Provided more wide string overloads
(`#724 <https://github.com/fmtlib/fmt/pull/724>`_).
Thanks `@DanielaE (Daniela Engert) <https://github.com/DanielaE>`_.
* Switched from a custom null-terminated string view class to ``string_view`` * Switched from a custom null-terminated string view class to ``string_view``
in the format API and provided ``fmt::string_view`` which implements a subset in the format API and provided ``fmt::string_view`` which implements a subset
of ``std::string_view`` API for pre-C++17 systems. of ``std::string_view`` API for pre-C++17 systems.
@ -188,6 +219,8 @@
* Implemented more efficient handling of large number of format arguments. * Implemented more efficient handling of large number of format arguments.
* Introduced an inline namespace for symbol versioning.
* Added debug postfix ``d`` to the `fmt`` library name * Added debug postfix ``d`` to the `fmt`` library name
(`#636 <https://github.com/fmtlib/fmt/issues/636>`_). (`#636 <https://github.com/fmtlib/fmt/issues/636>`_).
@ -229,12 +262,21 @@
`#656 <https://github.com/fmtlib/fmt/pull/656>`_, `#656 <https://github.com/fmtlib/fmt/pull/656>`_,
`#679 <https://github.com/fmtlib/fmt/pull/679>`_, `#679 <https://github.com/fmtlib/fmt/pull/679>`_,
`#681 <https://github.com/fmtlib/fmt/pull/681>`_, `#681 <https://github.com/fmtlib/fmt/pull/681>`_,
`#705 <https://github.com/fmtlib/fmt/pull/705>`_). `#705 <https://github.com/fmtlib/fmt/pull/705>`_,
`#715 <https://github.com/fmtlib/fmt/issues/715>`_,
`#717 <https://github.com/fmtlib/fmt/pull/717>`_,
`#720 <https://github.com/fmtlib/fmt/pull/720>`_,
`#723 <https://github.com/fmtlib/fmt/pull/723>`_,
`#726 <https://github.com/fmtlib/fmt/pull/726>`_,
`#730 <https://github.com/fmtlib/fmt/pull/730>`_,
`#739 <https://github.com/fmtlib/fmt/pull/739>`_).
Thanks `@peterbell10 <https://github.com/peterbell10>`_, Thanks `@peterbell10 <https://github.com/peterbell10>`_,
`@LarsGullik <https://github.com/LarsGullik>`_, `@LarsGullik <https://github.com/LarsGullik>`_,
`@foonathan (Jonathan Müller) <https://github.com/foonathan>`_, `@foonathan (Jonathan Müller) <https://github.com/foonathan>`_,
`@eliaskosunen (Elias Kosunen) <https://github.com/eliaskosunen>`_, and `@eliaskosunen (Elias Kosunen) <https://github.com/eliaskosunen>`_,
`@christianparpart (Christian Parpart) <https://github.com/christianparpart>`_. `@christianparpart (Christian Parpart) <https://github.com/christianparpart>`_,
`@DanielaE (Daniela Engert) <https://github.com/DanielaE>`_,
and `@mwinterb <https://github.com/mwinterb>`_.
* Worked around an MSVC bug and fixed several warnings * Worked around an MSVC bug and fixed several warnings
(`#653 <https://github.com/fmtlib/fmt/pull/653>`_). (`#653 <https://github.com/fmtlib/fmt/pull/653>`_).
@ -260,10 +302,17 @@
(`#660 <https://github.com/fmtlib/fmt/pull/660>`_). (`#660 <https://github.com/fmtlib/fmt/pull/660>`_).
Thanks `@hubslave <https://github.com/hubslave>`_. Thanks `@hubslave <https://github.com/hubslave>`_.
* Fixed compilation on FreeBSD 12
(`#732 <https://github.com/fmtlib/fmt/pull/732>`_).
Thanks `@dankm <https://github.com/dankm>`_.
* Fixed compilation when there is a mismatch between ``-std`` options between * Fixed compilation when there is a mismatch between ``-std`` options between
the library and user code the library and user code
(`#664 <https://github.com/fmtlib/fmt/issues/664>`_). (`#664 <https://github.com/fmtlib/fmt/issues/664>`_).
* Fixed compilation with GCC 7 and ``-std=c++11``
(`#734 <https://github.com/fmtlib/fmt/issues/734>`_).
* Improved generated binary code on GCC 7 and older * Improved generated binary code on GCC 7 and older
(`#668 <https://github.com/fmtlib/fmt/issues/668>`_). (`#668 <https://github.com/fmtlib/fmt/issues/668>`_).
@ -286,6 +335,17 @@
* Fixed compile checks for mixing narrow and wide strings * Fixed compile checks for mixing narrow and wide strings
(`#690 <https://github.com/fmtlib/fmt/issues/690>`_). (`#690 <https://github.com/fmtlib/fmt/issues/690>`_).
* Disabled unsafe implicit conversion to ``std::string``
(`#729 <https://github.com/fmtlib/fmt/issues/729>`_).
* Fixed handling of reused format specs (as in ``fmt::join``) for pointers
(`#725 <https://github.com/fmtlib/fmt/pull/725>`_).
Thanks `@mwinterb <https://github.com/mwinterb>`_.
* Fixed installation of ``fmt/ranges.h``
(`#738 <https://github.com/fmtlib/fmt/pull/738>`_).
Thanks `@sv1990 <https://github.com/sv1990>`_.
4.1.0 - 2017-12-20 4.1.0 - 2017-12-20
------------------ ------------------

View File

@ -164,6 +164,10 @@ Utilities
System errors System errors
------------- -------------
fmt does not use ``errno`` to communicate errors to the user, but it may call
system functions which set ``errno``. Users should not make any assumptions about
the value of ``errno`` being preserved by library functions.
.. doxygenclass:: fmt::system_error .. doxygenclass:: fmt::system_error
:members: :members:

View File

@ -2,8 +2,7 @@ Overview
======== ========
**fmt** (formerly cppformat) is an open-source formatting library. **fmt** (formerly cppformat) is an open-source formatting library.
It can be used as a safe alternative to printf or as a fast It can be used as a fast and safe alternative to printf and IOStreams.
alternative to C++ IOStreams.
.. raw:: html .. raw:: html
@ -30,9 +29,9 @@ in Python:
.. code:: c++ .. code:: c++
fmt::format("The answer is {}", 42); fmt::format("The answer is {}.", 42);
The ``fmt::format`` function returns a string "The answer is 42". You can use The ``fmt::format`` function returns a string "The answer is 42.". You can use
``fmt::memory_buffer`` to avoid constructing ``std::string``: ``fmt::memory_buffer`` to avoid constructing ``std::string``:
.. code:: c++ .. code:: c++
@ -94,19 +93,25 @@ Safety
------ ------
The library is fully type safe, automatic memory management prevents buffer The library is fully type safe, automatic memory management prevents buffer
overflow, errors in format strings are reported using exceptions. For example, overflow, errors in format strings are reported using exceptions or at compile
the code tim. For example, the code
.. code:: c++ .. code:: c++
fmt::format("The answer is {:d}", "forty-two"); fmt::format("The answer is {:d}", "forty-two");
throws a ``format_error`` exception with description throws a ``format_error`` exception with description "unknown format code 'd' for
"unknown format code 'd' for string", because the argument string", because the argument ``"forty-two"`` is a string while the format code
``"forty-two"`` is a string while the format code ``d`` ``d`` only applies to integers, while
only applies to integers.
Where possible, errors are caught at compile time. For example, the code .. code:: c++
format(fmt("The answer is {:d}"), "forty-two");
reports a compile-time error for the same reason on compilers that support
relaxed ``constexpr``.
The following code
.. code:: c++ .. code:: c++
@ -124,16 +129,10 @@ its numeric value being written to the stream (i.e. 1070 instead of letter 'ю'
which is represented by ``L'\x42e'`` if we use Unicode) which is rarely what is which is represented by ``L'\x42e'`` if we use Unicode) which is rarely what is
needed. needed.
Note that fmt does not use the value of the ``errno`` global to communicate
errors to the user, but it may call system functions which set ``errno``. Since
fmt does not attempt to preserve the value of ``errno``, users should not make
any assumptions about it and always set it to ``0`` before making any system
calls that convey error information via ``errno``.
Compact binary code Compact binary code
------------------- -------------------
Each call to a formatting function results in a compact binary code. For example The library is designed to produce compact per-call compiled code. For example
(`godbolt <https://godbolt.org/g/TZU4KF>`_), (`godbolt <https://godbolt.org/g/TZU4KF>`_),
.. code:: c++ .. code:: c++
@ -167,33 +166,19 @@ compiles to just
Portability Portability
----------- -----------
The library is highly portable. Here is an incomplete list of operating systems The library is highly portable and relies only on a small set of C++11 features:
and compilers where it has been tested and known to work:
* 64-bit (amd64) GNU/Linux with GCC 4.4.3, * variadic templates
`4.6.3 <https://travis-ci.org/fmtlib/fmt>`_, 4.7.2, 4.8.1, and Intel C++ * type traits
Compiler (ICC) 14.0.2 * rvalue references
* decltype
* trailing return types
* deleted functions
* 32-bit (i386) GNU/Linux with GCC 4.4.3, 4.6.3 These are available since GCC 4.4, Clang 2.9 and MSVC 18.0 (2013). For older
compilers use fmt `version 4.x
* Mac OS X with GCC 4.2.1 and Clang 4.2, 5.1.0 <https://github.com/fmtlib/fmt/releases/tag/4.1.0>`_ which continues to be
maintained and only requires C++98.
* 64-bit Windows with Visual C++ 2010, 2013 and
`2015 <https://ci.appveyor.com/project/vitaut/fmt>`_
* 32-bit Windows with Visual C++ 2010
Although the library uses C++11 features when available, it also works with
older compilers and standard library implementations. The only thing to keep in
mind for C++98 portability:
* Variadic templates: minimum GCC 4.4, Clang 2.9 or VS2013. This feature allows
the Format API to accept an unlimited number of arguments. With older
compilers the maximum is 15.
* User-defined literals: minimum GCC 4.7, Clang 3.1 or VS2015. The suffixes
``_format`` and ``_a`` are functionally equivalent to the functions
``fmt::format`` and ``fmt::arg``.
The output of all formatting functions is consistent across platforms. In The output of all formatting functions is consistent across platforms. In
particular, formatting a floating-point infinity always gives ``inf`` while the particular, formatting a floating-point infinity always gives ``inf`` while the
@ -211,7 +196,7 @@ Ease of Use
----------- -----------
fmt has a small self-contained code base with the core library consisting of fmt has a small self-contained code base with the core library consisting of
a single header file and a single source file and no external dependencies. just three header files and no external dependencies.
A permissive BSD `license <https://github.com/fmtlib/fmt#license>`_ allows A permissive BSD `license <https://github.com/fmtlib/fmt#license>`_ allows
using the library both in open-source and commercial projects. using the library both in open-source and commercial projects.

View File

@ -616,7 +616,8 @@ FMT_MAKE_VALUE(pointer_type, std::nullptr_t, const void*)
// formatting of "[const] volatile char *" which is printed as bool by // formatting of "[const] volatile char *" which is printed as bool by
// iostreams. // iostreams.
template <typename C, typename T> template <typename C, typename T>
typed_value<C, pointer_type> make_value(const T *) { typename std::enable_if<!std::is_same<T, typename C::char_type>::value>::type
make_value(const T *) {
static_assert(!sizeof(T), "formatting of non-void pointers is disallowed"); static_assert(!sizeof(T), "formatting of non-void pointers is disallowed");
} }
@ -1240,12 +1241,12 @@ inline std::string format(string_view format_str, const Args & ... args) {
// This should be just // This should be just
// return vformat(format_str, make_format_args(args...)); // return vformat(format_str, make_format_args(args...));
// but gcc has trouble optimizing the latter, so break it down. // but gcc has trouble optimizing the latter, so break it down.
format_arg_store<format_context, Args...> as(args...); format_arg_store<format_context, Args...> as{args...};
return vformat(format_str, as); return vformat(format_str, as);
} }
template <typename... Args> template <typename... Args>
inline std::wstring format(wstring_view format_str, const Args & ... args) { inline std::wstring format(wstring_view format_str, const Args & ... args) {
format_arg_store<wformat_context, Args...> as(args...); format_arg_store<wformat_context, Args...> as{args...};
return vformat(format_str, as); return vformat(format_str, as);
} }
@ -1286,7 +1287,7 @@ FMT_API void vprint(wstring_view format_str, wformat_args args);
*/ */
template <typename... Args> template <typename... Args>
inline void print(string_view format_str, const Args & ... args) { inline void print(string_view format_str, const Args & ... args) {
format_arg_store<format_context, Args...> as(args...); format_arg_store<format_context, Args...> as{args...};
vprint(format_str, as); vprint(format_str, as);
} }

View File

@ -9,7 +9,6 @@
#define FMT_FORMAT_INL_H_ #define FMT_FORMAT_INL_H_
#include "format.h" #include "format.h"
#include "locale.h"
#include <string.h> #include <string.h>
@ -19,6 +18,7 @@
#include <cmath> #include <cmath>
#include <cstdarg> #include <cstdarg>
#include <cstddef> // for std::ptrdiff_t #include <cstddef> // for std::ptrdiff_t
#include <locale>
#if defined(_WIN32) && defined(__MINGW32__) #if defined(_WIN32) && defined(__MINGW32__)
# include <cstring> # include <cstring>
@ -205,6 +205,15 @@ void report_error(FormatFunc func, int error_code,
} }
} // namespace } // namespace
class locale {
private:
std::locale locale_;
public:
explicit locale(std::locale loc = std::locale()) : locale_(loc) {}
std::locale get() { return locale_; }
};
template <typename Char> template <typename Char>
FMT_FUNC Char internal::thousands_sep(locale_provider *lp) { FMT_FUNC Char internal::thousands_sep(locale_provider *lp) {
std::locale loc = lp ? lp->locale().get() : std::locale(); std::locale loc = lp ? lp->locale().get() : std::locale();

View File

@ -304,7 +304,7 @@ fp operator*(fp x, fp y);
// Compute k such that its cached power c_k = c_k.f * pow(2, c_k.e) satisfies // Compute k such that its cached power c_k = c_k.f * pow(2, c_k.e) satisfies
// min_exponent <= c_k.e + e <= min_exponent + 3. // min_exponent <= c_k.e + e <= min_exponent + 3.
inline int compute_cached_power_index(int e, int min_exponent) { inline int compute_cached_power_index(int e, int min_exponent) {
constexpr double one_over_log2_10 = 0.30102999566398114; // 1 / log2(10) const double one_over_log2_10 = 0.30102999566398114; // 1 / log2(10)
return static_cast<int>(std::ceil((min_exponent - e + 63) * one_over_log2_10)); return static_cast<int>(std::ceil((min_exponent - e + 63) * one_over_log2_10));
} }
@ -2236,7 +2236,9 @@ void handle_dynamic_spec(
/** The default argument formatter. */ /** The default argument formatter. */
template <typename Range> template <typename Range>
class arg_formatter: class arg_formatter:
public internal::function<void>, public internal::arg_formatter_base<Range> { public internal::function<
typename internal::arg_formatter_base<Range>::iterator>,
public internal::arg_formatter_base<Range> {
private: private:
typedef typename Range::value_type char_type; typedef typename Range::value_type char_type;
typedef internal::arg_formatter_base<Range> base; typedef internal::arg_formatter_base<Range> base;

View File

@ -1,25 +0,0 @@
// Formatting library for C++ - locale support
//
// Copyright (c) 2012 - 2016, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_LOCALE_H_
#define FMT_LOCALE_H_
#include "format.h"
#include <locale>
FMT_BEGIN_NAMESPACE
class locale {
private:
std::locale locale_;
public:
explicit locale(std::locale loc = std::locale()) : locale_(loc) {}
std::locale get() { return locale_; }
};
FMT_END_NAMESPACE
#endif // FMT_LOCALE_

View File

@ -140,13 +140,13 @@ inline void vprint(std::basic_ostream<Char> &os,
template <typename... Args> template <typename... Args>
inline void print(std::ostream &os, string_view format_str, inline void print(std::ostream &os, string_view format_str,
const Args & ... args) { const Args & ... args) {
vprint(os, format_str, make_format_args<format_context>(args...)); vprint<char>(os, format_str, make_format_args<format_context>(args...));
} }
template <typename... Args> template <typename... Args>
inline void print(std::wostream &os, wstring_view format_str, inline void print(std::wostream &os, wstring_view format_str,
const Args & ... args) { const Args & ... args) {
vprint(os, format_str, make_format_args<wformat_context>(args...)); vprint<wchar_t>(os, format_str, make_format_args<wformat_context>(args...));
} }
FMT_END_NAMESPACE FMT_END_NAMESPACE

View File

@ -215,7 +215,9 @@ class basic_printf_context;
*/ */
template <typename Range> template <typename Range>
class printf_arg_formatter: class printf_arg_formatter:
public internal::function<void>, public internal::arg_formatter_base<Range> { public internal::function<
typename internal::arg_formatter_base<Range>::iterator>,
public internal::arg_formatter_base<Range> {
private: private:
typedef typename Range::value_type char_type; typedef typename Range::value_type char_type;
typedef decltype(internal::declval<Range>().begin()) iterator; typedef decltype(internal::declval<Range>().begin()) iterator;
@ -627,7 +629,7 @@ template <typename... Args>
inline int fprintf(std::FILE *f, string_view format_str, const Args & ... args) { inline int fprintf(std::FILE *f, string_view format_str, const Args & ... args) {
auto vargs = make_format_args< auto vargs = make_format_args<
typename printf_context<internal::buffer>::type>(args...); typename printf_context<internal::buffer>::type>(args...);
return vfprintf(f, format_str, vargs); return vfprintf<char>(f, format_str, vargs);
} }
template <typename... Args> template <typename... Args>

View File

@ -34,18 +34,20 @@ template <typename Char, typename Enable = void>
struct formatting_range : formatting_base<Char> { struct formatting_range : formatting_base<Char> {
static FMT_CONSTEXPR_DECL const std::size_t range_length_limit = static FMT_CONSTEXPR_DECL const std::size_t range_length_limit =
FMT_RANGE_OUTPUT_LENGTH_LIMIT; // output only up to N items from the range. FMT_RANGE_OUTPUT_LENGTH_LIMIT; // output only up to N items from the range.
Char prefix = '{'; Char prefix;
Char delimiter = ','; Char delimiter;
Char postfix = '}'; Char postfix;
formatting_range() : prefix('{'), delimiter(','), postfix('}') {}
static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true; static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false; static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
}; };
template <typename Char, typename Enable = void> template <typename Char, typename Enable = void>
struct formatting_tuple : formatting_base<Char> { struct formatting_tuple : formatting_base<Char> {
Char prefix = '('; Char prefix;
Char delimiter = ','; Char delimiter;
Char postfix = ')'; Char postfix;
formatting_tuple() : prefix('('), delimiter(','), postfix(')') {}
static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true; static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false; static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
}; };
@ -54,9 +56,8 @@ namespace internal {
template <typename RangeT, typename OutputIterator> template <typename RangeT, typename OutputIterator>
void copy(const RangeT &range, OutputIterator out) { void copy(const RangeT &range, OutputIterator out) {
for (const auto &it : range) { for (auto it = range.begin(), end = range.end(); it != end; ++it)
*out++ = it; *out++ = *it;
}
} }
template <typename OutputIterator> template <typename OutputIterator>
@ -83,7 +84,7 @@ class is_like_std_string {
public: public:
static FMT_CONSTEXPR_DECL const bool value = static FMT_CONSTEXPR_DECL const bool value =
!std::is_void<decltype(check<T>(nullptr))>::value; !std::is_void<decltype(check<T>(FMT_NULL))>::value;
}; };
template <typename... Ts> template <typename... Ts>
@ -95,8 +96,8 @@ struct is_range_ : std::false_type {};
template <typename T> template <typename T>
struct is_range_<T,typename std::conditional< struct is_range_<T,typename std::conditional<
false, false,
conditional_helper<decltype(std::declval<T>().begin()), conditional_helper<decltype(internal::declval<T>().begin()),
decltype(std::declval<T>().end())>, decltype(internal::declval<T>().end())>,
void>::type> : std::true_type {}; void>::type> : std::true_type {};
template <typename T> template <typename T>
@ -111,13 +112,13 @@ class is_tuple_like_ {
template <typename U> template <typename U>
static auto check(U *p) -> static auto check(U *p) ->
decltype(std::tuple_size<U>::value, decltype(std::tuple_size<U>::value,
std::declval<typename std::tuple_element<0, U>::type>(), int()); internal::declval<typename std::tuple_element<0, U>::type>(), int());
template <typename> template <typename>
static void check(...); static void check(...);
public: public:
static FMT_CONSTEXPR_DECL const bool value = static FMT_CONSTEXPR_DECL const bool value =
!std::is_void<decltype(check<T>(nullptr))>::value; !std::is_void<decltype(check<T>(FMT_NULL))>::value;
}; };
template <typename T> template <typename T>
@ -125,7 +126,16 @@ struct is_tuple_like {
static FMT_CONSTEXPR_DECL const bool value = static FMT_CONSTEXPR_DECL const bool value =
is_tuple_like_<T>::value && !is_range_<T>::value; is_tuple_like_<T>::value && !is_range_<T>::value;
}; };
} // namespace internal
#if FMT_HAS_FEATURE(__cpp_lib_integer_sequence)
# define FMT_USE_INTEGER_SEQUENCE 1
#else
# define FMT_USE_INTEGER_SEQUENCE 0
#endif
#if FMT_USE_INTEGER_SEQUENCE
namespace internal {
template <size_t... Is, class Tuple, class F> template <size_t... Is, class Tuple, class F>
void for_each(std::index_sequence<Is...>, Tuple &&tup, F &&f) noexcept { void for_each(std::index_sequence<Is...>, Tuple &&tup, F &&f) noexcept {
using std::get; using std::get;
@ -183,6 +193,7 @@ struct formatter<TupleT, Char,
return ctx.out(); return ctx.out();
} }
}; };
#endif // FMT_USE_INTEGER_SEQUENCE
template <typename RangeT, typename Char> template <typename RangeT, typename Char>
struct formatter< RangeT, Char, struct formatter< RangeT, Char,
@ -196,11 +207,12 @@ struct formatter< RangeT, Char,
} }
template <typename FormatContext> template <typename FormatContext>
auto format(const RangeT &values, FormatContext &ctx) -> decltype(ctx.out()) { typename FormatContext::iterator format(
const RangeT &values, FormatContext &ctx) {
auto out = ctx.out(); auto out = ctx.out();
internal::copy(formatting.prefix, out); internal::copy(formatting.prefix, out);
std::size_t i = 0; std::size_t i = 0;
for (const auto &it : values) { for (auto it = values.begin(), end = values.end(); it != end; ++it) {
if (i > 0) { if (i > 0) {
if (formatting.add_prepostfix_space) { if (formatting.add_prepostfix_space) {
*out++ = ' '; *out++ = ' ';
@ -208,9 +220,9 @@ struct formatter< RangeT, Char,
internal::copy(formatting.delimiter, out); internal::copy(formatting.delimiter, out);
} }
if (formatting.add_delimiter_spaces && i > 0) { if (formatting.add_delimiter_spaces && i > 0) {
format_to(out, " {}", it); format_to(out, " {}", *it);
} else { } else {
format_to(out, "{}", it); format_to(out, "{}", *it);
} }
if (++i > formatting.range_length_limit) { if (++i > formatting.range_length_limit) {
format_to(out, " ... <other elements>"); format_to(out, " ... <other elements>");

View File

@ -223,9 +223,9 @@ buffered_file file::fdopen(const char *mode) {
if (!f) if (!f)
FMT_THROW(system_error(errno, FMT_THROW(system_error(errno,
"cannot associate stream with file descriptor")); "cannot associate stream with file descriptor"));
buffered_file file(f); buffered_file bf(f);
fd_ = -1; fd_ = -1;
return file; return bf;
} }
long getpagesize() { long getpagesize() {

View File

@ -1394,7 +1394,8 @@ TEST(FormatTest, FixedEnum) {
typedef fmt::back_insert_range<fmt::internal::buffer> buffer_range; typedef fmt::back_insert_range<fmt::internal::buffer> buffer_range;
class mock_arg_formatter: class mock_arg_formatter:
public fmt::internal::function<void>, public fmt::internal::function<
fmt::internal::arg_formatter_base<buffer_range>::iterator>,
public fmt::internal::arg_formatter_base<buffer_range> { public fmt::internal::arg_formatter_base<buffer_range> {
private: private:
MOCK_METHOD1(call, void (int value)); MOCK_METHOD1(call, void (int value));

View File

@ -30,6 +30,7 @@ TEST(RangesTest, FormatVector2) {
EXPECT_EQ("{{1, 2}, {3, 5}, {7, 11}}", ivf); EXPECT_EQ("{{1, 2}, {3, 5}, {7, 11}}", ivf);
} }
#if FMT_USE_INTEGER_SEQUENCE
TEST(RangesTest, FormatMap) { TEST(RangesTest, FormatMap) {
std::map<std::string, int32_t> simap{{"one", 1}, {"two", 2}}; std::map<std::string, int32_t> simap{{"one", 1}, {"two", 2}};
EXPECT_EQ("{(one, 1), (two, 2)}", fmt::format("{}", simap)); EXPECT_EQ("{(one, 1), (two, 2)}", fmt::format("{}", simap));
@ -46,7 +47,7 @@ TEST(RangesTest, FormatTuple) {
EXPECT_EQ("(42, 3.14159, this is tuple)", fmt::format("{}", tu1)); EXPECT_EQ("(42, 3.14159, this is tuple)", fmt::format("{}", tu1));
} }
/// check if 'if constexpr' is supported. /// Check if 'if constexpr' is supported.
#if (__cplusplus > 201402L) || \ #if (__cplusplus > 201402L) || \
(defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910) (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)
@ -86,3 +87,4 @@ TEST(RangesTest, FormatStruct) {
#endif // (__cplusplus > 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG > #endif // (__cplusplus > 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >
// 201402L && _MSC_VER >= 1910) // 201402L && _MSC_VER >= 1910)
#endif // FMT_USE_INTEGER_SEQUENCE

View File

@ -17,7 +17,6 @@
# include <type_traits> # include <type_traits>
#endif #endif
#include "fmt/locale.h"
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "gtest-extra.h" #include "gtest-extra.h"
#include "mock-allocator.h" #include "mock-allocator.h"
@ -397,13 +396,14 @@ TEST(FixedBufferTest, BufferOverflow) {
EXPECT_THROW_MSG(buffer.resize(11), std::runtime_error, "buffer overflow"); EXPECT_THROW_MSG(buffer.resize(11), std::runtime_error, "buffer overflow");
} }
struct uint32_pair {
uint32_t u[2];
};
TEST(UtilTest, BitCast) { TEST(UtilTest, BitCast) {
struct S { auto s = fmt::internal::bit_cast<uint32_pair>(uint64_t{42});
uint32_t u[2];
};
auto s = fmt::internal::bit_cast<S>(uint64_t(42));
EXPECT_EQ(fmt::internal::bit_cast<uint64_t>(s), 42u); EXPECT_EQ(fmt::internal::bit_cast<uint64_t>(s), 42u);
s = fmt::internal::bit_cast<S>(uint64_t(~0ull)); s = fmt::internal::bit_cast<uint32_pair>(uint64_t(~0ull));
EXPECT_EQ(fmt::internal::bit_cast<uint64_t>(s), ~0ull); EXPECT_EQ(fmt::internal::bit_cast<uint64_t>(s), ~0ull);
} }