diff options
author | Zachary Turner <zturner@google.com> | 2016-11-10 20:16:45 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2016-11-10 20:16:45 +0000 |
commit | 4a86af07a23a7a8ce0b8f41b912c4e77bbb984d0 (patch) | |
tree | f52e225f81c1fbd84370a9adb0a3c50b7f1c1b45 /llvm/lib/Support/raw_ostream.cpp | |
parent | 811cdc979b1c51659887e1af7ba72a6f0adcac0b (diff) | |
download | llvm-4a86af07a23a7a8ce0b8f41b912c4e77bbb984d0.zip llvm-4a86af07a23a7a8ce0b8f41b912c4e77bbb984d0.tar.gz llvm-4a86af07a23a7a8ce0b8f41b912c4e77bbb984d0.tar.bz2 |
[Support] Improve flexibility of binary blob formatter.
This makes it possible to indent a binary blob by a certain
number of bytes, and also makes some things more idiomatic.
Finally, it integrates this binary blob formatter into ScopedPrinter
which used to have its own implementation of this algorithm.
Differential Revision: https://reviews.llvm.org/D26477
llvm-svn: 286495
Diffstat (limited to 'llvm/lib/Support/raw_ostream.cpp')
-rw-r--r-- | llvm/lib/Support/raw_ostream.cpp | 83 |
1 files changed, 50 insertions, 33 deletions
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp index 42f121d..9acc0d8 100644 --- a/llvm/lib/Support/raw_ostream.cpp +++ b/llvm/lib/Support/raw_ostream.cpp @@ -352,55 +352,72 @@ raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) { return *this; } -raw_ostream &raw_ostream::operator<<(const FormattedHexBytes &FB) { +raw_ostream &raw_ostream::operator<<(const FormattedBytes &FB) { + if (FB.Bytes.empty()) + return *this; + size_t LineIndex = 0; - const size_t Size = FB.Bytes.size(); - HexPrintStyle OffsetStyle = - FB.Upper ? HexPrintStyle::PrefixUpper : HexPrintStyle::PrefixLower; - HexPrintStyle ByteStyle = - FB.Upper ? HexPrintStyle::Upper : HexPrintStyle::Lower; - while (LineIndex < Size) { + auto Bytes = FB.Bytes; + const size_t Size = Bytes.size(); + HexPrintStyle HPS = FB.Upper ? HexPrintStyle::Upper : HexPrintStyle::Lower; + uint64_t OffsetWidth = 0; + if (FB.FirstByteOffset.hasValue()) { + // Figure out how many nibbles are needed to print the largest offset + // represented by this data set, so that we can align the offset field + // to the right width. + size_t Lines = Size / FB.NumPerLine; + uint64_t MaxOffset = *FB.FirstByteOffset + Lines * FB.NumPerLine; + unsigned Power = 0; + if (MaxOffset > 0) + Power = llvm::Log2_64_Ceil(MaxOffset); + OffsetWidth = std::max(4ULL, llvm::alignTo(Power, 4) / 4); + } + + // The width of a block of data including all spaces for group separators. + unsigned NumByteGroups = + alignTo(FB.NumPerLine, FB.ByteGroupSize) / FB.ByteGroupSize; + unsigned BlockCharWidth = FB.NumPerLine * 2 + NumByteGroups - 1; + + while (!Bytes.empty()) { + indent(FB.IndentLevel); + if (FB.FirstByteOffset.hasValue()) { uint64_t Offset = FB.FirstByteOffset.getValue(); - llvm::write_hex(*this, Offset + LineIndex, OffsetStyle, - sizeof(Offset) * 2 + 2); + llvm::write_hex(*this, Offset + LineIndex, HPS, OffsetWidth); *this << ": "; } - // Print the hex bytes for this line - uint32_t I = 0; - for (I = 0; I < FB.NumPerLine; ++I) { - size_t Index = LineIndex + I; - if (Index >= Size) - break; - if (I && (I % FB.ByteGroupSize) == 0) + + auto Line = Bytes.take_front(FB.NumPerLine); + + size_t CharsPrinted = 0; + // Print the hex bytes for this line in groups + for (size_t I = 0; I < Line.size(); ++I, CharsPrinted += 2) { + if (I && (I % FB.ByteGroupSize) == 0) { + ++CharsPrinted; *this << " "; - llvm::write_hex(*this, FB.Bytes[Index], ByteStyle, 2); + } + llvm::write_hex(*this, Line[I], HPS, 2); } - uint32_t BytesDisplayed = I; + if (FB.ASCII) { // Print any spaces needed for any bytes that we didn't print on this // line so that the ASCII bytes are correctly aligned. - for (; I < FB.NumPerLine; ++I) { - if (I && (I % FB.ByteGroupSize) == 0) - indent(3); - else - indent(2); - } - *this << " |"; + assert(BlockCharWidth >= CharsPrinted); + indent(BlockCharWidth - CharsPrinted + 2); + *this << "|"; + // Print the ASCII char values for each byte on this line - for (I = 0; I < FB.NumPerLine; ++I) { - size_t Index = LineIndex + I; - if (Index >= Size) - break; - char ch = (char)FB.Bytes[Index]; - if (isprint(ch)) - *this << ch; + for (uint8_t Byte : Line) { + if (isprint(Byte)) + *this << static_cast<char>(Byte); else *this << '.'; } *this << '|'; } - LineIndex += BytesDisplayed; + + Bytes = Bytes.drop_front(Line.size()); + LineIndex += Line.size(); if (LineIndex < Size) *this << '\n'; } |