summaryrefslogtreecommitdiff
path: root/AK
diff options
context:
space:
mode:
authorAli Mohammad Pur <ali.mpfard@gmail.com>2021-06-17 13:11:00 +0430
committerAli Mohammad Pur <Ali.mpfard@gmail.com>2021-06-17 18:44:00 +0430
commit7eda164c252af8e9337fe926f5dc88059452cfed (patch)
tree3d820a44fecfea4f63c10cb83729c60bdce30693 /AK
parent10f56166e5f5b4c7ed09fddc643505ca5d759013 (diff)
downloadserenity-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.cpp38
-rw-r--r--AK/Format.h27
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)