LLVM API Documentation
00001 //===-- llvm/Support/circular_raw_ostream.h - Buffered 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 circular 00011 // buffering of their output. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H 00016 #define LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H 00017 00018 #include "llvm/Support/raw_ostream.h" 00019 00020 namespace llvm 00021 { 00022 /// circular_raw_ostream - A raw_ostream which *can* save its data 00023 /// to a circular buffer, or can pass it through directly to an 00024 /// underlying stream if specified with a buffer of zero. 00025 /// 00026 class circular_raw_ostream : public raw_ostream { 00027 public: 00028 /// TAKE_OWNERSHIP - Tell this stream that it owns the underlying 00029 /// stream and is responsible for cleanup, memory management 00030 /// issues, etc. 00031 /// 00032 static const bool TAKE_OWNERSHIP = true; 00033 00034 /// REFERENCE_ONLY - Tell this stream it should not manage the 00035 /// held stream. 00036 /// 00037 static const bool REFERENCE_ONLY = false; 00038 00039 private: 00040 /// TheStream - The real stream we output to. We set it to be 00041 /// unbuffered, since we're already doing our own buffering. 00042 /// 00043 raw_ostream *TheStream; 00044 00045 /// OwnsStream - Are we responsible for managing the underlying 00046 /// stream? 00047 /// 00048 bool OwnsStream; 00049 00050 /// BufferSize - The size of the buffer in bytes. 00051 /// 00052 size_t BufferSize; 00053 00054 /// BufferArray - The actual buffer storage. 00055 /// 00056 char *BufferArray; 00057 00058 /// Cur - Pointer to the current output point in BufferArray. 00059 /// 00060 char *Cur; 00061 00062 /// Filled - Indicate whether the buffer has been completely 00063 /// filled. This helps avoid garbage output. 00064 /// 00065 bool Filled; 00066 00067 /// Banner - A pointer to a banner to print before dumping the 00068 /// log. 00069 /// 00070 const char *Banner; 00071 00072 /// flushBuffer - Dump the contents of the buffer to Stream. 00073 /// 00074 void flushBuffer() { 00075 if (Filled) 00076 // Write the older portion of the buffer. 00077 TheStream->write(Cur, BufferArray + BufferSize - Cur); 00078 // Write the newer portion of the buffer. 00079 TheStream->write(BufferArray, Cur - BufferArray); 00080 Cur = BufferArray; 00081 Filled = false; 00082 } 00083 00084 void write_impl(const char *Ptr, size_t Size) override; 00085 00086 /// current_pos - Return the current position within the stream, 00087 /// not counting the bytes currently in the buffer. 00088 /// 00089 uint64_t current_pos() const override { 00090 // This has the same effect as calling TheStream.current_pos(), 00091 // but that interface is private. 00092 return TheStream->tell() - TheStream->GetNumBytesInBuffer(); 00093 } 00094 00095 public: 00096 /// circular_raw_ostream - Construct an optionally 00097 /// circular-buffered stream, handing it an underlying stream to 00098 /// do the "real" output. 00099 /// 00100 /// As a side effect, if BuffSize is nonzero, the given Stream is 00101 /// set to be Unbuffered. This is because circular_raw_ostream 00102 /// does its own buffering, so it doesn't want another layer of 00103 /// buffering to be happening underneath it. 00104 /// 00105 /// "Owns" tells the circular_raw_ostream whether it is 00106 /// responsible for managing the held stream, doing memory 00107 /// management of it, etc. 00108 /// 00109 circular_raw_ostream(raw_ostream &Stream, const char *Header, 00110 size_t BuffSize = 0, bool Owns = REFERENCE_ONLY) 00111 : raw_ostream(/*unbuffered*/true), 00112 TheStream(nullptr), 00113 OwnsStream(Owns), 00114 BufferSize(BuffSize), 00115 BufferArray(nullptr), 00116 Filled(false), 00117 Banner(Header) { 00118 if (BufferSize != 0) 00119 BufferArray = new char[BufferSize]; 00120 Cur = BufferArray; 00121 setStream(Stream, Owns); 00122 } 00123 explicit circular_raw_ostream() 00124 : raw_ostream(/*unbuffered*/true), 00125 TheStream(nullptr), 00126 OwnsStream(REFERENCE_ONLY), 00127 BufferArray(nullptr), 00128 Filled(false), 00129 Banner("") { 00130 Cur = BufferArray; 00131 } 00132 00133 ~circular_raw_ostream() { 00134 flush(); 00135 flushBufferWithBanner(); 00136 releaseStream(); 00137 delete[] BufferArray; 00138 } 00139 00140 /// setStream - Tell the circular_raw_ostream to output a 00141 /// different stream. "Owns" tells circular_raw_ostream whether 00142 /// it should take responsibility for managing the underlying 00143 /// stream. 00144 /// 00145 void setStream(raw_ostream &Stream, bool Owns = REFERENCE_ONLY) { 00146 releaseStream(); 00147 TheStream = &Stream; 00148 OwnsStream = Owns; 00149 } 00150 00151 /// flushBufferWithBanner - Force output of the buffer along with 00152 /// a small header. 00153 /// 00154 void flushBufferWithBanner(); 00155 00156 private: 00157 /// releaseStream - Delete the held stream if needed. Otherwise, 00158 /// transfer the buffer settings from this circular_raw_ostream 00159 /// back to the underlying stream. 00160 /// 00161 void releaseStream() { 00162 if (!TheStream) 00163 return; 00164 if (OwnsStream) 00165 delete TheStream; 00166 } 00167 }; 00168 } // end llvm namespace 00169 00170 00171 #endif