forked from fmtlib/fmt
Add dynamic width support to FMT_COMPILE (#1809)
This commit is contained in:
@ -443,7 +443,8 @@ template <typename Char, typename T, int N> struct spec_field {
|
|||||||
OutputIt format(OutputIt out, const Args&... args) const {
|
OutputIt format(OutputIt out, const Args&... args) const {
|
||||||
// This ensures that the argument type is convertile to `const T&`.
|
// This ensures that the argument type is convertile to `const T&`.
|
||||||
const T& arg = get<N>(args...);
|
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);
|
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 {
|
template <typename T, typename Char> struct parse_specs_result {
|
||||||
formatter<T, Char> fmt;
|
formatter<T, Char> fmt;
|
||||||
size_t end;
|
size_t end;
|
||||||
|
int next_arg_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename Char>
|
template <typename T, typename Char>
|
||||||
constexpr parse_specs_result<T, Char> parse_specs(basic_string_view<Char> str,
|
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);
|
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 f = formatter<T, Char>();
|
||||||
auto end = f.parse(ctx);
|
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
|
// 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);
|
format_str);
|
||||||
} else if constexpr (str[POS + 1] == ':') {
|
} else if constexpr (str[POS + 1] == ':') {
|
||||||
using type = get_type<ID, Args>;
|
using type = get_type<ID, Args>;
|
||||||
constexpr auto result = parse_specs<type>(str, POS + 2);
|
constexpr auto result = parse_specs<type>(str, POS + 2, ID);
|
||||||
return parse_tail<Args, result.end, ID + 1>(
|
return parse_tail<Args, result.end, result.next_arg_id>(
|
||||||
spec_field<char_type, type, ID>{result.fmt}, format_str);
|
spec_field<char_type, type, ID>{result.fmt}, format_str);
|
||||||
} else {
|
} else {
|
||||||
return unknown_format();
|
return unknown_format();
|
||||||
|
@ -298,7 +298,8 @@ template <typename T> struct std_string_view {};
|
|||||||
|
|
||||||
#ifdef FMT_USE_INT128
|
#ifdef FMT_USE_INT128
|
||||||
// Do nothing.
|
// 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
|
# define FMT_USE_INT128 1
|
||||||
using int128_t = __int128_t;
|
using int128_t = __int128_t;
|
||||||
using uint128_t = __uint128_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;
|
using iterator = typename basic_string_view<Char>::iterator;
|
||||||
|
|
||||||
explicit constexpr basic_format_parse_context(
|
explicit constexpr basic_format_parse_context(
|
||||||
basic_string_view<Char> format_str, ErrorHandler eh = {})
|
basic_string_view<Char> format_str, ErrorHandler eh = {},
|
||||||
: ErrorHandler(eh), format_str_(format_str), next_arg_id_(0) {}
|
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
|
Returns an iterator to the beginning of the format string range being
|
||||||
|
@ -153,6 +153,11 @@ TEST(CompileTest, FormatSpecs) {
|
|||||||
EXPECT_EQ("42", fmt::format(FMT_COMPILE("{:x}"), 0x42));
|
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) {
|
TEST(CompileTest, FormatTo) {
|
||||||
char buf[8];
|
char buf[8];
|
||||||
auto end = fmt::format_to(buf, FMT_COMPILE("{}"), 42);
|
auto end = fmt::format_to(buf, FMT_COMPILE("{}"), 42);
|
||||||
|
Reference in New Issue
Block a user