From 33e49ef5e5dc2d3e65bcd4fc1f20874bf3847829 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 13 Aug 2009 15:44:52 +0000 Subject: [PATCH] Fix the buffer handling logic so that write_impl is always called with a full buffer, rather than often being called with a slightly-less-than-full buffer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78907 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/raw_ostream.h | 4 +++ lib/Support/raw_ostream.cpp | 45 +++++++++++++++++------------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index f7fbe21ee3f..58de3e81867 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -261,6 +261,10 @@ private: /// non-empty. This outputs the currently buffered data and resets /// the buffer to empty. void flush_nonempty(); + + /// copy_to_buffer - Copy data into the buffer. Size must not be + /// greater than the number of unused bytes in the buffer. + void copy_to_buffer(const char *Ptr, size_t Size); }; //===----------------------------------------------------------------------===// diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp index e3ab0c688a3..11a11bd930a 100644 --- a/lib/Support/raw_ostream.cpp +++ b/lib/Support/raw_ostream.cpp @@ -164,17 +164,32 @@ raw_ostream &raw_ostream::write(unsigned char C) { raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) { // Group exceptional cases into a single branch. if (BUILTIN_EXPECT(OutBufCur+Size > OutBufEnd, false)) { - if (Unbuffered) { - write_impl(Ptr, Size); - return *this; - } - - if (!OutBufStart) + if (BUILTIN_EXPECT(!OutBufStart, false)) { + if (Unbuffered) { + write_impl(Ptr, Size); + return *this; + } + // Set up a buffer and start over. SetBufferSize(); - else + return write(Ptr, Size); + } + // Write out the data in buffer-sized blocks until the remainder + // fits within the buffer. + do { + size_t NumBytes = OutBufEnd - OutBufCur; + copy_to_buffer(Ptr, NumBytes); flush_nonempty(); + Ptr += NumBytes; + Size -= NumBytes; + } while (OutBufCur+Size > OutBufEnd); } - + + copy_to_buffer(Ptr, Size); + + return *this; +} + +void raw_ostream::copy_to_buffer(const char *Ptr, size_t Size) { // Handle short strings specially, memcpy isn't very good at very short // strings. switch (Size) { @@ -184,21 +199,11 @@ raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) { case 1: OutBufCur[0] = Ptr[0]; // FALL THROUGH case 0: break; default: - // Normally the string to emit is shorter than the buffer. - if (Size <= unsigned(OutBufEnd-OutBufCur)) { - memcpy(OutBufCur, Ptr, Size); - break; - } - - // Otherwise we are emitting a string larger than our buffer. We - // know we already flushed, so just write it out directly. - write_impl(Ptr, Size); - Size = 0; + memcpy(OutBufCur, Ptr, Size); break; } - OutBufCur += Size; - return *this; + OutBufCur += Size; } // Formatted output.