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