12#include "../microfmt.hpp"
26template <
typename CharT,
typename Traits,
typename Alloc>
struct formatter<std::basic_string<CharT, Traits, Alloc>> {
36 void format(
const std::basic_string<CharT, Traits, Alloc> &val,
const sink &out)
const noexcept {
37 RELOCO_BEGIN_UNSAFE_BUFFER_USAGE;
39 out.write(std::basic_string_view<CharT, Traits>(val.data(), val.size()));
41 RELOCO_END_UNSAFE_BUFFER_USAGE;
71 size_t precision{size_t(-1)};
75 bool debug_escaped{
false};
85RELOCO_BEGIN_UNSAFE_CODE
93 const size_t len = spec.size();
96 if (pos + 1 < len && (spec[pos + 1] ==
'<' || spec[pos + 1] ==
'>' || spec[pos + 1] ==
'^')) {
97 res.
fill = spec[pos++];
98 const char a = spec[pos++];
105 }
else if (pos < len && (spec[pos] ==
'<' || spec[pos] ==
'>' || spec[pos] ==
'^')) {
106 const char a = spec[pos++];
116 while (pos < len && spec[pos] >=
'0' && spec[pos] <=
'9') {
117 res.width = res.width * 10 +
static_cast<size_t>(spec[pos++] -
'0');
121 if (pos < len && spec[pos] ==
'.') {
124 while (pos < len && spec[pos] >=
'0' && spec[pos] <=
'9') {
125 res.precision = res.precision * 10 +
static_cast<size_t>(spec[pos++] -
'0');
131 if (spec[pos] ==
'?') {
132 res.debug_escaped =
true;
155 std::fill_n(buf, std::min<size_t>(count,
sizeof(buf)), fill);
157 const size_t chunk = std::min<size_t>(count,
sizeof(buf));
158 out.write(microfmt::string_view(buf, chunk));
189 if (
static_cast<unsigned char>(ch) < 0x20 ||
static_cast<unsigned char>(ch) == 0x7F) {
190 static constexpr microfmt::string_view hex_chars =
"0123456789abcdef";
192 char hex[4] = {
'\\',
'x', hex_chars[(
static_cast<unsigned char>(ch) >> 4) & 0x0F],
193 hex_chars[
static_cast<unsigned char>(ch) & 0x0F]};
194 out.write(microfmt::string_view(
hex, 4));
196 out.write(microfmt::string_view(&ch, 1));
220 if (
static_cast<unsigned char>(ch) < 0x20 ||
static_cast<unsigned char>(ch) == 0x7F) {
246 constexpr explicit as_string_view(microfmt::string_view str) noexcept : str_(str) {}
252 [[nodiscard]]
constexpr microfmt::string_view
get() const & noexcept {
return str_; }
254 [[nodiscard]]
constexpr microfmt::string_view
get() const && = delete;
280template <
typename CharT,
typename Traits,
typename Alloc>
282 return as_string_view{microfmt::string_view(str.data(), str.size())};
285template <
typename CharT,
typename Traits,
typename Alloc>
294RELOCO_BEGIN_UNSAFE_CODE
296 return as_string_view{str !=
nullptr ? microfmt::string_view(str) : microfmt::string_view(
"(null)")};
298RELOCO_END_UNSAFE_CODE
326 microfmt::string_view sv = val.get();
329 if (spec_.precision !=
size_t(-1) && sv.size() > spec_.precision) {
330 sv = sv.substr(0, spec_.precision);
334 if (!spec_.debug_escaped && spec_.align == detail::string_align::none && spec_.width <= sv.size()) {
339 const size_t visible_len = spec_.debug_escaped ? detail::calculate_escaped_len(sv) : sv.size();
340 const size_t total_pad = (spec_.width > visible_len) ? (spec_.width - visible_len) : 0;
342 const auto emit_body = [
this, &out, &sv]() {
343 if (spec_.debug_escaped) {
346 detail::write_escaped_character(out, ch);
354 if (total_pad == 0) {
360 switch (spec_.align) {
361 case detail::string_align::left:
362 case detail::string_align::none:
364 detail::write_fill_chars(out, spec_.fill, total_pad);
367 case detail::string_align::right:
368 detail::write_fill_chars(out, spec_.fill, total_pad);
372 case detail::string_align::center: {
373 const size_t left_pad = total_pad / 2;
374 const size_t right_pad = total_pad - left_pad;
375 detail::write_fill_chars(out, spec_.fill, left_pad);
377 detail::write_fill_chars(out, spec_.fill, right_pad);
Non-owning string view supporting advanced format specifiers.
Definition string.hpp:240
constexpr microfmt::string_view get() const &&=delete
constexpr microfmt::string_view get() const &noexcept
Returns the underlying string view.
Definition string.hpp:252
constexpr as_string_view(microfmt::string_view str) noexcept
Constructs the view over a string_view.
Definition string.hpp:246
Definition microfmt.hpp:881
#define MICROFMT_API_CLASS
Definition compat.hpp:181
RELOCO_END_UNSAFE_CODE void write_fill_chars(const sink &out, char fill, size_t count) noexcept
Writes count copies of fill to the sink in bounded chunks.
Definition string.hpp:152
string_align
Horizontal alignment mode for padded string output.
Definition string.hpp:50
RELOCO_BEGIN_UNSAFE_CODE constexpr parsed_string_spec parse_advanced_string_spec(microfmt::string_view spec) noexcept
Parses an advanced string specifier: [[fill]align][width][.precision][?].
Definition string.hpp:86
size_t calculate_escaped_len(microfmt::string_view sv) noexcept
Computes the rendered character count of a debug-escaped string.
Definition string.hpp:207
void write_escaped_character(const sink &out, char ch) noexcept
Writes a single character with C-style debug escaping.
Definition string.hpp:168
constexpr as_string_view as_string(microfmt::string_view sv) noexcept
Wraps a string_view for advanced string formatting.
Definition string.hpp:270
constexpr hex_view< T > hex(T val, int width=0, bool prefix=false, bool uppercase=false) noexcept
Definition format_helpers.hpp:29
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46
RELOCO_END_UNSAFE_CODE
Definition remote_object.hpp:132
Parsed advanced string format specifier state.
Definition string.hpp:55
char fill
Fill character used for padding (default space).
Definition string.hpp:59