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