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