<div dir="ltr">Just wanted to say, thanks for the iterations here, I like the end result a lot. =]<br></div><br><div class="gmail_quote">On Tue, Apr 14, 2015 at 8:08 AM Rafael Espindola <<a href="mailto:rafael.espindola@gmail.com">rafael.espindola@gmail.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rafael<br>
Date: Tue Apr 14 10:00:34 2015<br>
New Revision: 234895<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=234895&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=234895&view=rev</a><br>
Log:<br>
Add raw_pwrite_stream type.<br>
<br>
This is a raw_ostream that also supports pwrite.<br>
I will be used in a sec.<br>
<br>
Added:<br>
    llvm/trunk/unittests/Support/raw_pwrite_stream_test.cpp<br>
Modified:<br>
    llvm/trunk/include/llvm/Support/raw_ostream.h<br>
    llvm/trunk/lib/Support/raw_ostream.cpp<br>
    llvm/trunk/unittests/Support/CMakeLists.txt<br>
<br>
Modified: llvm/trunk/include/llvm/Support/raw_ostream.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/raw_ostream.h?rev=234895&r1=234894&r2=234895&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/raw_ostream.h?rev=234895&r1=234894&r2=234895&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Support/raw_ostream.h (original)<br>
+++ llvm/trunk/include/llvm/Support/raw_ostream.h Tue Apr 14 10:00:34 2015<br>
@@ -313,13 +313,22 @@ private:<br>
   void copy_to_buffer(const char *Ptr, size_t Size);<br>
 };<br>
<br>
+/// An abstract base class for streams implementations that also support a<br>
+/// pwrite operation. This is usefull for code that can mostly stream out data,<br>
+/// but needs to patch in a header that needs to know the output size.<br>
+class raw_pwrite_stream : public raw_ostream {<br>
+public:<br>
+  using raw_ostream::raw_ostream;<br>
+  virtual void pwrite(const char *Ptr, size_t Size, uint64_t Offset) = 0;<br>
+};<br>
+<br>
 //===----------------------------------------------------------------------===//<br>
 // File Output Streams<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 /// A raw_ostream that writes to a file descriptor.<br>
 ///<br>
-class raw_fd_ostream : public raw_ostream {<br>
+class raw_fd_ostream : public raw_pwrite_stream {<br>
   int FD;<br>
   bool ShouldClose;<br>
<br>
@@ -378,6 +387,8 @@ public:<br>
   /// to the offset specified from the beginning of the file.<br>
   uint64_t seek(uint64_t off);<br>
<br>
+  void pwrite(const char *Ptr, size_t Size, uint64_t Offset) override;<br>
+<br>
   /// Set the stream to attempt to use atomic writes for individual output<br>
   /// routines where possible.<br>
   ///<br>
@@ -460,7 +471,7 @@ public:<br>
<br>
 /// A raw_ostream that writes to an SmallVector or SmallString.  This is a<br>
 /// simple adaptor class. This class does not encounter output errors.<br>
-class raw_svector_ostream : public raw_ostream {<br>
+class raw_svector_ostream : public raw_pwrite_stream {<br>
   SmallVectorImpl<char> &OS;<br>
<br>
   /// See raw_ostream::write_impl.<br>
@@ -469,6 +480,12 @@ class raw_svector_ostream : public raw_o<br>
   /// Return the current position within the stream, not counting the bytes<br>
   /// currently in the buffer.<br>
   uint64_t current_pos() const override;<br>
+<br>
+protected:<br>
+  // Like the regular constructor, but doesn't call init.<br>
+  explicit raw_svector_ostream(SmallVectorImpl<char> &O, unsigned);<br>
+  void init();<br>
+<br>
 public:<br>
   /// Construct a new raw_svector_ostream.<br>
   ///<br>
@@ -477,6 +494,8 @@ public:<br>
   explicit raw_svector_ostream(SmallVectorImpl<char> &O);<br>
   ~raw_svector_ostream() override;<br>
<br>
+  void pwrite(const char *Ptr, size_t Size, uint64_t Offset) override;<br>
+<br>
   /// This is called when the SmallVector we're appending to is changed outside<br>
   /// of the raw_svector_ostream's control.  It is only safe to do this if the<br>
   /// raw_svector_ostream has previously been flushed.<br>
@@ -488,7 +507,7 @@ public:<br>
 };<br>
<br>
 /// A raw_ostream that discards all output.<br>
-class raw_null_ostream : public raw_ostream {<br>
+class raw_null_ostream : public raw_pwrite_stream {<br>
   /// See raw_ostream::write_impl.<br>
   void write_impl(const char *Ptr, size_t size) override;<br>
<br>
@@ -499,6 +518,18 @@ class raw_null_ostream : public raw_ostr<br>
 public:<br>
   explicit raw_null_ostream() {}<br>
   ~raw_null_ostream() override;<br>
+  void pwrite(const char *Ptr, size_t Size, uint64_t Offset) override;<br>
+};<br>
+<br>
+class buffer_ostream : public raw_svector_ostream {<br>
+  raw_ostream &OS;<br>
+  SmallVector<char, 0> Buffer;<br>
+<br>
+public:<br>
+  buffer_ostream(raw_ostream &OS) : raw_svector_ostream(Buffer, 0), OS(OS) {<br>
+    init();<br>
+  }<br>
+  ~buffer_ostream() { OS << str(); }<br>
 };<br>
<br>
 } // end llvm namespace<br>
<br>
Modified: llvm/trunk/lib/Support/raw_ostream.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/raw_ostream.cpp?rev=234895&r1=234894&r2=234895&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/raw_ostream.cpp?rev=234895&r1=234894&r2=234895&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Support/raw_ostream.cpp (original)<br>
+++ llvm/trunk/lib/Support/raw_ostream.cpp Tue Apr 14 10:00:34 2015<br>
@@ -516,8 +516,8 @@ raw_fd_ostream::raw_fd_ostream(StringRef<br>
 /// FD is the file descriptor that this writes to.  If ShouldClose is true, this<br>
 /// closes the file when the stream is destroyed.<br>
 raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered)<br>
-  : raw_ostream(unbuffered), FD(fd),<br>
-    ShouldClose(shouldClose), Error(false), UseAtomicWrites(false) {<br>
+    : raw_pwrite_stream(unbuffered), FD(fd), ShouldClose(shouldClose),<br>
+      Error(false), UseAtomicWrites(false) {<br>
   if (FD < 0 ) {<br>
     ShouldClose = false;<br>
     return;<br>
@@ -630,6 +630,13 @@ uint64_t raw_fd_ostream::seek(uint64_t o<br>
   return pos;<br>
 }<br>
<br>
+void raw_fd_ostream::pwrite(const char *Ptr, size_t Size, uint64_t Offset) {<br>
+  uint64_t Pos = tell();<br>
+  seek(Offset);<br>
+  write(Ptr, Size);<br>
+  seek(Pos);<br>
+}<br>
+<br>
 size_t raw_fd_ostream::preferred_buffer_size() const {<br>
 #if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__minix)<br>
   // Windows and Minix have no st_blksize.<br>
@@ -753,7 +760,14 @@ void raw_string_ostream::write_impl(cons<br>
 // capacity. This allows raw_ostream to write directly into the correct place,<br>
 // and we only need to set the vector size when the data is flushed.<br>
<br>
+raw_svector_ostream::raw_svector_ostream(SmallVectorImpl<char> &O, unsigned)<br>
+    : OS(O) {}<br>
+<br>
 raw_svector_ostream::raw_svector_ostream(SmallVectorImpl<char> &O) : OS(O) {<br>
+  init();<br>
+}<br>
+<br>
+void raw_svector_ostream::init() {<br>
   // Set up the initial external buffer. We make sure that the buffer has at<br>
   // least 128 bytes free; raw_ostream itself only requires 64, but we want to<br>
   // make sure that we don't grow the buffer unnecessarily on destruction (when<br>
@@ -767,6 +781,17 @@ raw_svector_ostream::~raw_svector_ostrea<br>
   flush();<br>
 }<br>
<br>
+void raw_svector_ostream::pwrite(const char *Ptr, size_t Size,<br>
+                                 uint64_t Offset) {<br>
+  flush();<br>
+<br>
+  uint64_t End = Offset + Size;<br>
+  if (End > OS.size())<br>
+    OS.resize(End);<br>
+<br>
+  memcpy(OS.begin() + Offset, Ptr, Size);<br>
+}<br>
+<br>
 /// resync - This is called when the SmallVector we're appending to is changed<br>
 /// outside of the raw_svector_ostream's control.  It is only safe to do this<br>
 /// if the raw_svector_ostream has previously been flushed.<br>
@@ -821,3 +846,5 @@ void raw_null_ostream::write_impl(const<br>
 uint64_t raw_null_ostream::current_pos() const {<br>
   return 0;<br>
 }<br>
+<br>
+void raw_null_ostream::pwrite(const char *Ptr, size_t Size, uint64_t Offset) {}<br>
<br>
Modified: llvm/trunk/unittests/Support/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/CMakeLists.txt?rev=234895&r1=234894&r2=234895&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/CMakeLists.txt?rev=234895&r1=234894&r2=234895&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/Support/CMakeLists.txt (original)<br>
+++ llvm/trunk/unittests/Support/CMakeLists.txt Tue Apr 14 10:00:34 2015<br>
@@ -44,6 +44,7 @@ add_llvm_unittest(SupportTests<br>
   YAMLParserTest.cpp<br>
   formatted_raw_ostream_test.cpp<br>
   raw_ostream_test.cpp<br>
+  raw_pwrite_stream_test.cpp<br>
   )<br>
<br>
 # ManagedStatic.cpp uses <pthread>.<br>
<br>
Added: llvm/trunk/unittests/Support/raw_pwrite_stream_test.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/raw_pwrite_stream_test.cpp?rev=234895&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/raw_pwrite_stream_test.cpp?rev=234895&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/Support/raw_pwrite_stream_test.cpp (added)<br>
+++ llvm/trunk/unittests/Support/raw_pwrite_stream_test.cpp Tue Apr 14 10:00:34 2015<br>
@@ -0,0 +1,25 @@<br>
+//===- raw_pwrite_stream_test.cpp - raw_pwrite_stream tests ---------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "gtest/gtest.h"<br>
+#include "llvm/ADT/SmallString.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+<br>
+using namespace llvm;<br>
+<br>
+namespace {<br>
+<br>
+TEST(raw_pwrite_ostreamTest, TestSVector) {<br>
+  SmallString<64> Buffer;<br>
+  raw_svector_ostream OS(Buffer);<br>
+  StringRef Test = "test";<br>
+  OS.pwrite(Test.data(), Test.size(), 0);<br>
+  EXPECT_EQ(Test, OS.str());<br>
+}<br>
+}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>