Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 14 | pmbaty | 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 | /// |
||
| 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 | /// |
||
| 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) |
||
| 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 | |||
| 117 | ~circular_raw_ostream() override { |
||
| 118 | flush(); |
||
| 119 | flushBufferWithBanner(); |
||
| 120 | releaseStream(); |
||
| 121 | delete[] BufferArray; |
||
| 122 | } |
||
| 123 | |||
| 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 | /// |
||
| 149 | void releaseStream() { |
||
| 150 | if (!TheStream) |
||
| 151 | return; |
||
| 152 | if (OwnsStream) |
||
| 153 | delete TheStream; |
||
| 154 | } |
||
| 155 | }; |
||
| 156 | } // end llvm namespace |
||
| 157 | |||
| 158 | #endif |