@@ -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+
485490template <typename Char>
486491inline 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
31603202template <typename It, typename Char> struct arg_join : internal::view {
0 commit comments