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