Add dynamic width support to FMT_COMPILE (#1809)

This commit is contained in:
Victor Zverovich 2020-08-10 09:13:13 -07:00
parent 6fb7c6fb25
commit 54daa0864a
3 changed files with 18 additions and 9 deletions

View File

@ -443,7 +443,8 @@ template <typename Char, typename T, int N> struct spec_field {
OutputIt format(OutputIt out, const Args&... args) const {
// This ensures that the argument type is convertile to `const T&`.
const T& arg = get<N>(args...);
basic_format_context<OutputIt, Char> ctx(out, {});
const auto& vargs = make_format_args(args...);
basic_format_context<OutputIt, Char> ctx(out, vargs);
return fmt.format(arg, ctx);
}
};
@ -502,16 +503,17 @@ constexpr auto parse_tail(T head, S format_str) {
template <typename T, typename Char> struct parse_specs_result {
formatter<T, Char> fmt;
size_t end;
int next_arg_id;
};
template <typename T, typename Char>
constexpr parse_specs_result<T, Char> parse_specs(basic_string_view<Char> str,
size_t pos) {
size_t pos, int arg_id) {
str.remove_prefix(pos);
auto ctx = basic_format_parse_context<Char>(str);
auto ctx = basic_format_parse_context<Char>(str, {}, arg_id + 1);
auto f = formatter<T, Char>();
auto end = f.parse(ctx);
return {f, pos + (end - str.data()) + 1};
return {f, pos + (end - str.data()) + 1, ctx.next_arg_id()};
}
// Compiles a non-empty format string and returns the compiled representation
@ -531,8 +533,8 @@ constexpr auto compile_format_string(S format_str) {
format_str);
} else if constexpr (str[POS + 1] == ':') {
using type = get_type<ID, Args>;
constexpr auto result = parse_specs<type>(str, POS + 2);
return parse_tail<Args, result.end, ID + 1>(
constexpr auto result = parse_specs<type>(str, POS + 2, ID);
return parse_tail<Args, result.end, result.next_arg_id>(
spec_field<char_type, type, ID>{result.fmt}, format_str);
} else {
return unknown_format();

View File

@ -298,7 +298,8 @@ template <typename T> struct std_string_view {};
#ifdef FMT_USE_INT128
// Do nothing.
#elif defined(__SIZEOF_INT128__) && !FMT_NVCC && !(FMT_CLANG_VERSION && FMT_MSC_VER)
#elif defined(__SIZEOF_INT128__) && !FMT_NVCC && \
!(FMT_CLANG_VERSION && FMT_MSC_VER)
# define FMT_USE_INT128 1
using int128_t = __int128_t;
using uint128_t = __uint128_t;
@ -556,8 +557,9 @@ class basic_format_parse_context : private ErrorHandler {
using iterator = typename basic_string_view<Char>::iterator;
explicit constexpr basic_format_parse_context(
basic_string_view<Char> format_str, ErrorHandler eh = {})
: ErrorHandler(eh), format_str_(format_str), next_arg_id_(0) {}
basic_string_view<Char> format_str, ErrorHandler eh = {},
int next_arg_id = 0)
: ErrorHandler(eh), format_str_(format_str), next_arg_id_(next_arg_id) {}
/**
Returns an iterator to the beginning of the format string range being

View File

@ -153,6 +153,11 @@ TEST(CompileTest, FormatSpecs) {
EXPECT_EQ("42", fmt::format(FMT_COMPILE("{:x}"), 0x42));
}
TEST(CompileTest, DynamicWidth) {
EXPECT_EQ(" 42foo ",
fmt::format(FMT_COMPILE("{:{}}{:{}}"), 42, 4, "foo", 5));
}
TEST(CompileTest, FormatTo) {
char buf[8];
auto end = fmt::format_to(buf, FMT_COMPILE("{}"), 42);