diff options
author | Ali Mohammad Pur <ali.mpfard@gmail.com> | 2021-06-17 13:11:00 +0430 |
---|---|---|
committer | Ali Mohammad Pur <Ali.mpfard@gmail.com> | 2021-06-17 18:44:00 +0430 |
commit | 7eda164c252af8e9337fe926f5dc88059452cfed (patch) | |
tree | 3d820a44fecfea4f63c10cb83729c60bdce30693 /AK | |
parent | 10f56166e5f5b4c7ed09fddc643505ca5d759013 (diff) | |
download | serenity-7eda164c252af8e9337fe926f5dc88059452cfed.zip |
AK: Add a :hex-dump mode to AK::Format
This will just hexdump the given value.
Note that not all formatters respect this, the ones that do are:
- (Readonly)Bytes: formatter added in this commit
- StringView / char const*
- integral types
Diffstat (limited to 'AK')
-rw-r--r-- | AK/Format.cpp | 38 | ||||
-rw-r--r-- | AK/Format.h | 27 |
2 files changed, 63 insertions, 2 deletions
diff --git a/AK/Format.cpp b/AK/Format.cpp index d93bf20062..82047a8673 100644 --- a/AK/Format.cpp +++ b/AK/Format.cpp @@ -377,6 +377,29 @@ void FormatBuilder::put_f64( } #endif +void FormatBuilder::put_hexdump(ReadonlyBytes bytes, size_t width, char fill) +{ + auto put_char_view = [&](auto i) { + put_padding(fill, 4); + for (size_t j = i - width; j < i; ++j) { + auto ch = bytes[j]; + m_builder.append(ch >= 32 && ch <= 127 ? ch : '.'); // silly hack + } + }; + for (size_t i = 0; i < bytes.size(); ++i) { + if (width > 0) { + if (i % width == 0 && i) { + put_char_view(i); + put_literal("\n"); + } + } + put_u64(bytes[i], 16, false, false, true, Align::Right, 2); + } + + if (width > 0 && bytes.size() && bytes.size() % width == 0) + put_char_view(bytes.size()); +} + void vformat(StringBuilder& builder, StringView fmtstr, TypeErasedFormatParams params) { FormatBuilder fmtbuilder { builder }; @@ -456,6 +479,8 @@ void StandardFormatter::parse(TypeErasedFormatParams& params, FormatParser& pars m_mode = Mode::Hexfloat; else if (parser.consume_specific('A')) m_mode = Mode::HexfloatUppercase; + else if (parser.consume_specific("hex-dump")) + m_mode = Mode::HexDump; if (!parser.is_eof()) dbgln("{} did not consume '{}'", __PRETTY_FUNCTION__, parser.remaining()); @@ -471,7 +496,7 @@ void Formatter<StringView>::format(FormatBuilder& builder, StringView value) VERIFY_NOT_REACHED(); if (m_zero_pad) VERIFY_NOT_REACHED(); - if (m_mode != Mode::Default && m_mode != Mode::String && m_mode != Mode::Character) + if (m_mode != Mode::Default && m_mode != Mode::String && m_mode != Mode::Character && m_mode != Mode::HexDump) VERIFY_NOT_REACHED(); if (m_width.has_value() && m_precision.has_value()) VERIFY_NOT_REACHED(); @@ -479,7 +504,10 @@ void Formatter<StringView>::format(FormatBuilder& builder, StringView value) m_width = m_width.value_or(0); m_precision = m_precision.value_or(NumericLimits<size_t>::max()); - builder.put_string(value, m_align, m_width.value(), m_precision.value(), m_fill); + if (m_mode == Mode::HexDump) + builder.put_hexdump(value.bytes(), m_width.value(), m_fill); + else + builder.put_string(value, m_align, m_width.value(), m_precision.value(), m_fill); } void Formatter<FormatString>::vformat(FormatBuilder& builder, StringView fmtstr, TypeErasedFormatParams params) @@ -535,6 +563,10 @@ void Formatter<T, typename EnableIf<IsIntegral<T>>::Type>::format(FormatBuilder& } else if (m_mode == Mode::HexadecimalUppercase) { base = 16; upper_case = true; + } else if (m_mode == Mode::HexDump) { + m_width = m_width.value_or(32); + builder.put_hexdump({ &value, sizeof(value) }, m_width.value(), m_fill); + return; } else { VERIFY_NOT_REACHED(); } @@ -563,6 +595,8 @@ void Formatter<bool>::format(FormatBuilder& builder, bool value) if (m_mode == Mode::Binary || m_mode == Mode::BinaryUppercase || m_mode == Mode::Decimal || m_mode == Mode::Octal || m_mode == Mode::Hexadecimal || m_mode == Mode::HexadecimalUppercase) { Formatter<u8> formatter { *this }; return formatter.format(builder, static_cast<u8>(value)); + } else if (m_mode == Mode::HexDump) { + return builder.put_hexdump({ &value, sizeof(value) }, m_width.value_or(32), m_fill); } else { Formatter<StringView> formatter { *this }; return formatter.format(builder, value ? "true" : "false"); diff --git a/AK/Format.h b/AK/Format.h index 96106f5fbd..cae81e821a 100644 --- a/AK/Format.h +++ b/AK/Format.h @@ -196,6 +196,11 @@ public: SignMode sign_mode = SignMode::OnlyIfNeeded); #endif + void put_hexdump( + ReadonlyBytes, + size_t width, + char fill = ' '); + const StringBuilder& builder() const { return m_builder; @@ -261,6 +266,7 @@ struct StandardFormatter { Float, Hexfloat, HexfloatUppercase, + HexDump, }; FormatBuilder::Align m_align = FormatBuilder::Align::Default; @@ -296,6 +302,27 @@ struct Formatter<StringView> : StandardFormatter { void format(FormatBuilder&, StringView value); }; + +template<> +struct Formatter<ReadonlyBytes> : Formatter<StringView> { + void format(FormatBuilder& builder, ReadonlyBytes const& value) + { + if (m_mode == Mode::Pointer) { + Formatter<FlatPtr> formatter { *this }; + formatter.format(builder, reinterpret_cast<FlatPtr>(value.data())); + } else if (m_mode == Mode::Default || m_mode == Mode::HexDump) { + m_mode = Mode::HexDump; + Formatter<StringView>::format(builder, value); + } else { + Formatter<StringView>::format(builder, value); + } + } +}; + +template<> +struct Formatter<Bytes> : Formatter<ReadonlyBytes> { +}; + template<> struct Formatter<const char*> : Formatter<StringView> { void format(FormatBuilder& builder, const char* value) |