llvm.org GIT mirror llvm / 906d5b4
raw_ostream: Add the capability for subclasses to manually install an external buffer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79382 91177308-0d34-0410-b5e6-96231b3b80d8 Daniel Dunbar 10 years ago
2 changed file(s) with 73 addition(s) and 32 deletion(s). Raw diff Collapse all Expand all
4141 /// need to take the slow path to write a single character.
4242 ///
4343 /// The buffer is in one of three states:
44 /// 1. Unbuffered (Unbuffered == true)
45 /// 1. Uninitialized (Unbuffered == false && OutBufStart == 0).
46 /// 2. Buffered (Unbuffered == false && OutBufStart != 0 &&
44 /// 1. Unbuffered (BufferMode == Unbuffered)
45 /// 1. Uninitialized (BufferMode != Unbuffered && OutBufStart == 0).
46 /// 2. Buffered (BufferMode != Unbuffered && OutBufStart != 0 &&
4747 /// OutBufEnd - OutBufStart >= 64).
48 ///
49 /// If buffered, then the raw_ostream owns the buffer if (BufferMode ==
50 /// InternalBuffer); otherwise the buffer has been set via SetBuffer and is
51 /// managed by the subclass.
52 ///
53 /// If a subclass installs an external buffer using SetBuffer then it can wait
54 /// for a \see write_impl() call to handle the data which has been put into
55 /// this buffer.
4856 char *OutBufStart, *OutBufEnd, *OutBufCur;
49 bool Unbuffered;
57
58 enum BufferKind {
59 Unbuffered = 0,
60 InternalBuffer,
61 ExternalBuffer
62 } BufferMode;
5063
5164 /// Error This flag is true if an error of any kind has been detected.
5265 ///
6780 };
6881
6982 explicit raw_ostream(bool unbuffered=false)
70 : Unbuffered(unbuffered), Error(false) {
83 : BufferMode(unbuffered ? Unbuffered : InternalBuffer), Error(false) {
7184 // Start out ready to flush.
7285 OutBufStart = OutBufEnd = OutBufCur = 0;
7386 }
99112 /// determined buffer size.
100113 void SetBuffered();
101114
102 /// SetBufferrSize - Set the stream to be buffered, using the
115 /// SetBufferSize - Set the stream to be buffered, using the
103116 /// specified buffer size.
104 void SetBufferSize(size_t Size);
117 void SetBufferSize(size_t Size) {
118 flush();
119 SetBufferAndMode(new char[Size], Size, InternalBuffer);
120 }
105121
106122 size_t GetBufferSize() {
107123 // If we're supposed to be buffered but haven't actually gotten around
117133 /// unbuffered, the stream will flush after every write. This routine
118134 /// will also flush the buffer immediately when the stream is being
119135 /// set to unbuffered.
120 void SetUnbuffered();
136 void SetUnbuffered() {
137 flush();
138 SetBufferAndMode(0, 0, Unbuffered);
139 }
121140
122141 size_t GetNumBytesInBuffer() const {
123142 return OutBufCur - OutBufStart;
174193 return *this;
175194 }
176195
177 raw_ostream &operator<<(const std::string& Str) {
196 raw_ostream &operator<<(const std::string &Str) {
197 // Avoid the fast path, it would only increase code size for a marginal win.
198
178199 write(Str.data(), Str.length());
179200 return *this;
180201 }
231252 /// by subclasses. This writes the \args Size bytes starting at
232253 /// \arg Ptr to the underlying stream.
233254 ///
255 /// This function is guaranteed to only be called at a point at which it is
256 /// safe for the subclass to install a new buffer via SetBuffer.
257 ///
258 /// \arg Ptr - The start of the data to be written. For buffered streams this
259 /// is guaranteed to be the start of the buffer.
260 /// \arg Size - The number of bytes to be written.
261 ///
234262 /// \invariant { Size > 0 }
235263 virtual void write_impl(const char *Ptr, size_t Size) = 0;
236264
242270 virtual uint64_t current_pos() = 0;
243271
244272 protected:
273 /// SetBuffer - Use the provided buffer as the raw_ostream buffer. This is
274 /// intended for use only by subclasses which can arrange for the output to go
275 /// directly into the desired output buffer, instead of being copied on each
276 /// flush.
277 void SetBuffer(char *BufferStart, size_t Size) {
278 SetBufferAndMode(BufferStart, Size, ExternalBuffer);
279 }
280
245281 /// preferred_buffer_size - Return an efficient buffer size for the
246282 /// underlying output mechanism.
247283 virtual size_t preferred_buffer_size();
258294 // Private Interface
259295 //===--------------------------------------------------------------------===//
260296 private:
297 /// SetBufferAndMode - Install the given buffer and mode.
298 void SetBufferAndMode(char *BufferStart, size_t Size, BufferKind Mode);
299
261300 /// flush_nonempty - Flush the current buffer, which is known to be
262301 /// non-empty. This outputs the currently buffered data and resets
263302 /// the buffer to empty.
421460 /// counting the bytes currently in the buffer.
422461 virtual uint64_t current_pos();
423462 public:
424 explicit raw_svector_ostream(SmallVectorImpl &O) : OS(O) {}
463 explicit raw_svector_ostream(SmallVectorImpl &O);
425464 ~raw_svector_ostream();
426465
427466 /// tell - Return the current offset with the stream.
5151 assert(OutBufCur == OutBufStart &&
5252 "raw_ostream destructor called with non-empty buffer!");
5353
54 delete [] OutBufStart;
54 if (BufferMode == InternalBuffer)
55 delete [] OutBufStart;
5556
5657 // If there are any pending errors, report them now. Clients wishing
5758 // to avoid llvm_report_error calls should check for errors with
7879 SetUnbuffered();
7980 }
8081
81 void raw_ostream::SetBufferSize(size_t Size) {
82 assert(Size >= 64 &&
83 "Buffer size must be somewhat large for invariants to hold");
84 flush();
85
86 delete [] OutBufStart;
87 OutBufStart = new char[Size];
82 void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size,
83 BufferKind Mode) {
84 assert(((Mode == Unbuffered && BufferStart == 0 && Size == 0) ||
85 (Mode != Unbuffered && BufferStart && Size >= 64)) &&
86 "stream must be unbuffered, or have >= 64 bytes of buffer");
87 // Make sure the current buffer is free of content (we can't flush here; the
88 // child buffer management logic will be in write_impl).
89 assert(GetNumBytesInBuffer() == 0 && "Current buffer is non-empty!");
90
91 if (BufferMode == InternalBuffer)
92 delete [] OutBufStart;
93 OutBufStart = BufferStart;
8894 OutBufEnd = OutBufStart+Size;
8995 OutBufCur = OutBufStart;
90 Unbuffered = false;
91 }
92
93 void raw_ostream::SetUnbuffered() {
94 flush();
95
96 delete [] OutBufStart;
97 OutBufStart = OutBufEnd = OutBufCur = 0;
98 Unbuffered = true;
96 BufferMode = Mode;
9997 }
10098
10199 raw_ostream &raw_ostream::operator<<(unsigned long N) {
179177
180178 void raw_ostream::flush_nonempty() {
181179 assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty.");
182 write_impl(OutBufStart, OutBufCur - OutBufStart);
183 OutBufCur = OutBufStart;
180 size_t Length = OutBufCur - OutBufStart;
181 OutBufCur = OutBufStart;
182 write_impl(OutBufStart, Length);
184183 }
185184
186185 raw_ostream &raw_ostream::write(unsigned char C) {
187186 // Group exceptional cases into a single branch.
188187 if (OutBufCur >= OutBufEnd) {
189 if (Unbuffered) {
188 if (BufferMode == Unbuffered) {
190189 write_impl(reinterpret_cast(&C), 1);
191190 return *this;
192191 }
197196 SetBuffered();
198197 // It's possible for the underlying stream to decline
199198 // buffering, so check this condition again.
200 if (Unbuffered) {
199 if (BufferMode == Unbuffered) {
201200 write_impl(reinterpret_cast(&C), 1);
202201 return *this;
203202 }
212211 // Group exceptional cases into a single branch.
213212 if (BUILTIN_EXPECT(OutBufCur+Size > OutBufEnd, false)) {
214213 if (BUILTIN_EXPECT(!OutBufStart, false)) {
215 if (Unbuffered) {
214 if (BufferMode == Unbuffered) {
216215 write_impl(Ptr, Size);
217216 return *this;
218217 }
497496 // raw_svector_ostream
498497 //===----------------------------------------------------------------------===//
499498
499 raw_svector_ostream::raw_svector_ostream(SmallVectorImpl &O) : OS(O) {
500 }
501
500502 raw_svector_ostream::~raw_svector_ostream() {
501503 flush();
502504 }