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/ADT/SmallString.h" 18 #include "llvm/Support/raw_ostream.h" 19 #include <utility> 20 21 namespace llvm { 22 23 /// formatted_raw_ostream - A raw_ostream that wraps another one and keeps track 24 /// of line and column position, allowing padding out to specific column 25 /// boundaries and querying the number of lines written to the stream. This 26 /// assumes that the contents of the stream is valid UTF-8 encoded text. This 27 /// doesn't attempt to handle everything Unicode can do (combining characters, 28 /// right-to-left markers, etc), but should cover the cases likely to appear in 29 /// source code or diagnostic messages. 30 class formatted_raw_ostream : public raw_ostream { 31 /// TheStream - The real stream we output to. We set it to be 32 /// unbuffered, since we're already doing our own buffering. 33 /// 34 raw_ostream *TheStream; 35 36 /// Position - The current output column and line of the data that's 37 /// been flushed and the portion of the buffer that's been 38 /// scanned. The line and column scheme is zero-based. 39 /// 40 std::pair<unsigned, unsigned> Position; 41 42 /// Scanned - This points to one past the last character in the 43 /// buffer we've scanned. 44 /// 45 const char *Scanned; 46 47 /// PartialUTF8Char - Either empty or a prefix of a UTF-8 code unit sequence 48 /// for a Unicode scalar value which should be prepended to the buffer for the 49 /// next call to ComputePosition. This is needed when the buffer is flushed 50 /// when it ends part-way through the UTF-8 encoding of a Unicode scalar 51 /// value, so that we can compute the display width of the character once we 52 /// have the rest of it. 53 SmallString<4> PartialUTF8Char; 54 55 void write_impl(const char *Ptr, size_t Size) override; 56 57 /// current_pos - Return the current position within the stream, 58 /// not counting the bytes currently in the buffer. current_pos()59 uint64_t current_pos() const override { 60 // Our current position in the stream is all the contents which have been 61 // written to the underlying stream (*not* the current position of the 62 // underlying stream). 63 return TheStream->tell(); 64 } 65 66 /// ComputePosition - Examine the given output buffer and figure out the new 67 /// position after output. This is safe to call multiple times on the same 68 /// buffer, as it records the most recently scanned character and resumes from 69 /// there when the buffer has not been flushed. 70 void ComputePosition(const char *Ptr, size_t size); 71 72 /// UpdatePosition - scan the characters in [Ptr, Ptr+Size), and update the 73 /// line and column numbers. Unlike ComputePosition, this must be called 74 /// exactly once on each region of the buffer. 75 void UpdatePosition(const char *Ptr, size_t Size); 76 setStream(raw_ostream & Stream)77 void setStream(raw_ostream &Stream) { 78 releaseStream(); 79 80 TheStream = &Stream; 81 82 // This formatted_raw_ostream inherits from raw_ostream, so it'll do its 83 // own buffering, and it doesn't need or want TheStream to do another 84 // layer of buffering underneath. Resize the buffer to what TheStream 85 // had been using, and tell TheStream not to do its own buffering. 86 if (size_t BufferSize = TheStream->GetBufferSize()) 87 SetBufferSize(BufferSize); 88 else 89 SetUnbuffered(); 90 TheStream->SetUnbuffered(); 91 92 Scanned = nullptr; 93 } 94 95 public: 96 /// formatted_raw_ostream - Open the specified file for 97 /// writing. If an error occurs, information about the error is 98 /// put into ErrorInfo, and the stream should be immediately 99 /// destroyed; the string will be empty if no error occurred. 100 /// 101 /// As a side effect, the given Stream is set to be Unbuffered. 102 /// This is because formatted_raw_ostream does its own buffering, 103 /// so it doesn't want another layer of buffering to be happening 104 /// underneath it. 105 /// formatted_raw_ostream(raw_ostream & Stream)106 formatted_raw_ostream(raw_ostream &Stream) 107 : TheStream(nullptr), Position(0, 0) { 108 setStream(Stream); 109 } formatted_raw_ostream()110 explicit formatted_raw_ostream() : TheStream(nullptr), Position(0, 0) { 111 Scanned = nullptr; 112 } 113 ~formatted_raw_ostream()114 ~formatted_raw_ostream() override { 115 flush(); 116 releaseStream(); 117 } 118 119 /// PadToColumn - Align the output to some column number. If the current 120 /// column is already equal to or more than NewCol, PadToColumn inserts one 121 /// space. 122 /// 123 /// \param NewCol - The column to move to. 124 formatted_raw_ostream &PadToColumn(unsigned NewCol); 125 getColumn()126 unsigned getColumn() { 127 // Calculate current position, taking buffer contents into account. 128 ComputePosition(getBufferStart(), GetNumBytesInBuffer()); 129 return Position.first; 130 } 131 getLine()132 unsigned getLine() { 133 // Calculate current position, taking buffer contents into account. 134 ComputePosition(getBufferStart(), GetNumBytesInBuffer()); 135 return Position.second; 136 } 137 resetColor()138 raw_ostream &resetColor() override { 139 TheStream->resetColor(); 140 return *this; 141 } 142 reverseColor()143 raw_ostream &reverseColor() override { 144 TheStream->reverseColor(); 145 return *this; 146 } 147 changeColor(enum Colors Color,bool Bold,bool BG)148 raw_ostream &changeColor(enum Colors Color, bool Bold, bool BG) override { 149 TheStream->changeColor(Color, Bold, BG); 150 return *this; 151 } 152 is_displayed()153 bool is_displayed() const override { 154 return TheStream->is_displayed(); 155 } 156 157 private: releaseStream()158 void releaseStream() { 159 // Transfer the buffer settings from this raw_ostream back to the underlying 160 // stream. 161 if (!TheStream) 162 return; 163 if (size_t BufferSize = GetBufferSize()) 164 TheStream->SetBufferSize(BufferSize); 165 else 166 TheStream->SetUnbuffered(); 167 } 168 }; 169 170 /// fouts() - This returns a reference to a formatted_raw_ostream for 171 /// standard output. Use it like: fouts() << "foo" << "bar"; 172 formatted_raw_ostream &fouts(); 173 174 /// ferrs() - This returns a reference to a formatted_raw_ostream for 175 /// standard error. Use it like: ferrs() << "foo" << "bar"; 176 formatted_raw_ostream &ferrs(); 177 178 /// fdbgs() - This returns a reference to a formatted_raw_ostream for 179 /// debug output. Use it like: fdbgs() << "foo" << "bar"; 180 formatted_raw_ostream &fdbgs(); 181 182 } // end llvm namespace 183 184 185 #endif 186