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