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 20201360Srdivackynamespace llvm 21201360Srdivacky{ 22201360Srdivacky /// circular_raw_ostream - A raw_ostream which *can* save its data 23201360Srdivacky /// to a circular buffer, or can pass it through directly to an 24201360Srdivacky /// underlying stream if specified with a buffer of zero. 25201360Srdivacky /// 26201360Srdivacky class circular_raw_ostream : public raw_ostream { 27201360Srdivacky public: 28201360Srdivacky /// TAKE_OWNERSHIP - Tell this stream that it owns the underlying 29201360Srdivacky /// stream and is responsible for cleanup, memory management 30201360Srdivacky /// issues, etc. 31201360Srdivacky /// 32201360Srdivacky static const bool TAKE_OWNERSHIP = true; 33201360Srdivacky 34201360Srdivacky /// REFERENCE_ONLY - Tell this stream it should not manage the 35201360Srdivacky /// held stream. 36201360Srdivacky /// 37201360Srdivacky static const bool REFERENCE_ONLY = false; 38201360Srdivacky 39201360Srdivacky private: 40201360Srdivacky /// TheStream - The real stream we output to. We set it to be 41201360Srdivacky /// unbuffered, since we're already doing our own buffering. 42201360Srdivacky /// 43201360Srdivacky raw_ostream *TheStream; 44201360Srdivacky 45201360Srdivacky /// OwnsStream - Are we responsible for managing the underlying 46201360Srdivacky /// stream? 47201360Srdivacky /// 48201360Srdivacky bool OwnsStream; 49201360Srdivacky 50201360Srdivacky /// BufferSize - The size of the buffer in bytes. 51201360Srdivacky /// 52201360Srdivacky size_t BufferSize; 53201360Srdivacky 54201360Srdivacky /// BufferArray - The actual buffer storage. 55201360Srdivacky /// 56201360Srdivacky char *BufferArray; 57201360Srdivacky 58201360Srdivacky /// Cur - Pointer to the current output point in BufferArray. 59201360Srdivacky /// 60201360Srdivacky char *Cur; 61201360Srdivacky 62201360Srdivacky /// Filled - Indicate whether the buffer has been completely 63201360Srdivacky /// filled. This helps avoid garbage output. 64201360Srdivacky /// 65201360Srdivacky bool Filled; 66201360Srdivacky 67201360Srdivacky /// Banner - A pointer to a banner to print before dumping the 68201360Srdivacky /// log. 69201360Srdivacky /// 70201360Srdivacky const char *Banner; 71201360Srdivacky 72201360Srdivacky /// flushBuffer - Dump the contents of the buffer to Stream. 73201360Srdivacky /// 74249423Sdim void flushBuffer() { 75201360Srdivacky if (Filled) 76201360Srdivacky // Write the older portion of the buffer. 77201360Srdivacky TheStream->write(Cur, BufferArray + BufferSize - Cur); 78201360Srdivacky // Write the newer portion of the buffer. 79201360Srdivacky TheStream->write(BufferArray, Cur - BufferArray); 80201360Srdivacky Cur = BufferArray; 81201360Srdivacky Filled = false; 82201360Srdivacky } 83201360Srdivacky 84243830Sdim virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; 85201360Srdivacky 86201360Srdivacky /// current_pos - Return the current position within the stream, 87201360Srdivacky /// not counting the bytes currently in the buffer. 88201360Srdivacky /// 89243830Sdim virtual uint64_t current_pos() const LLVM_OVERRIDE { 90201360Srdivacky // This has the same effect as calling TheStream.current_pos(), 91201360Srdivacky // but that interface is private. 92201360Srdivacky return TheStream->tell() - TheStream->GetNumBytesInBuffer(); 93201360Srdivacky } 94201360Srdivacky 95201360Srdivacky public: 96201360Srdivacky /// circular_raw_ostream - Construct an optionally 97201360Srdivacky /// circular-buffered stream, handing it an underlying stream to 98201360Srdivacky /// do the "real" output. 99201360Srdivacky /// 100201360Srdivacky /// As a side effect, if BuffSize is nonzero, the given Stream is 101201360Srdivacky /// set to be Unbuffered. This is because circular_raw_ostream 102201360Srdivacky /// does its own buffering, so it doesn't want another layer of 103201360Srdivacky /// buffering to be happening underneath it. 104201360Srdivacky /// 105201360Srdivacky /// "Owns" tells the circular_raw_ostream whether it is 106201360Srdivacky /// responsible for managing the held stream, doing memory 107201360Srdivacky /// management of it, etc. 108201360Srdivacky /// 109201360Srdivacky circular_raw_ostream(raw_ostream &Stream, const char *Header, 110201360Srdivacky size_t BuffSize = 0, bool Owns = REFERENCE_ONLY) 111201360Srdivacky : raw_ostream(/*unbuffered*/true), 112201360Srdivacky TheStream(0), 113201360Srdivacky OwnsStream(Owns), 114201360Srdivacky BufferSize(BuffSize), 115201360Srdivacky BufferArray(0), 116201360Srdivacky Filled(false), 117201360Srdivacky Banner(Header) { 118201360Srdivacky if (BufferSize != 0) 119201360Srdivacky BufferArray = new char[BufferSize]; 120201360Srdivacky Cur = BufferArray; 121201360Srdivacky setStream(Stream, Owns); 122201360Srdivacky } 123201360Srdivacky explicit circular_raw_ostream() 124201360Srdivacky : raw_ostream(/*unbuffered*/true), 125201360Srdivacky TheStream(0), 126201360Srdivacky OwnsStream(REFERENCE_ONLY), 127201360Srdivacky BufferArray(0), 128201360Srdivacky Filled(false), 129201360Srdivacky Banner("") { 130201360Srdivacky Cur = BufferArray; 131201360Srdivacky } 132201360Srdivacky 133201360Srdivacky ~circular_raw_ostream() { 134201360Srdivacky flush(); 135201360Srdivacky flushBufferWithBanner(); 136201360Srdivacky releaseStream(); 137201360Srdivacky delete[] BufferArray; 138201360Srdivacky } 139201360Srdivacky 140201360Srdivacky /// setStream - Tell the circular_raw_ostream to output a 141201360Srdivacky /// different stream. "Owns" tells circular_raw_ostream whether 142201360Srdivacky /// it should take responsibility for managing the underlying 143201360Srdivacky /// stream. 144201360Srdivacky /// 145201360Srdivacky void setStream(raw_ostream &Stream, bool Owns = REFERENCE_ONLY) { 146201360Srdivacky releaseStream(); 147201360Srdivacky TheStream = &Stream; 148201360Srdivacky OwnsStream = Owns; 149201360Srdivacky } 150201360Srdivacky 151201360Srdivacky /// flushBufferWithBanner - Force output of the buffer along with 152201360Srdivacky /// a small header. 153201360Srdivacky /// 154249423Sdim void flushBufferWithBanner(); 155201360Srdivacky 156201360Srdivacky private: 157201360Srdivacky /// releaseStream - Delete the held stream if needed. Otherwise, 158201360Srdivacky /// transfer the buffer settings from this circular_raw_ostream 159201360Srdivacky /// back to the underlying stream. 160201360Srdivacky /// 161201360Srdivacky void releaseStream() { 162201360Srdivacky if (!TheStream) 163201360Srdivacky return; 164201360Srdivacky if (OwnsStream) 165201360Srdivacky delete TheStream; 166201360Srdivacky } 167201360Srdivacky }; 168201360Srdivacky} // end llvm namespace 169201360Srdivacky 170201360Srdivacky 171201360Srdivacky#endif 172