mirror of
https://github.com/shadps4-emu/ext-fmt.git
synced 2024-11-23 17:59:52 +00:00
Count width in code points (#628)
This commit is contained in:
parent
deb901b9e4
commit
38325248e5
@ -1342,10 +1342,11 @@ struct is_contiguous<internal::basic_buffer<Char> >: std::true_type {};
|
|||||||
/** Formats a string and writes the output to ``out``. */
|
/** Formats a string and writes the output to ``out``. */
|
||||||
template <typename Container, typename S>
|
template <typename Container, typename S>
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
is_contiguous<Container>::value, std::back_insert_iterator<Container>>::type
|
is_contiguous<Container>::value, std::back_insert_iterator<Container>>::type
|
||||||
vformat_to(std::back_insert_iterator<Container> out,
|
vformat_to(
|
||||||
const S &format_str,
|
std::back_insert_iterator<Container> out,
|
||||||
basic_format_args<typename buffer_context<FMT_CHAR(S)>::type> args) {
|
const S &format_str,
|
||||||
|
basic_format_args<typename buffer_context<FMT_CHAR(S)>::type> args) {
|
||||||
internal::container_buffer<Container> buf(internal::get_container(out));
|
internal::container_buffer<Container> buf(internal::get_container(out));
|
||||||
vformat_to(buf, internal::to_string_view(format_str), args);
|
vformat_to(buf, internal::to_string_view(format_str), args);
|
||||||
return out;
|
return out;
|
||||||
|
@ -192,7 +192,7 @@ void report_error(FormatFunc func, int error_code,
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
FMT_FUNC size_t internal::count_code_points(u8string_view s) {
|
FMT_FUNC size_t internal::count_code_points(basic_string_view<char8_t> s) {
|
||||||
const char8_t *data = s.data();
|
const char8_t *data = s.data();
|
||||||
size_t num_code_points = 0;
|
size_t num_code_points = 0;
|
||||||
for (size_t i = 0, size = s.size(); i != size; ++i) {
|
for (size_t i = 0, size = s.size(); i != size; ++i) {
|
||||||
@ -845,7 +845,8 @@ FMT_FUNC void report_windows_error(
|
|||||||
|
|
||||||
FMT_FUNC void vprint(std::FILE *f, string_view format_str, format_args args) {
|
FMT_FUNC void vprint(std::FILE *f, string_view format_str, format_args args) {
|
||||||
memory_buffer buffer;
|
memory_buffer buffer;
|
||||||
vformat_to(buffer, format_str, basic_format_args<buffer_context<char>::type>(args));
|
vformat_to(buffer, format_str,
|
||||||
|
basic_format_args<buffer_context<char>::type>(args));
|
||||||
std::fwrite(buffer.data(), 1, buffer.size(), f);
|
std::fwrite(buffer.data(), 1, buffer.size(), f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -922,8 +922,11 @@ inline unsigned count_digits(uint64_t n) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
template <typename Char>
|
||||||
|
inline size_t count_code_points(basic_string_view<Char> s) { return s.size(); }
|
||||||
|
|
||||||
// Counts the number of code points in a UTF-8 string.
|
// Counts the number of code points in a UTF-8 string.
|
||||||
FMT_API size_t count_code_points(u8string_view s);
|
FMT_API size_t count_code_points(basic_string_view<char8_t> s);
|
||||||
|
|
||||||
inline char8_t to_char8_t(char c) { return static_cast<char8_t>(c); }
|
inline char8_t to_char8_t(char c) { return static_cast<char8_t>(c); }
|
||||||
|
|
||||||
@ -1456,6 +1459,9 @@ class arg_formatter_base {
|
|||||||
|
|
||||||
struct char_writer {
|
struct char_writer {
|
||||||
char_type value;
|
char_type value;
|
||||||
|
|
||||||
|
size_t size() const { return 1; }
|
||||||
|
|
||||||
template <typename It>
|
template <typename It>
|
||||||
void operator()(It &&it) const { *it++ = value; }
|
void operator()(It &&it) const { *it++ = value; }
|
||||||
};
|
};
|
||||||
@ -2457,11 +2463,14 @@ class basic_writer {
|
|||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
struct padded_int_writer {
|
struct padded_int_writer {
|
||||||
|
size_t size_;
|
||||||
string_view prefix;
|
string_view prefix;
|
||||||
char_type fill;
|
char_type fill;
|
||||||
std::size_t padding;
|
std::size_t padding;
|
||||||
F f;
|
F f;
|
||||||
|
|
||||||
|
size_t size() const { return size_; }
|
||||||
|
|
||||||
template <typename It>
|
template <typename It>
|
||||||
void operator()(It &&it) const {
|
void operator()(It &&it) const {
|
||||||
if (prefix.size() != 0)
|
if (prefix.size() != 0)
|
||||||
@ -2493,7 +2502,7 @@ class basic_writer {
|
|||||||
align_spec as = spec;
|
align_spec as = spec;
|
||||||
if (spec.align() == ALIGN_DEFAULT)
|
if (spec.align() == ALIGN_DEFAULT)
|
||||||
as.align_ = ALIGN_RIGHT;
|
as.align_ = ALIGN_RIGHT;
|
||||||
write_padded(size, as, padded_int_writer<F>{prefix, fill, padding, f});
|
write_padded(size, as, padded_int_writer<F>{size, prefix, fill, padding, f});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes a decimal integer.
|
// Writes a decimal integer.
|
||||||
@ -2659,6 +2668,8 @@ class basic_writer {
|
|||||||
char sign;
|
char sign;
|
||||||
const char *str;
|
const char *str;
|
||||||
|
|
||||||
|
size_t size() const { return static_cast<std::size_t>(INF_SIZE); }
|
||||||
|
|
||||||
template <typename It>
|
template <typename It>
|
||||||
void operator()(It &&it) const {
|
void operator()(It &&it) const {
|
||||||
if (sign)
|
if (sign)
|
||||||
@ -2673,6 +2684,8 @@ class basic_writer {
|
|||||||
char sign;
|
char sign;
|
||||||
internal::buffer &buffer;
|
internal::buffer &buffer;
|
||||||
|
|
||||||
|
size_t size() const { return buffer.size() + (sign ? 1 : 0); }
|
||||||
|
|
||||||
template <typename It>
|
template <typename It>
|
||||||
void operator()(It &&it) {
|
void operator()(It &&it) {
|
||||||
if (sign) {
|
if (sign) {
|
||||||
@ -2693,11 +2706,15 @@ class basic_writer {
|
|||||||
template <typename Char>
|
template <typename Char>
|
||||||
struct str_writer {
|
struct str_writer {
|
||||||
const Char *s;
|
const Char *s;
|
||||||
std::size_t size;
|
size_t size_;
|
||||||
|
|
||||||
|
size_t size() const {
|
||||||
|
return internal::count_code_points(basic_string_view<Char>(s, size_));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename It>
|
template <typename It>
|
||||||
void operator()(It &&it) const {
|
void operator()(It &&it) const {
|
||||||
it = internal::copy_str<char_type>(s, s + size, it);
|
it = internal::copy_str<char_type>(s, s + size_, it);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2796,11 +2813,12 @@ template <typename F>
|
|||||||
void basic_writer<Range>::write_padded(
|
void basic_writer<Range>::write_padded(
|
||||||
std::size_t size, const align_spec &spec, F &&f) {
|
std::size_t size, const align_spec &spec, F &&f) {
|
||||||
unsigned width = spec.width();
|
unsigned width = spec.width();
|
||||||
if (width <= size)
|
size_t num_code_points = width != 0 ? f.size() : size;
|
||||||
|
if (width <= num_code_points)
|
||||||
return f(reserve(size));
|
return f(reserve(size));
|
||||||
auto &&it = reserve(width);
|
auto &&it = reserve(width + (size - num_code_points));
|
||||||
char_type fill = static_cast<char_type>(spec.fill());
|
char_type fill = static_cast<char_type>(spec.fill());
|
||||||
std::size_t padding = width - size;
|
std::size_t padding = width - num_code_points;
|
||||||
if (spec.align() == ALIGN_RIGHT) {
|
if (spec.align() == ALIGN_RIGHT) {
|
||||||
it = std::fill_n(it, padding, fill);
|
it = std::fill_n(it, padding, fill);
|
||||||
f(it);
|
f(it);
|
||||||
@ -3533,12 +3551,14 @@ using format_to_n_context = typename fmt::format_context_t<
|
|||||||
fmt::internal::truncating_iterator<OutputIt>, Char>::type;
|
fmt::internal::truncating_iterator<OutputIt>, Char>::type;
|
||||||
|
|
||||||
template <typename OutputIt, typename Char = typename OutputIt::value_type>
|
template <typename OutputIt, typename Char = typename OutputIt::value_type>
|
||||||
using format_to_n_args = fmt::basic_format_args<format_to_n_context<OutputIt, Char>>;
|
using format_to_n_args =
|
||||||
|
fmt::basic_format_args<format_to_n_context<OutputIt, Char>>;
|
||||||
|
|
||||||
template <typename OutputIt, typename Char, typename ...Args>
|
template <typename OutputIt, typename Char, typename ...Args>
|
||||||
inline format_arg_store<format_to_n_context<OutputIt, Char>, Args...>
|
inline format_arg_store<format_to_n_context<OutputIt, Char>, Args...>
|
||||||
make_format_to_n_args(const Args &... args) {
|
make_format_to_n_args(const Args &... args) {
|
||||||
return format_arg_store<format_to_n_context<OutputIt, Char>, Args...>(args...);
|
return format_arg_store<
|
||||||
|
format_to_n_context<OutputIt, Char>, Args...>(args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIt, typename Char, typename... Args>
|
template <typename OutputIt, typename Char, typename... Args>
|
||||||
@ -3561,7 +3581,8 @@ template <typename OutputIt, typename String, typename... Args>
|
|||||||
inline typename std::enable_if<
|
inline typename std::enable_if<
|
||||||
internal::is_format_string<String>::value,
|
internal::is_format_string<String>::value,
|
||||||
format_to_n_result<OutputIt>>::type format_to_n(
|
format_to_n_result<OutputIt>>::type format_to_n(
|
||||||
OutputIt out, std::size_t n, const String &format_str, const Args &... args) {
|
OutputIt out, std::size_t n, const String &format_str,
|
||||||
|
const Args &... args) {
|
||||||
internal::check_format_string<Args...>(format_str);
|
internal::check_format_string<Args...>(format_str);
|
||||||
typedef FMT_CHAR(String) Char;
|
typedef FMT_CHAR(String) Char;
|
||||||
format_arg_store<format_to_n_context<OutputIt, Char>, Args...> as{ args... };
|
format_arg_store<format_to_n_context<OutputIt, Char>, Args...> as{ args... };
|
||||||
|
@ -2448,6 +2448,7 @@ TEST(FormatTest, U8StringViewLiteral) {
|
|||||||
const fmt::char8_t *data = s.data();
|
const fmt::char8_t *data = s.data();
|
||||||
EXPECT_EQ(data[0], 'a');
|
EXPECT_EQ(data[0], 'a');
|
||||||
EXPECT_EQ(data[1], 'b');
|
EXPECT_EQ(data[1], 'b');
|
||||||
|
EXPECT_EQ(format("{:*^5}"_u, "🤡"_u), "**🤡**"_u);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user