1 //===-- llvm/Support/circular_raw_ostream.h - Buffered streams --*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains raw_ostream implementations for streams to do circular 11 // buffering of their output. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H 16 #define LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H 17 18 #include "llvm/Support/raw_ostream.h" 19 20 namespace llvm { 21 /// circular_raw_ostream - A raw_ostream which *can* save its data 22 /// to a circular buffer, or can pass it through directly to an 23 /// underlying stream if specified with a buffer of zero. 24 /// 25 class circular_raw_ostream : public raw_ostream { 26 public: 27 /// TAKE_OWNERSHIP - Tell this stream that it owns the underlying 28 /// stream and is responsible for cleanup, memory management 29 /// issues, etc. 30 /// 31 static const bool TAKE_OWNERSHIP = true; 32 33 /// REFERENCE_ONLY - Tell this stream it should not manage the 34 /// held stream. 35 /// 36 static const bool REFERENCE_ONLY = false; 37 38 private: 39 /// TheStream - The real stream we output to. We set it to be 40 /// unbuffered, since we're already doing our own buffering. 41 /// 42 raw_ostream *TheStream; 43 44 /// OwnsStream - Are we responsible for managing the underlying 45 /// stream? 46 /// 47 bool OwnsStream; 48 49 /// BufferSize - The size of the buffer in bytes. 50 /// 51 size_t BufferSize; 52 53 /// BufferArray - The actual buffer storage. 54 /// 55 char *BufferArray; 56 57 /// Cur - Pointer to the current output point in BufferArray. 58 /// 59 char *Cur; 60 61 /// Filled - Indicate whether the buffer has been completely 62 /// filled. This helps avoid garbage output. 63 /// 64 bool Filled; 65 66 /// Banner - A pointer to a banner to print before dumping the 67 /// log. 68 /// 69 const char *Banner; 70 71 /// flushBuffer - Dump the contents of the buffer to Stream. 72 /// 73 void flushBuffer() { 74 if (Filled) 75 // Write the older portion of the buffer. 76 TheStream->write(Cur, BufferArray + BufferSize - Cur); 77 // Write the newer portion of the buffer. 78 TheStream->write(BufferArray, Cur - BufferArray); 79 Cur = BufferArray; 80 Filled = false; 81 } 82 83 void write_impl(const char *Ptr, size_t Size) override; 84 85 /// current_pos - Return the current position within the stream, 86 /// not counting the bytes currently in the buffer. 87 /// 88 uint64_t current_pos() const override { 89 // This has the same effect as calling TheStream.current_pos(), 90 // but that interface is private. 91 return TheStream->tell() - TheStream->GetNumBytesInBuffer(); 92 } 93 94 public: 95 /// circular_raw_ostream - Construct an optionally 96 /// circular-buffered stream, handing it an underlying stream to 97 /// do the "real" output. 98 /// 99 /// As a side effect, if BuffSize is nonzero, the given Stream is 100 /// set to be Unbuffered. This is because circular_raw_ostream 101 /// does its own buffering, so it doesn't want another layer of 102 /// buffering to be happening underneath it. 103 /// 104 /// "Owns" tells the circular_raw_ostream whether it is 105 /// responsible for managing the held stream, doing memory 106 /// management of it, etc. 107 /// 108 circular_raw_ostream(raw_ostream &Stream, const char *Header, 109 size_t BuffSize = 0, bool Owns = REFERENCE_ONLY) 110 : raw_ostream(/*unbuffered*/ true), TheStream(nullptr), 111 OwnsStream(Owns), BufferSize(BuffSize), BufferArray(nullptr), 112 Filled(false), Banner(Header) { 113 if (BufferSize != 0) 114 BufferArray = new char[BufferSize]; 115 Cur = BufferArray; 116 setStream(Stream, Owns); 117 } 118 119 ~circular_raw_ostream() override { 120 flush(); 121 flushBufferWithBanner(); 122 releaseStream(); 123 delete[] BufferArray; 124 } 125 126 /// setStream - Tell the circular_raw_ostream to output a 127 /// different stream. "Owns" tells circular_raw_ostream whether 128 /// it should take responsibility for managing the underlying 129 /// stream. 130 /// 131 void setStream(raw_ostream &Stream, bool Owns = REFERENCE_ONLY) { 132 releaseStream(); 133 TheStream = &Stream; 134 OwnsStream = Owns; 135 } 136 137 /// flushBufferWithBanner - Force output of the buffer along with 138 /// a small header. 139 /// 140 void flushBufferWithBanner(); 141 142 private: 143 /// releaseStream - Delete the held stream if needed. Otherwise, 144 /// transfer the buffer settings from this circular_raw_ostream 145 /// back to the underlying stream. 146 /// 147 void releaseStream() { 148 if (!TheStream) 149 return; 150 if (OwnsStream) 151 delete TheStream; 152 } 153 }; 154 } // end llvm namespace 155 156 #endif 157