mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
Support variable number of arguments to inject at runtime (#1580)
Further, switching internal member from array_view to span to be closer to standard, and more constexpr friendly. Also adjusting to C++11 template syntax. Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
This commit is contained in:
parent
06e54f6b23
commit
c896d2d7dd
@ -35,7 +35,6 @@ SOFTWARE.
|
|||||||
|
|
||||||
#include "algorithm.h"
|
#include "algorithm.h"
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
#include "array_view.h"
|
|
||||||
#include "error_handler.h"
|
#include "error_handler.h"
|
||||||
#include "limits.h"
|
#include "limits.h"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
@ -627,7 +626,7 @@ namespace etl
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct has_formatter_parse<T, etl::void_t<decltype(etl::declval<etl::formatter<T>&>().parse(etl::declval<format_parse_context&>()))> >
|
struct has_formatter_parse<T, etl::void_t<decltype(etl::declval<etl::formatter<T>&>().parse(etl::declval<format_parse_context&>()))>>
|
||||||
: etl::true_type
|
: etl::true_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
@ -642,7 +641,7 @@ namespace etl
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct has_formatter_format<T, etl::void_t<decltype(etl::declval<etl::formatter<T>&>().format(
|
struct has_formatter_format<T, etl::void_t<decltype(etl::declval<etl::formatter<T>&>().format(
|
||||||
etl::declval<const T&>(), etl::declval<etl::basic_format_context<char*, char>&>()))> > : etl::true_type
|
etl::declval<const T&>(), etl::declval<etl::basic_format_context<char*, char>&>()))>> : etl::true_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -806,7 +805,7 @@ namespace etl
|
|||||||
// Converting constructor for user-defined types that provide an
|
// Converting constructor for user-defined types that provide an
|
||||||
// etl::formatter<T> specialisation. The value is stored type-erased in a
|
// etl::formatter<T> specialisation. The value is stored type-erased in a
|
||||||
// handle, matching the std::basic_format_arg behaviour for custom types.
|
// handle, matching the std::basic_format_arg behaviour for custom types.
|
||||||
template <typename T, typename = etl::enable_if_t<private_format::is_formattable<T>::value> >
|
template <typename T, typename = etl::enable_if_t<private_format::is_formattable<T>::value>>
|
||||||
basic_format_arg(const T& v)
|
basic_format_arg(const T& v)
|
||||||
: data(handle(v))
|
: data(handle(v))
|
||||||
{
|
{
|
||||||
@ -863,7 +862,7 @@ namespace etl
|
|||||||
return _args.get(i);
|
return _args.get(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
etl::array_view<basic_format_arg<Context>> get()
|
etl::span<basic_format_arg<Context>> get()
|
||||||
{
|
{
|
||||||
return _args;
|
return _args;
|
||||||
}
|
}
|
||||||
@ -884,6 +883,15 @@ namespace etl
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// non-standard
|
||||||
|
// Constructs from externally owned storage, for cases where the number of
|
||||||
|
// arguments is only known at runtime and so no format_arg_store<Context, Args...>
|
||||||
|
// can be formed. The referenced storage must outlive this object.
|
||||||
|
explicit basic_format_args(etl::span<basic_format_arg<Context>> args_)
|
||||||
|
: _args(args_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
basic_format_args(const basic_format_args<Context>& other)
|
basic_format_args(const basic_format_args<Context>& other)
|
||||||
: _args(other._args)
|
: _args(other._args)
|
||||||
{
|
{
|
||||||
@ -908,7 +916,7 @@ namespace etl
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
etl::array_view<basic_format_arg<Context>> _args;
|
etl::span<basic_format_arg<Context>> _args;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace private_format
|
namespace private_format
|
||||||
@ -2019,7 +2027,7 @@ namespace etl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// for user-defined types routed through basic_format_arg::handle
|
// for user-defined types routed through basic_format_arg::handle
|
||||||
void operator()(typename basic_format_arg<format_context<OutputIt> >::handle h)
|
void operator()(typename basic_format_arg<format_context<OutputIt>>::handle h)
|
||||||
{
|
{
|
||||||
h.format(parse_ctx, fmt_ctx);
|
h.format(parse_ctx, fmt_ctx);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -950,6 +950,29 @@ namespace
|
|||||||
CHECK_EQUAL("010", test_format(s, "{:#o}", 8));
|
CHECK_EQUAL("010", test_format(s, "{:#o}", 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//*************************************************************************
|
||||||
|
// Arguments whose count is only known at runtime cannot be held in a
|
||||||
|
// format_arg_store<Context, Args...>, so basic_format_args can also be built
|
||||||
|
// directly over caller owned storage.
|
||||||
|
TEST(test_vformat_to_runtime_sized_args)
|
||||||
|
{
|
||||||
|
etl::string<100> s;
|
||||||
|
|
||||||
|
using iterator_t = etl::back_insert_iterator<etl::string<100>>;
|
||||||
|
using arg_t = etl::format_arg<iterator_t>;
|
||||||
|
|
||||||
|
etl::array<arg_t, 4> storage = {arg_t(1), arg_t("two"), arg_t(3), arg_t('x')};
|
||||||
|
|
||||||
|
// Only the first three of the four slots are used.
|
||||||
|
etl::vformat_to(etl::back_inserter(s), "{} {} {}", etl::format_args<iterator_t>(etl::span<arg_t>(storage.data(), 3U)));
|
||||||
|
CHECK_EQUAL("1 two 3", s);
|
||||||
|
|
||||||
|
// An empty argument list is also valid.
|
||||||
|
s.clear();
|
||||||
|
etl::vformat_to(etl::back_inserter(s), "no args", etl::format_args<iterator_t>(etl::span<arg_t>()));
|
||||||
|
CHECK_EQUAL("no args", s);
|
||||||
|
}
|
||||||
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
TEST(test_format_custom_type)
|
TEST(test_format_custom_type)
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user