1 //===-- llvm/Support/FormattedStream.h - Formatted streams ------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains raw_ostream implementations for streams to do 10 // things like pretty-print comments. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_SUPPORT_FORMATTEDSTREAM_H 15 #define LLVM_SUPPORT_FORMATTEDSTREAM_H 16 17 #include "llvm/Support/raw_ostream.h" 18 #include <utility> 19 20 namespace llvm { 21 22 /// formatted_raw_ostream - A raw_ostream that wraps another one and keeps track 23 /// of line and column position, allowing padding out to specific column 24 /// boundaries and querying the number of lines written to the stream. 25 /// 26 class formatted_raw_ostream : public raw_ostream { 27 /// TheStream - The real stream we output to. We set it to be 28 /// unbuffered, since we're already doing our own buffering. 29 /// 30 raw_ostream *TheStream; 31 32 /// Position - The current output column and line of the data that's 33 /// been flushed and the portion of the buffer that's been 34 /// scanned. The line and column scheme is zero-based. 35 /// 36 std::pair<unsigned, unsigned> Position; 37 38 /// Scanned - This points to one past the last character in the 39 /// buffer we've scanned. 40 /// 41 const char *Scanned; 42 43 void write_impl(const char *Ptr, size_t Size) override; 44 45 /// current_pos - Return the current position within the stream, 46 /// not counting the bytes currently in the buffer. 47 uint64_t current_pos() const override { 48 // Our current position in the stream is all the contents which have been 49 // written to the underlying stream (*not* the current position of the 50 // underlying stream). 51 return TheStream->tell(); 52 } 53 54 /// ComputePosition - Examine the given output buffer and figure out the new 55 /// position after output. 56 /// 57 void ComputePosition(const char *Ptr, size_t size); 58 59 void setStream(raw_ostream &Stream) { 60 releaseStream(); 61 62 TheStream = &Stream; 63 64 // This formatted_raw_ostream inherits from raw_ostream, so it'll do its 65 // own buffering, and it doesn't need or want TheStream to do another 66 // layer of buffering underneath. Resize the buffer to what TheStream 67 // had been using, and tell TheStream not to do its own buffering. 68 if (size_t BufferSize = TheStream->GetBufferSize()) 69 SetBufferSize(BufferSize); 70 else 71 SetUnbuffered(); 72 TheStream->SetUnbuffered(); 73 74 Scanned = nullptr; 75 } 76 77 public: 78 /// formatted_raw_ostream - Open the specified file for 79 /// writing. If an error occurs, information about the error is 80 /// put into ErrorInfo, and the stream should be immediately 81 /// destroyed; the string will be empty if no error occurred. 82 /// 83 /// As a side effect, the given Stream is set to be Unbuffered. 84 /// This is because formatted_raw_ostream does its own buffering, 85 /// so it doesn't want another layer of buffering to be happening 86 /// underneath it. 87 /// 88 formatted_raw_ostream(raw_ostream &Stream) 89 : TheStream(nullptr), Position(0, 0) { 90 setStream(Stream); 91 } 92 explicit formatted_raw_ostream() : TheStream(nullptr), Position(0, 0) { 93 Scanned = nullptr; 94 } 95 96 ~formatted_raw_ostream() override { 97 flush(); 98 releaseStream(); 99 } 100 101 /// PadToColumn - Align the output to some column number. If the current 102 /// column is already equal to or more than NewCol, PadToColumn inserts one 103 /// space. 104 /// 105 /// \param NewCol - The column to move to. 106 formatted_raw_ostream &PadToColumn(unsigned NewCol); 107 108 /// getColumn - Return the column number 109 unsigned getColumn() { return Position.first; } 110 111 /// getLine - Return the line number 112 unsigned getLine() { return Position.second; } 113 114 raw_ostream &resetColor() override { 115 TheStream->resetColor(); 116 return *this; 117 } 118 119 raw_ostream &reverseColor() override { 120 TheStream->reverseColor(); 121 return *this; 122 } 123 124 raw_ostream &changeColor(enum Colors Color, bool Bold, bool BG) override { 125 TheStream->changeColor(Color, Bold, BG); 126 return *this; 127 } 128 129 bool is_displayed() const override { 130 return TheStream->is_displayed(); 131 } 132 133 private: 134 void releaseStream() { 135 // Transfer the buffer settings from this raw_ostream back to the underlying 136 // stream. 137 if (!TheStream) 138 return; 139 if (size_t BufferSize = GetBufferSize()) 140 TheStream->SetBufferSize(BufferSize); 141 else 142 TheStream->SetUnbuffered(); 143 } 144 }; 145 146 /// fouts() - This returns a reference to a formatted_raw_ostream for 147 /// standard output. Use it like: fouts() << "foo" << "bar"; 148 formatted_raw_ostream &fouts(); 149 150 /// ferrs() - This returns a reference to a formatted_raw_ostream for 151 /// standard error. Use it like: ferrs() << "foo" << "bar"; 152 formatted_raw_ostream &ferrs(); 153 154 /// fdbgs() - This returns a reference to a formatted_raw_ostream for 155 /// debug output. Use it like: fdbgs() << "foo" << "bar"; 156 formatted_raw_ostream &fdbgs(); 157 158 } // end llvm namespace 159 160 161 #endif 162