common/buffer: make hexdump look like 'hexdump -C ...'

...the better to diff them with.

Signed-off-by: Sage Weil <sage@redhat.com>
This commit is contained in:
Sage Weil 2015-12-24 10:41:08 -05:00
parent e4e1a7f41a
commit 5c6269081e

View File

@ -2097,24 +2097,58 @@ void buffer::list::write_stream(std::ostream &out) const
void buffer::list::hexdump(std::ostream &out) const
{
if (!length())
return;
std::ios_base::fmtflags original_flags = out.flags();
// do our best to match the output of hexdump -C, for better
// diff'ing!
out.setf(std::ios::right);
out.fill('0');
unsigned per = 16;
bool was_zeros = false, did_star = false;
for (unsigned o=0; o<length(); o += per) {
out << std::hex << std::setw(4) << o << " :";
bool row_is_zeros = false;
if (o + per < length()) {
row_is_zeros = true;
for (unsigned i=0; i<per && o+i<length(); i++) {
if ((*this)[o+i]) {
row_is_zeros = false;
}
}
if (row_is_zeros) {
if (was_zeros) {
if (!did_star) {
out << "*\n";
did_star = true;
}
continue;
}
was_zeros = true;
} else {
was_zeros = false;
did_star = false;
}
}
out << std::hex << std::setw(8) << o << " ";
unsigned i;
for (i=0; i<per && o+i<length(); i++) {
if (i == 8)
out << ' ';
out << " " << std::setw(2) << ((unsigned)(*this)[o+i] & 0xff);
}
for (; i<per; i++)
for (; i<per; i++) {
if (i == 8)
out << ' ';
out << " ";
}
out << " : ";
out << " |";
for (i=0; i<per && o+i<length(); i++) {
char c = (*this)[o+i];
if (isupper(c) || islower(c) || isdigit(c) || c == ' ' || ispunct(c))
@ -2122,8 +2156,9 @@ void buffer::list::hexdump(std::ostream &out) const
else
out << '.';
}
out << std::dec << std::endl;
out << '|' << std::dec << std::endl;
}
out << std::hex << std::setw(8) << length() << "\n";
out.flags(original_flags);
}