mirror of
https://github.com/fmtlib/fmt.git
synced 2025-04-16 05:42:19 +00:00
Disallow passing views as lvalues
This commit is contained in:
parent
f6f0415b83
commit
dd8cc8b0ba
@ -1260,10 +1260,20 @@ inline void check_format_string(const S&) {}
|
|||||||
template <typename..., typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>
|
template <typename..., typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>
|
||||||
void check_format_string(S);
|
void check_format_string(S);
|
||||||
|
|
||||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
struct view {};
|
||||||
inline format_arg_store<buffer_context<Char>, Args...> make_args_checked(
|
template <bool...> struct bool_pack;
|
||||||
const S& format_str, const Args&... args) {
|
template <bool... Args>
|
||||||
check_format_string<Args...>(format_str);
|
using all_true =
|
||||||
|
std::is_same<bool_pack<Args..., true>, bool_pack<true, Args...>>;
|
||||||
|
|
||||||
|
template <typename... Args, typename S, typename Char = char_t<S>>
|
||||||
|
inline format_arg_store<buffer_context<Char>, remove_reference_t<Args>...>
|
||||||
|
make_args_checked(const S& format_str,
|
||||||
|
const remove_reference_t<Args>&... args) {
|
||||||
|
static_assert(all_true<(!std::is_base_of<view, remove_reference_t<Args>>() ||
|
||||||
|
!std::is_reference<Args>())...>::value,
|
||||||
|
"passing views as lvalues is disallowed");
|
||||||
|
check_format_string<remove_reference_t<Args>...>(format_str);
|
||||||
return {args...};
|
return {args...};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1321,9 +1331,10 @@ template <typename Container, typename S, typename... Args,
|
|||||||
is_contiguous<Container>::value&& internal::is_string<S>::value)>
|
is_contiguous<Container>::value&& internal::is_string<S>::value)>
|
||||||
inline std::back_insert_iterator<Container> format_to(
|
inline std::back_insert_iterator<Container> format_to(
|
||||||
std::back_insert_iterator<Container> out, const S& format_str,
|
std::back_insert_iterator<Container> out, const S& format_str,
|
||||||
const Args&... args) {
|
Args&&... args) {
|
||||||
return vformat_to(out, to_string_view(format_str),
|
return vformat_to(
|
||||||
{internal::make_args_checked(format_str, args...)});
|
out, to_string_view(format_str),
|
||||||
|
{internal::make_args_checked<Args...>(format_str, args...)});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename Char = char_t<S>>
|
template <typename S, typename Char = char_t<S>>
|
||||||
@ -1345,10 +1356,10 @@ inline std::basic_string<Char> vformat(
|
|||||||
// Pass char_t as a default template parameter instead of using
|
// Pass char_t as a default template parameter instead of using
|
||||||
// std::basic_string<char_t<S>> to reduce the symbol size.
|
// std::basic_string<char_t<S>> to reduce the symbol size.
|
||||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||||
inline std::basic_string<Char> format(const S& format_str,
|
inline std::basic_string<Char> format(const S& format_str, Args&&... args) {
|
||||||
const Args&... args) {
|
return internal::vformat(
|
||||||
return internal::vformat(to_string_view(format_str),
|
to_string_view(format_str),
|
||||||
{internal::make_args_checked(format_str, args...)});
|
{internal::make_args_checked<Args...>(format_str, args...)});
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_API void vprint(std::FILE* f, string_view format_str, format_args args);
|
FMT_API void vprint(std::FILE* f, string_view format_str, format_args args);
|
||||||
@ -1367,9 +1378,9 @@ FMT_API void vprint(std::FILE* f, wstring_view format_str, wformat_args args);
|
|||||||
*/
|
*/
|
||||||
template <typename S, typename... Args,
|
template <typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(internal::is_string<S>::value)>
|
FMT_ENABLE_IF(internal::is_string<S>::value)>
|
||||||
inline void print(std::FILE* f, const S& format_str, const Args&... args) {
|
inline void print(std::FILE* f, const S& format_str, Args&&... args) {
|
||||||
vprint(f, to_string_view(format_str),
|
vprint(f, to_string_view(format_str),
|
||||||
internal::make_args_checked(format_str, args...));
|
internal::make_args_checked<Args...>(format_str, args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_API void vprint(string_view format_str, format_args args);
|
FMT_API void vprint(string_view format_str, format_args args);
|
||||||
@ -1386,9 +1397,9 @@ FMT_API void vprint(wstring_view format_str, wformat_args args);
|
|||||||
*/
|
*/
|
||||||
template <typename S, typename... Args,
|
template <typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(internal::is_string<S>::value)>
|
FMT_ENABLE_IF(internal::is_string<S>::value)>
|
||||||
inline void print(const S& format_str, const Args&... args) {
|
inline void print(const S& format_str, Args&&... args) {
|
||||||
vprint(to_string_view(format_str),
|
vprint(to_string_view(format_str),
|
||||||
internal::make_args_checked(format_str, args...));
|
internal::make_args_checked<Args...>(format_str, args...));
|
||||||
}
|
}
|
||||||
FMT_END_NAMESPACE
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
|
@ -3218,10 +3218,12 @@ template <typename T> inline const void* ptr(const std::shared_ptr<T>& p) {
|
|||||||
return p.get();
|
return p.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename It, typename Char> struct arg_join {
|
template <typename It, typename Char> struct arg_join : internal::view {
|
||||||
It begin;
|
It begin;
|
||||||
It end;
|
It end;
|
||||||
basic_string_view<Char> sep;
|
basic_string_view<Char> sep;
|
||||||
|
|
||||||
|
arg_join(It b, It e, basic_string_view<Char> s) : begin(b), end(e), sep(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename It, typename Char>
|
template <typename It, typename Char>
|
||||||
@ -3330,8 +3332,7 @@ inline typename buffer_context<Char>::iterator vformat_to(
|
|||||||
template <typename S, typename... Args, std::size_t SIZE = inline_buffer_size,
|
template <typename S, typename... Args, std::size_t SIZE = inline_buffer_size,
|
||||||
typename Char = enable_if_t<internal::is_string<S>::value, char_t<S>>>
|
typename Char = enable_if_t<internal::is_string<S>::value, char_t<S>>>
|
||||||
inline typename buffer_context<Char>::iterator format_to(
|
inline typename buffer_context<Char>::iterator format_to(
|
||||||
basic_memory_buffer<Char, SIZE>& buf, const S& format_str,
|
basic_memory_buffer<Char, SIZE>& buf, const S& format_str, Args&&... args) {
|
||||||
const Args&... args) {
|
|
||||||
internal::check_format_string<Args...>(format_str);
|
internal::check_format_string<Args...>(format_str);
|
||||||
using context = buffer_context<Char>;
|
using context = buffer_context<Char>;
|
||||||
return internal::vformat_to(buf, to_string_view(format_str),
|
return internal::vformat_to(buf, to_string_view(format_str),
|
||||||
@ -3367,8 +3368,7 @@ inline OutputIt vformat_to(OutputIt out, const S& format_str,
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
template <typename OutputIt, typename S, typename... Args>
|
template <typename OutputIt, typename S, typename... Args>
|
||||||
inline OutputIt format_to(OutputIt out, const S& format_str,
|
inline OutputIt format_to(OutputIt out, const S& format_str, Args&&... args) {
|
||||||
const Args&... args) {
|
|
||||||
static_assert(internal::is_output_iterator<OutputIt>::value &&
|
static_assert(internal::is_output_iterator<OutputIt>::value &&
|
||||||
internal::is_string<S>::value,
|
internal::is_string<S>::value,
|
||||||
"");
|
"");
|
||||||
|
@ -43,10 +43,10 @@ inline std::basic_string<Char> vformat(
|
|||||||
|
|
||||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||||
inline std::basic_string<Char> format(const std::locale& loc,
|
inline std::basic_string<Char> format(const std::locale& loc,
|
||||||
const S& format_str,
|
const S& format_str, Args&&... args) {
|
||||||
const Args&... args) {
|
return internal::vformat(
|
||||||
return internal::vformat(loc, to_string_view(format_str),
|
loc, to_string_view(format_str),
|
||||||
{internal::make_args_checked(format_str, args...)});
|
{internal::make_args_checked<Args...>(format_str, args...)});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename OutputIt, typename... Args,
|
template <typename S, typename OutputIt, typename... Args,
|
||||||
@ -64,7 +64,7 @@ template <typename OutputIt, typename S, typename... Args,
|
|||||||
FMT_ENABLE_IF(internal::is_output_iterator<OutputIt>::value&&
|
FMT_ENABLE_IF(internal::is_output_iterator<OutputIt>::value&&
|
||||||
internal::is_string<S>::value)>
|
internal::is_string<S>::value)>
|
||||||
inline OutputIt format_to(OutputIt out, const std::locale& loc,
|
inline OutputIt format_to(OutputIt out, const std::locale& loc,
|
||||||
const S& format_str, const Args&... args) {
|
const S& format_str, Args&&... args) {
|
||||||
internal::check_format_string<Args...>(format_str);
|
internal::check_format_string<Args...>(format_str);
|
||||||
using context = format_context_t<OutputIt, char_t<S>>;
|
using context = format_context_t<OutputIt, char_t<S>>;
|
||||||
format_arg_store<context, Args...> as{args...};
|
format_arg_store<context, Args...> as{args...};
|
||||||
|
@ -127,10 +127,9 @@ void vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str,
|
|||||||
*/
|
*/
|
||||||
template <typename S, typename... Args,
|
template <typename S, typename... Args,
|
||||||
typename Char = enable_if_t<internal::is_string<S>::value, char_t<S>>>
|
typename Char = enable_if_t<internal::is_string<S>::value, char_t<S>>>
|
||||||
void print(std::basic_ostream<Char>& os, const S& format_str,
|
void print(std::basic_ostream<Char>& os, const S& format_str, Args&&... args) {
|
||||||
const Args&... args) {
|
|
||||||
vprint(os, to_string_view(format_str),
|
vprint(os, to_string_view(format_str),
|
||||||
{internal::make_args_checked(format_str, args...)});
|
{internal::make_args_checked<Args...>(format_str, args...)});
|
||||||
}
|
}
|
||||||
FMT_END_NAMESPACE
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
|
@ -215,18 +215,20 @@ class prepared_format {
|
|||||||
std::basic_string<char_type> format(const Args&... args) const {
|
std::basic_string<char_type> format(const Args&... args) const {
|
||||||
basic_memory_buffer<char_type> buffer;
|
basic_memory_buffer<char_type> buffer;
|
||||||
using range = buffer_range<char_type>;
|
using range = buffer_range<char_type>;
|
||||||
this->vformat_to(range(buffer), basic_format_args<context>{
|
this->vformat_to(range(buffer),
|
||||||
make_args_checked(format_, args...)});
|
basic_format_args<context>{
|
||||||
|
make_args_checked<Args...>(format_, args...)});
|
||||||
return to_string(buffer);
|
return to_string(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
|
template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
|
||||||
inline std::back_insert_iterator<Container> format_to(
|
inline std::back_insert_iterator<Container> format_to(
|
||||||
std::back_insert_iterator<Container> out, const Args&... args) const {
|
std::back_insert_iterator<Container> out, Args&&... args) const {
|
||||||
internal::container_buffer<Container> buffer(internal::get_container(out));
|
internal::container_buffer<Container> buffer(internal::get_container(out));
|
||||||
using range = buffer_range<char_type>;
|
using range = buffer_range<char_type>;
|
||||||
this->vformat_to(range(buffer), basic_format_args<context>{
|
this->vformat_to(range(buffer),
|
||||||
make_args_checked(format_, args...)});
|
basic_format_args<context>{
|
||||||
|
make_args_checked<Args...>(format_, args...)});
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,9 +244,9 @@ class prepared_format {
|
|||||||
inline typename buffer_context<char_type>::iterator format_to(
|
inline typename buffer_context<char_type>::iterator format_to(
|
||||||
basic_memory_buffer<char_type, SIZE>& buf, const Args&... args) const {
|
basic_memory_buffer<char_type, SIZE>& buf, const Args&... args) const {
|
||||||
using range = buffer_range<char_type>;
|
using range = buffer_range<char_type>;
|
||||||
return this->vformat_to(
|
return this->vformat_to(range(buf),
|
||||||
range(buf),
|
basic_format_args<context>{
|
||||||
basic_format_args<context>{make_args_checked(format_, args...)});
|
make_args_checked<Args...>(format_, args...)});
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -138,7 +138,7 @@ template <typename Context> class char_converter {
|
|||||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||||
void operator()(T value) {
|
void operator()(T value) {
|
||||||
arg_ = internal::make_arg<Context>(
|
arg_ = internal::make_arg<Context>(
|
||||||
static_cast<typename Context::char_type>(value));
|
static_cast<typename Context::char_type>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
||||||
@ -563,9 +563,10 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
|||||||
return std::copy(start, it, out);
|
return std::copy(start, it, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char> using basic_printf_context_t =
|
template <typename Char>
|
||||||
basic_printf_context<std::back_insert_iterator<internal::buffer<Char>>,
|
using basic_printf_context_t =
|
||||||
Char>;
|
basic_printf_context<std::back_insert_iterator<internal::buffer<Char>>,
|
||||||
|
Char>;
|
||||||
|
|
||||||
using printf_context = basic_printf_context_t<char>;
|
using printf_context = basic_printf_context_t<char>;
|
||||||
using wprintf_context = basic_printf_context_t<wchar_t>;
|
using wprintf_context = basic_printf_context_t<wchar_t>;
|
||||||
@ -599,8 +600,7 @@ inline format_arg_store<wprintf_context, Args...> make_wprintf_args(
|
|||||||
|
|
||||||
template <typename S, typename Char = char_t<S>>
|
template <typename S, typename Char = char_t<S>>
|
||||||
inline std::basic_string<Char> vsprintf(
|
inline std::basic_string<Char> vsprintf(
|
||||||
const S& format,
|
const S& format, basic_format_args<basic_printf_context_t<Char>> args) {
|
||||||
basic_format_args<basic_printf_context_t<Char>> args) {
|
|
||||||
basic_memory_buffer<Char> buffer;
|
basic_memory_buffer<Char> buffer;
|
||||||
printf(buffer, to_string_view(format), args);
|
printf(buffer, to_string_view(format), args);
|
||||||
return to_string(buffer);
|
return to_string(buffer);
|
||||||
@ -623,9 +623,8 @@ inline std::basic_string<Char> sprintf(const S& format, const Args&... args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename Char = char_t<S>>
|
template <typename S, typename Char = char_t<S>>
|
||||||
inline int vfprintf(
|
inline int vfprintf(std::FILE* f, const S& format,
|
||||||
std::FILE* f, const S& format,
|
basic_format_args<basic_printf_context_t<Char>> args) {
|
||||||
basic_format_args<basic_printf_context_t<Char>> args) {
|
|
||||||
basic_memory_buffer<Char> buffer;
|
basic_memory_buffer<Char> buffer;
|
||||||
printf(buffer, to_string_view(format), args);
|
printf(buffer, to_string_view(format), args);
|
||||||
std::size_t size = buffer.size();
|
std::size_t size = buffer.size();
|
||||||
@ -652,9 +651,8 @@ inline int fprintf(std::FILE* f, const S& format, const Args&... args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename Char = char_t<S>>
|
template <typename S, typename Char = char_t<S>>
|
||||||
inline int vprintf(
|
inline int vprintf(const S& format,
|
||||||
const S& format,
|
basic_format_args<basic_printf_context_t<Char>> args) {
|
||||||
basic_format_args<basic_printf_context_t<Char>> args) {
|
|
||||||
return vfprintf(stdout, to_string_view(format), args);
|
return vfprintf(stdout, to_string_view(format), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -676,9 +674,8 @@ inline int printf(const S& format_str, const Args&... args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename Char = char_t<S>>
|
template <typename S, typename Char = char_t<S>>
|
||||||
inline int vfprintf(
|
inline int vfprintf(std::basic_ostream<Char>& os, const S& format,
|
||||||
std::basic_ostream<Char>& os, const S& format,
|
basic_format_args<basic_printf_context_t<Char>> args) {
|
||||||
basic_format_args<basic_printf_context_t<Char>> args) {
|
|
||||||
basic_memory_buffer<Char> buffer;
|
basic_memory_buffer<Char> buffer;
|
||||||
printf(buffer, to_string_view(format), args);
|
printf(buffer, to_string_view(format), args);
|
||||||
internal::write(os, buffer);
|
internal::write(os, buffer);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user