1201360Srdivacky//===-- llvm/Support/circular_raw_ostream.h - Buffered streams --*- C++ -*-===// 2201360Srdivacky// 3201360Srdivacky// The LLVM Compiler Infrastructure 4201360Srdivacky// 5201360Srdivacky// This file is distributed under the University of Illinois Open Source 6201360Srdivacky// License. See LICENSE.TXT for details. 7201360Srdivacky// 8201360Srdivacky//===----------------------------------------------------------------------===// 9201360Srdivacky// 10201360Srdivacky// This file contains raw_ostream implementations for streams to do circular 11201360Srdivacky// buffering of their output. 12201360Srdivacky// 13201360Srdivacky//===----------------------------------------------------------------------===// 14201360Srdivacky 15201360Srdivacky#ifndef LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H 16201360Srdivacky#define LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H 17201360Srdivacky 18201360Srdivacky#include "llvm/Support/raw_ostream.h" 19201360Srdivacky 20296417Sdimnamespace llvm { 21201360Srdivacky /// circular_raw_ostream - A raw_ostream which *can* save its data 22201360Srdivacky /// to a circular buffer, or can pass it through directly to an 23201360Srdivacky /// underlying stream if specified with a buffer of zero. 24201360Srdivacky /// 25201360Srdivacky class circular_raw_ostream : public raw_ostream { 26201360Srdivacky public: 27201360Srdivacky /// TAKE_OWNERSHIP - Tell this stream that it owns the underlying 28201360Srdivacky /// stream and is responsible for cleanup, memory management 29201360Srdivacky /// issues, etc. 30201360Srdivacky /// 31201360Srdivacky static const bool TAKE_OWNERSHIP = true; 32201360Srdivacky 33201360Srdivacky /// REFERENCE_ONLY - Tell this stream it should not manage the 34201360Srdivacky /// held stream. 35201360Srdivacky /// 36201360Srdivacky static const bool REFERENCE_ONLY = false; 37201360Srdivacky 38201360Srdivacky private: 39201360Srdivacky /// TheStream - The real stream we output to. We set it to be 40201360Srdivacky /// unbuffered, since we're already doing our own buffering. 41201360Srdivacky /// 42201360Srdivacky raw_ostream *TheStream; 43201360Srdivacky 44201360Srdivacky /// OwnsStream - Are we responsible for managing the underlying 45201360Srdivacky /// stream? 46201360Srdivacky /// 47201360Srdivacky bool OwnsStream; 48201360Srdivacky 49201360Srdivacky /// BufferSize - The size of the buffer in bytes. 50201360Srdivacky /// 51201360Srdivacky size_t BufferSize; 52201360Srdivacky 53201360Srdivacky /// BufferArray - The actual buffer storage. 54201360Srdivacky /// 55201360Srdivacky char *BufferArray; 56201360Srdivacky 57201360Srdivacky /// Cur - Pointer to the current output point in BufferArray. 58201360Srdivacky /// 59201360Srdivacky char *Cur; 60201360Srdivacky 61201360Srdivacky /// Filled - Indicate whether the buffer has been completely 62201360Srdivacky /// filled. This helps avoid garbage output. 63201360Srdivacky /// 64201360Srdivacky bool Filled; 65201360Srdivacky 66201360Srdivacky /// Banner - A pointer to a banner to print before dumping the 67201360Srdivacky /// log. 68201360Srdivacky /// 69201360Srdivacky const char *Banner; 70201360Srdivacky 71201360Srdivacky /// flushBuffer - Dump the contents of the buffer to Stream. 72201360Srdivacky /// 73249423Sdim void flushBuffer() { 74201360Srdivacky if (Filled) 75201360Srdivacky // Write the older portion of the buffer. 76201360Srdivacky TheStream->write(Cur, BufferArray + BufferSize - Cur); 77201360Srdivacky // Write the newer portion of the buffer. 78201360Srdivacky TheStream->write(BufferArray, Cur - BufferArray); 79201360Srdivacky Cur = BufferArray; 80201360Srdivacky Filled = false; 81201360Srdivacky } 82201360Srdivacky 83276479Sdim void write_impl(const char *Ptr, size_t Size) override; 84201360Srdivacky 85201360Srdivacky /// current_pos - Return the current position within the stream, 86201360Srdivacky /// not counting the bytes currently in the buffer. 87201360Srdivacky /// 88276479Sdim uint64_t current_pos() const override { 89201360Srdivacky // This has the same effect as calling TheStream.current_pos(), 90201360Srdivacky // but that interface is private. 91201360Srdivacky return TheStream->tell() - TheStream->GetNumBytesInBuffer(); 92201360Srdivacky } 93201360Srdivacky 94201360Srdivacky public: 95201360Srdivacky /// circular_raw_ostream - Construct an optionally 96201360Srdivacky /// circular-buffered stream, handing it an underlying stream to 97201360Srdivacky /// do the "real" output. 98201360Srdivacky /// 99201360Srdivacky /// As a side effect, if BuffSize is nonzero, the given Stream is 100201360Srdivacky /// set to be Unbuffered. This is because circular_raw_ostream 101201360Srdivacky /// does its own buffering, so it doesn't want another layer of 102201360Srdivacky /// buffering to be happening underneath it. 103201360Srdivacky /// 104201360Srdivacky /// "Owns" tells the circular_raw_ostream whether it is 105201360Srdivacky /// responsible for managing the held stream, doing memory 106201360Srdivacky /// management of it, etc. 107201360Srdivacky /// 108201360Srdivacky circular_raw_ostream(raw_ostream &Stream, const char *Header, 109288943Sdim size_t BuffSize = 0, bool Owns = REFERENCE_ONLY) 110288943Sdim : raw_ostream(/*unbuffered*/ true), TheStream(nullptr), 111288943Sdim OwnsStream(Owns), BufferSize(BuffSize), BufferArray(nullptr), 112288943Sdim Filled(false), Banner(Header) { 113201360Srdivacky if (BufferSize != 0) 114201360Srdivacky BufferArray = new char[BufferSize]; 115201360Srdivacky Cur = BufferArray; 116201360Srdivacky setStream(Stream, Owns); 117201360Srdivacky } 118201360Srdivacky 119288943Sdim ~circular_raw_ostream() override { 120201360Srdivacky flush(); 121201360Srdivacky flushBufferWithBanner(); 122201360Srdivacky releaseStream(); 123201360Srdivacky delete[] BufferArray; 124201360Srdivacky } 125201360Srdivacky 126201360Srdivacky /// setStream - Tell the circular_raw_ostream to output a 127201360Srdivacky /// different stream. "Owns" tells circular_raw_ostream whether 128201360Srdivacky /// it should take responsibility for managing the underlying 129201360Srdivacky /// stream. 130201360Srdivacky /// 131201360Srdivacky void setStream(raw_ostream &Stream, bool Owns = REFERENCE_ONLY) { 132201360Srdivacky releaseStream(); 133201360Srdivacky TheStream = &Stream; 134201360Srdivacky OwnsStream = Owns; 135201360Srdivacky } 136201360Srdivacky 137201360Srdivacky /// flushBufferWithBanner - Force output of the buffer along with 138201360Srdivacky /// a small header. 139201360Srdivacky /// 140249423Sdim void flushBufferWithBanner(); 141201360Srdivacky 142201360Srdivacky private: 143201360Srdivacky /// releaseStream - Delete the held stream if needed. Otherwise, 144201360Srdivacky /// transfer the buffer settings from this circular_raw_ostream 145201360Srdivacky /// back to the underlying stream. 146201360Srdivacky /// 147201360Srdivacky void releaseStream() { 148201360Srdivacky if (!TheStream) 149201360Srdivacky return; 150201360Srdivacky if (OwnsStream) 151201360Srdivacky delete TheStream; 152201360Srdivacky } 153201360Srdivacky }; 154201360Srdivacky} // end llvm namespace 155201360Srdivacky 156201360Srdivacky#endif 157