Skip to content

Commit eafd079

Browse files
committed
Improve width computation
1 parent 0c6919e commit eafd079

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed

include/fmt/format.h

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -473,15 +473,20 @@ inline size_t count_code_points(basic_string_view<Char> s) {
473473
}
474474

475475
// Counts the number of code points in a UTF-8 string.
476-
inline size_t count_code_points(basic_string_view<char8_t> s) {
477-
const char8_t* data = s.data();
476+
inline size_t count_code_points(basic_string_view<char> s) {
477+
const char* data = s.data();
478478
size_t num_code_points = 0;
479479
for (size_t i = 0, size = s.size(); i != size; ++i) {
480480
if ((data[i] & 0xc0) != 0x80) ++num_code_points;
481481
}
482482
return num_code_points;
483483
}
484484

485+
inline size_t count_code_points(basic_string_view<char8_t> s) {
486+
return count_code_points(basic_string_view<char>(
487+
reinterpret_cast<const char*>(s.data()), s.size()));
488+
}
489+
485490
template <typename Char>
486491
inline size_t code_point_index(basic_string_view<Char> s, size_t n) {
487492
size_t size = s.size();
@@ -1603,6 +1608,18 @@ template <typename Range> class basic_writer {
16031608
}
16041609
};
16051610

1611+
struct bytes_writer {
1612+
string_view bytes;
1613+
1614+
size_t size() const { return bytes.size(); }
1615+
size_t width() const { return bytes.size(); }
1616+
1617+
template <typename It> void operator()(It&& it) const {
1618+
const char* data = bytes.data();
1619+
it = copy_str<char>(data, data + size(), it);
1620+
}
1621+
};
1622+
16061623
template <typename UIntPtr> struct pointer_writer {
16071624
UIntPtr value;
16081625
int num_digits;
@@ -1761,6 +1778,10 @@ template <typename Range> class basic_writer {
17611778
write(data, size, specs);
17621779
}
17631780

1781+
void write_bytes(string_view bytes, const format_specs& specs) {
1782+
write_padded(specs, bytes_writer{bytes});
1783+
}
1784+
17641785
template <typename UIntPtr>
17651786
void write_pointer(UIntPtr value, const format_specs* specs) {
17661787
int num_digits = count_digits<4>(value);
@@ -3150,11 +3171,32 @@ class bytes {
31503171
explicit bytes(string_view data) : data_(data) {}
31513172
};
31523173

3153-
template <> struct formatter<bytes> : formatter<string_view> {
3174+
template <> struct formatter<bytes> {
3175+
template <typename ParseContext>
3176+
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
3177+
using handler_type = internal::dynamic_specs_handler<ParseContext>;
3178+
internal::specs_checker<handler_type> handler(handler_type(specs_, ctx),
3179+
internal::type::string_type);
3180+
auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
3181+
internal::check_string_type_spec(specs_.type, ctx.error_handler());
3182+
return it;
3183+
}
3184+
31543185
template <typename FormatContext>
31553186
auto format(bytes b, FormatContext& ctx) -> decltype(ctx.out()) {
3156-
return formatter<string_view>::format(b.data_, ctx);
3187+
internal::handle_dynamic_spec<internal::width_checker>(
3188+
specs_.width, specs_.width_ref, ctx);
3189+
internal::handle_dynamic_spec<internal::precision_checker>(
3190+
specs_.precision, specs_.precision_ref, ctx);
3191+
using range_type =
3192+
internal::output_range<typename FormatContext::iterator, char>;
3193+
internal::basic_writer<range_type> writer(range_type(ctx.out()));
3194+
writer.write_bytes(b.data_, specs_);
3195+
return writer.out();
31573196
}
3197+
3198+
private:
3199+
internal::dynamic_format_specs<char> specs_;
31583200
};
31593201

31603202
template <typename It, typename Char> struct arg_join : internal::view {

test/format-test.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// For the license information refer to format.h.
77

88
#include <stdint.h>
9+
910
#include <cctype>
1011
#include <cfloat>
1112
#include <climits>
@@ -987,7 +988,9 @@ TEST(FormatterTest, Width) {
987988
EXPECT_EQ(" 0xcafe", format("{0:10}", reinterpret_cast<void*>(0xcafe)));
988989
EXPECT_EQ("x ", format("{0:11}", 'x'));
989990
EXPECT_EQ("str ", format("{0:12}", "str"));
991+
EXPECT_EQ(fmt::format("{:*^5}", "🤡"), "**🤡**");
990992
}
993+
991994
template <typename T> inline T const_check(T value) { return value; }
992995

993996
TEST(FormatterTest, RuntimeWidth) {

0 commit comments

Comments
 (0)