Fix the buffer handling logic so that write_impl is always called with
authorDan Gohman <gohman@apple.com>
Thu, 13 Aug 2009 15:44:52 +0000 (15:44 +0000)
committerDan Gohman <gohman@apple.com>
Thu, 13 Aug 2009 15:44:52 +0000 (15:44 +0000)
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
lib/Support/raw_ostream.cpp

index f7fbe21ee3f5d685b7c1c1cd7ff6c9c0fbebe4ee..58de3e81867c8ee2b51b72b876fce14dddd4a84b 100644 (file)
@@ -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);
 };
 
 //===----------------------------------------------------------------------===//
index e3ab0c688a333feedf82c47962ab65233da3a05d..11a11bd930a73a1bb313dc7373ea569c1d5c54ae 100644 (file)
@@ -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.