aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/raw_ostream.cpp
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2016-11-10 20:16:45 +0000
committerZachary Turner <zturner@google.com>2016-11-10 20:16:45 +0000
commit4a86af07a23a7a8ce0b8f41b912c4e77bbb984d0 (patch)
treef52e225f81c1fbd84370a9adb0a3c50b7f1c1b45 /llvm/lib/Support/raw_ostream.cpp
parent811cdc979b1c51659887e1af7ba72a6f0adcac0b (diff)
downloadllvm-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.cpp83
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';
}