LLVM API Documentation
00001 //===-- llvm/Support/FormattedStream.h - Formatted streams ------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file contains raw_ostream implementations for streams to do 00011 // things like pretty-print comments. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_SUPPORT_FORMATTEDSTREAM_H 00016 #define LLVM_SUPPORT_FORMATTEDSTREAM_H 00017 00018 #include "llvm/Support/raw_ostream.h" 00019 #include <utility> 00020 00021 namespace llvm { 00022 00023 /// formatted_raw_ostream - A raw_ostream that wraps another one and keeps track 00024 /// of line and column position, allowing padding out to specific column 00025 /// boundaries and querying the number of lines written to the stream. 00026 /// 00027 class formatted_raw_ostream : public raw_ostream { 00028 public: 00029 /// DELETE_STREAM - Tell the destructor to delete the held stream. 00030 /// 00031 static const bool DELETE_STREAM = true; 00032 00033 /// PRESERVE_STREAM - Tell the destructor to not delete the held 00034 /// stream. 00035 /// 00036 static const bool PRESERVE_STREAM = false; 00037 00038 private: 00039 /// TheStream - The real stream we output to. We set it to be 00040 /// unbuffered, since we're already doing our own buffering. 00041 /// 00042 raw_ostream *TheStream; 00043 00044 /// DeleteStream - Do we need to delete TheStream in the 00045 /// destructor? 00046 /// 00047 bool DeleteStream; 00048 00049 /// Position - The current output column and line of the data that's 00050 /// been flushed and the portion of the buffer that's been 00051 /// scanned. The line and column scheme is zero-based. 00052 /// 00053 std::pair<unsigned, unsigned> Position; 00054 00055 /// Scanned - This points to one past the last character in the 00056 /// buffer we've scanned. 00057 /// 00058 const char *Scanned; 00059 00060 void write_impl(const char *Ptr, size_t Size) override; 00061 00062 /// current_pos - Return the current position within the stream, 00063 /// not counting the bytes currently in the buffer. 00064 uint64_t current_pos() const override { 00065 // Our current position in the stream is all the contents which have been 00066 // written to the underlying stream (*not* the current position of the 00067 // underlying stream). 00068 return TheStream->tell(); 00069 } 00070 00071 /// ComputePosition - Examine the given output buffer and figure out the new 00072 /// position after output. 00073 /// 00074 void ComputePosition(const char *Ptr, size_t size); 00075 00076 public: 00077 /// formatted_raw_ostream - Open the specified file for 00078 /// writing. If an error occurs, information about the error is 00079 /// put into ErrorInfo, and the stream should be immediately 00080 /// destroyed; the string will be empty if no error occurred. 00081 /// 00082 /// As a side effect, the given Stream is set to be Unbuffered. 00083 /// This is because formatted_raw_ostream does its own buffering, 00084 /// so it doesn't want another layer of buffering to be happening 00085 /// underneath it. 00086 /// 00087 formatted_raw_ostream(raw_ostream &Stream, bool Delete = false) 00088 : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) { 00089 setStream(Stream, Delete); 00090 } 00091 explicit formatted_raw_ostream() 00092 : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) { 00093 Scanned = nullptr; 00094 } 00095 00096 ~formatted_raw_ostream() { 00097 flush(); 00098 releaseStream(); 00099 } 00100 00101 void setStream(raw_ostream &Stream, bool Delete = false) { 00102 releaseStream(); 00103 00104 TheStream = &Stream; 00105 DeleteStream = Delete; 00106 00107 // This formatted_raw_ostream inherits from raw_ostream, so it'll do its 00108 // own buffering, and it doesn't need or want TheStream to do another 00109 // layer of buffering underneath. Resize the buffer to what TheStream 00110 // had been using, and tell TheStream not to do its own buffering. 00111 if (size_t BufferSize = TheStream->GetBufferSize()) 00112 SetBufferSize(BufferSize); 00113 else 00114 SetUnbuffered(); 00115 TheStream->SetUnbuffered(); 00116 00117 Scanned = nullptr; 00118 } 00119 00120 /// PadToColumn - Align the output to some column number. If the current 00121 /// column is already equal to or more than NewCol, PadToColumn inserts one 00122 /// space. 00123 /// 00124 /// \param NewCol - The column to move to. 00125 formatted_raw_ostream &PadToColumn(unsigned NewCol); 00126 00127 /// getColumn - Return the column number 00128 unsigned getColumn() { return Position.first; } 00129 00130 /// getLine - Return the line number 00131 unsigned getLine() { return Position.second; } 00132 00133 raw_ostream &resetColor() override { 00134 TheStream->resetColor(); 00135 return *this; 00136 } 00137 00138 raw_ostream &reverseColor() override { 00139 TheStream->reverseColor(); 00140 return *this; 00141 } 00142 00143 raw_ostream &changeColor(enum Colors Color, bool Bold, bool BG) override { 00144 TheStream->changeColor(Color, Bold, BG); 00145 return *this; 00146 } 00147 00148 bool is_displayed() const override { 00149 return TheStream->is_displayed(); 00150 } 00151 00152 private: 00153 void releaseStream() { 00154 // Delete the stream if needed. Otherwise, transfer the buffer 00155 // settings from this raw_ostream back to the underlying stream. 00156 if (!TheStream) 00157 return; 00158 if (DeleteStream) 00159 delete TheStream; 00160 else if (size_t BufferSize = GetBufferSize()) 00161 TheStream->SetBufferSize(BufferSize); 00162 else 00163 TheStream->SetUnbuffered(); 00164 } 00165 }; 00166 00167 /// fouts() - This returns a reference to a formatted_raw_ostream for 00168 /// standard output. Use it like: fouts() << "foo" << "bar"; 00169 formatted_raw_ostream &fouts(); 00170 00171 /// ferrs() - This returns a reference to a formatted_raw_ostream for 00172 /// standard error. Use it like: ferrs() << "foo" << "bar"; 00173 formatted_raw_ostream &ferrs(); 00174 00175 /// fdbgs() - This returns a reference to a formatted_raw_ostream for 00176 /// debug output. Use it like: fdbgs() << "foo" << "bar"; 00177 formatted_raw_ostream &fdbgs(); 00178 00179 } // end llvm namespace 00180 00181 00182 #endif