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