Add ElfWriter::GetStream().
This will be used for writing the OatHeader which is
currently oddly written through the .text stream.
Also move the error delaying output stream out of the
ElfBuilder<> to its own file and move all output stream
files to compiler/linker/.
Change-Id: I00db4e33ed80ac4757ec459946c7b5ae014a3a2e
diff --git a/compiler/linker/arm/relative_patcher_arm_base.cc b/compiler/linker/arm/relative_patcher_arm_base.cc
index 13754fd..73b0fac 100644
--- a/compiler/linker/arm/relative_patcher_arm_base.cc
+++ b/compiler/linker/arm/relative_patcher_arm_base.cc
@@ -17,9 +17,9 @@
#include "linker/arm/relative_patcher_arm_base.h"
#include "compiled_method.h"
+#include "linker/output_stream.h"
#include "oat.h"
#include "oat_quick_method_header.h"
-#include "output_stream.h"
namespace art {
namespace linker {
diff --git a/compiler/linker/arm64/relative_patcher_arm64.cc b/compiler/linker/arm64/relative_patcher_arm64.cc
index 57018af..3d4c218 100644
--- a/compiler/linker/arm64/relative_patcher_arm64.cc
+++ b/compiler/linker/arm64/relative_patcher_arm64.cc
@@ -20,10 +20,10 @@
#include "art_method.h"
#include "compiled_method.h"
#include "driver/compiler_driver.h"
-#include "utils/arm64/assembler_arm64.h"
+#include "linker/output_stream.h"
#include "oat.h"
#include "oat_quick_method_header.h"
-#include "output_stream.h"
+#include "utils/arm64/assembler_arm64.h"
namespace art {
namespace linker {
diff --git a/compiler/linker/buffered_output_stream.cc b/compiler/linker/buffered_output_stream.cc
new file mode 100644
index 0000000..4c66c76
--- /dev/null
+++ b/compiler/linker/buffered_output_stream.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "buffered_output_stream.h"
+
+#include <string.h>
+
+namespace art {
+
+BufferedOutputStream::BufferedOutputStream(std::unique_ptr<OutputStream> out)
+ : OutputStream(out->GetLocation()), // Before out is moved to out_.
+ out_(std::move(out)),
+ used_(0) {}
+
+BufferedOutputStream::~BufferedOutputStream() {
+ FlushBuffer();
+}
+
+bool BufferedOutputStream::WriteFully(const void* buffer, size_t byte_count) {
+ if (byte_count > kBufferSize) {
+ if (!FlushBuffer()) {
+ return false;
+ }
+ return out_->WriteFully(buffer, byte_count);
+ }
+ if (used_ + byte_count > kBufferSize) {
+ if (!FlushBuffer()) {
+ return false;
+ }
+ }
+ const uint8_t* src = reinterpret_cast<const uint8_t*>(buffer);
+ memcpy(&buffer_[used_], src, byte_count);
+ used_ += byte_count;
+ return true;
+}
+
+bool BufferedOutputStream::Flush() {
+ return FlushBuffer() && out_->Flush();
+}
+
+bool BufferedOutputStream::FlushBuffer() {
+ bool success = true;
+ if (used_ > 0) {
+ success = out_->WriteFully(&buffer_[0], used_);
+ used_ = 0;
+ }
+ return success;
+}
+
+off_t BufferedOutputStream::Seek(off_t offset, Whence whence) {
+ if (!FlushBuffer()) {
+ return -1;
+ }
+ return out_->Seek(offset, whence);
+}
+
+} // namespace art
diff --git a/compiler/linker/buffered_output_stream.h b/compiler/linker/buffered_output_stream.h
new file mode 100644
index 0000000..a2eefbb
--- /dev/null
+++ b/compiler/linker/buffered_output_stream.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_LINKER_BUFFERED_OUTPUT_STREAM_H_
+#define ART_COMPILER_LINKER_BUFFERED_OUTPUT_STREAM_H_
+
+#include <memory>
+
+#include "output_stream.h"
+
+#include "globals.h"
+
+namespace art {
+
+class BufferedOutputStream FINAL : public OutputStream {
+ public:
+ explicit BufferedOutputStream(std::unique_ptr<OutputStream> out);
+
+ ~BufferedOutputStream() OVERRIDE;
+
+ bool WriteFully(const void* buffer, size_t byte_count) OVERRIDE;
+
+ off_t Seek(off_t offset, Whence whence) OVERRIDE;
+
+ bool Flush() OVERRIDE;
+
+ private:
+ static const size_t kBufferSize = 8 * KB;
+
+ bool FlushBuffer();
+
+ std::unique_ptr<OutputStream> const out_;
+ uint8_t buffer_[kBufferSize];
+ size_t used_;
+
+ DISALLOW_COPY_AND_ASSIGN(BufferedOutputStream);
+};
+
+} // namespace art
+
+#endif // ART_COMPILER_LINKER_BUFFERED_OUTPUT_STREAM_H_
diff --git a/compiler/linker/error_delaying_output_stream.h b/compiler/linker/error_delaying_output_stream.h
new file mode 100644
index 0000000..99410e4
--- /dev/null
+++ b/compiler/linker/error_delaying_output_stream.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_LINKER_ERROR_DELAYING_OUTPUT_STREAM_H_
+#define ART_COMPILER_LINKER_ERROR_DELAYING_OUTPUT_STREAM_H_
+
+#include "output_stream.h"
+
+#include "base/logging.h"
+
+namespace art {
+
+// OutputStream wrapper that delays reporting an error until Flush().
+class ErrorDelayingOutputStream FINAL : public OutputStream {
+ public:
+ explicit ErrorDelayingOutputStream(OutputStream* output)
+ : OutputStream(output->GetLocation()),
+ output_(output),
+ output_good_(true),
+ output_offset_(0) { }
+
+ // This function always succeeds to simplify code.
+ // Use Good() to check the actual status of the output stream.
+ bool WriteFully(const void* buffer, size_t byte_count) OVERRIDE {
+ if (output_good_) {
+ if (!output_->WriteFully(buffer, byte_count)) {
+ PLOG(ERROR) << "Failed to write " << byte_count
+ << " bytes to " << GetLocation() << " at offset " << output_offset_;
+ output_good_ = false;
+ }
+ }
+ output_offset_ += byte_count;
+ return true;
+ }
+
+ // This function always succeeds to simplify code.
+ // Use Good() to check the actual status of the output stream.
+ off_t Seek(off_t offset, Whence whence) OVERRIDE {
+ // We keep shadow copy of the offset so that we return
+ // the expected value even if the output stream failed.
+ off_t new_offset;
+ switch (whence) {
+ case kSeekSet:
+ new_offset = offset;
+ break;
+ case kSeekCurrent:
+ new_offset = output_offset_ + offset;
+ break;
+ default:
+ LOG(FATAL) << "Unsupported seek type: " << whence;
+ UNREACHABLE();
+ }
+ if (output_good_) {
+ off_t actual_offset = output_->Seek(offset, whence);
+ if (actual_offset == static_cast<off_t>(-1)) {
+ PLOG(ERROR) << "Failed to seek in " << GetLocation() << ". Offset=" << offset
+ << " whence=" << whence << " new_offset=" << new_offset;
+ output_good_ = false;
+ }
+ DCHECK_EQ(actual_offset, new_offset);
+ }
+ output_offset_ = new_offset;
+ return new_offset;
+ }
+
+ // Flush the output and return whether all operations have succeeded.
+ // Do nothing if we already have a pending error.
+ bool Flush() OVERRIDE {
+ if (output_good_) {
+ output_good_ = output_->Flush();
+ }
+ return output_good_;
+ }
+
+ // Check (without flushing) whether all operations have succeeded so far.
+ bool Good() const {
+ return output_good_;
+ }
+
+ private:
+ OutputStream* output_;
+ bool output_good_; // True if all writes to output succeeded.
+ off_t output_offset_; // Keep track of the current position in the stream.
+};
+
+} // namespace art
+
+#endif // ART_COMPILER_LINKER_ERROR_DELAYING_OUTPUT_STREAM_H_
diff --git a/compiler/linker/file_output_stream.cc b/compiler/linker/file_output_stream.cc
new file mode 100644
index 0000000..bbfbdfd
--- /dev/null
+++ b/compiler/linker/file_output_stream.cc
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "file_output_stream.h"
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "base/unix_file/fd_file.h"
+
+namespace art {
+
+FileOutputStream::FileOutputStream(File* file) : OutputStream(file->GetPath()), file_(file) {}
+
+bool FileOutputStream::WriteFully(const void* buffer, size_t byte_count) {
+ return file_->WriteFully(buffer, byte_count);
+}
+
+off_t FileOutputStream::Seek(off_t offset, Whence whence) {
+ return lseek(file_->Fd(), offset, static_cast<int>(whence));
+}
+
+bool FileOutputStream::Flush() {
+ return file_->Flush() == 0;
+}
+
+} // namespace art
diff --git a/compiler/linker/file_output_stream.h b/compiler/linker/file_output_stream.h
new file mode 100644
index 0000000..f2d8453
--- /dev/null
+++ b/compiler/linker/file_output_stream.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_LINKER_FILE_OUTPUT_STREAM_H_
+#define ART_COMPILER_LINKER_FILE_OUTPUT_STREAM_H_
+
+#include "output_stream.h"
+
+#include "os.h"
+
+namespace art {
+
+class FileOutputStream FINAL : public OutputStream {
+ public:
+ explicit FileOutputStream(File* file);
+
+ ~FileOutputStream() OVERRIDE {}
+
+ bool WriteFully(const void* buffer, size_t byte_count) OVERRIDE;
+
+ off_t Seek(off_t offset, Whence whence) OVERRIDE;
+
+ bool Flush() OVERRIDE;
+
+ private:
+ File* const file_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileOutputStream);
+};
+
+} // namespace art
+
+#endif // ART_COMPILER_LINKER_FILE_OUTPUT_STREAM_H_
diff --git a/compiler/linker/output_stream.cc b/compiler/linker/output_stream.cc
new file mode 100644
index 0000000..a8b64ca
--- /dev/null
+++ b/compiler/linker/output_stream.cc
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "output_stream.h"
+
+namespace art {
+
+std::ostream& operator<<(std::ostream& os, const Whence& rhs) {
+ switch (rhs) {
+ case kSeekSet: os << "SEEK_SET"; break;
+ case kSeekCurrent: os << "SEEK_CUR"; break;
+ case kSeekEnd: os << "SEEK_END"; break;
+ default: UNREACHABLE();
+ }
+ return os;
+}
+
+} // namespace art
diff --git a/compiler/linker/output_stream.h b/compiler/linker/output_stream.h
new file mode 100644
index 0000000..96a5f48
--- /dev/null
+++ b/compiler/linker/output_stream.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_LINKER_OUTPUT_STREAM_H_
+#define ART_COMPILER_LINKER_OUTPUT_STREAM_H_
+
+#include <ostream>
+#include <string>
+
+#include "base/macros.h"
+
+namespace art {
+
+enum Whence {
+ kSeekSet = SEEK_SET,
+ kSeekCurrent = SEEK_CUR,
+ kSeekEnd = SEEK_END,
+};
+std::ostream& operator<<(std::ostream& os, const Whence& rhs);
+
+class OutputStream {
+ public:
+ explicit OutputStream(const std::string& location) : location_(location) {}
+
+ virtual ~OutputStream() {}
+
+ const std::string& GetLocation() const {
+ return location_;
+ }
+
+ virtual bool WriteFully(const void* buffer, size_t byte_count) = 0;
+
+ virtual off_t Seek(off_t offset, Whence whence) = 0;
+
+ /*
+ * Flushes the stream. Returns whether the operation was successful.
+ *
+ * An OutputStream may delay reporting errors from WriteFully() or
+ * Seek(). In that case, Flush() shall report any pending error.
+ */
+ virtual bool Flush() = 0;
+
+ private:
+ const std::string location_;
+
+ DISALLOW_COPY_AND_ASSIGN(OutputStream);
+};
+
+} // namespace art
+
+#endif // ART_COMPILER_LINKER_OUTPUT_STREAM_H_
diff --git a/compiler/linker/output_stream_test.cc b/compiler/linker/output_stream_test.cc
new file mode 100644
index 0000000..84c76f2
--- /dev/null
+++ b/compiler/linker/output_stream_test.cc
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "file_output_stream.h"
+#include "vector_output_stream.h"
+
+#include "base/unix_file/fd_file.h"
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "buffered_output_stream.h"
+#include "common_runtime_test.h"
+
+namespace art {
+
+class OutputStreamTest : public CommonRuntimeTest {
+ protected:
+ void CheckOffset(off_t expected) {
+ off_t actual = output_stream_->Seek(0, kSeekCurrent);
+ EXPECT_EQ(expected, actual);
+ }
+
+ void SetOutputStream(OutputStream& output_stream) {
+ output_stream_ = &output_stream;
+ }
+
+ void GenerateTestOutput() {
+ EXPECT_EQ(3, output_stream_->Seek(3, kSeekCurrent));
+ CheckOffset(3);
+ EXPECT_EQ(2, output_stream_->Seek(2, kSeekSet));
+ CheckOffset(2);
+ uint8_t buf[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ EXPECT_TRUE(output_stream_->WriteFully(buf, 2));
+ CheckOffset(4);
+ EXPECT_EQ(6, output_stream_->Seek(2, kSeekEnd));
+ CheckOffset(6);
+ EXPECT_TRUE(output_stream_->WriteFully(buf, 4));
+ CheckOffset(10);
+ EXPECT_TRUE(output_stream_->WriteFully(buf, 6));
+ EXPECT_TRUE(output_stream_->Flush());
+ }
+
+ void CheckTestOutput(const std::vector<uint8_t>& actual) {
+ uint8_t expected[] = {
+ 0, 0, 1, 2, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 5, 6
+ };
+ EXPECT_EQ(sizeof(expected), actual.size());
+ EXPECT_EQ(0, memcmp(expected, &actual[0], actual.size()));
+ }
+
+ OutputStream* output_stream_;
+};
+
+TEST_F(OutputStreamTest, File) {
+ ScratchFile tmp;
+ FileOutputStream output_stream(tmp.GetFile());
+ SetOutputStream(output_stream);
+ GenerateTestOutput();
+ std::unique_ptr<File> in(OS::OpenFileForReading(tmp.GetFilename().c_str()));
+ EXPECT_TRUE(in.get() != nullptr);
+ std::vector<uint8_t> actual(in->GetLength());
+ bool readSuccess = in->ReadFully(&actual[0], actual.size());
+ EXPECT_TRUE(readSuccess);
+ CheckTestOutput(actual);
+}
+
+TEST_F(OutputStreamTest, Buffered) {
+ ScratchFile tmp;
+ {
+ BufferedOutputStream buffered_output_stream(MakeUnique<FileOutputStream>(tmp.GetFile()));
+ SetOutputStream(buffered_output_stream);
+ GenerateTestOutput();
+ }
+ std::unique_ptr<File> in(OS::OpenFileForReading(tmp.GetFilename().c_str()));
+ EXPECT_TRUE(in.get() != nullptr);
+ std::vector<uint8_t> actual(in->GetLength());
+ bool readSuccess = in->ReadFully(&actual[0], actual.size());
+ EXPECT_TRUE(readSuccess);
+ CheckTestOutput(actual);
+}
+
+TEST_F(OutputStreamTest, Vector) {
+ std::vector<uint8_t> output;
+ VectorOutputStream output_stream("test vector output", &output);
+ SetOutputStream(output_stream);
+ GenerateTestOutput();
+ CheckTestOutput(output);
+}
+
+TEST_F(OutputStreamTest, BufferedFlush) {
+ struct CheckingOutputStream : OutputStream {
+ CheckingOutputStream()
+ : OutputStream("dummy"),
+ flush_called(false) { }
+ ~CheckingOutputStream() OVERRIDE {}
+
+ bool WriteFully(const void* buffer ATTRIBUTE_UNUSED,
+ size_t byte_count ATTRIBUTE_UNUSED) OVERRIDE {
+ LOG(FATAL) << "UNREACHABLE";
+ UNREACHABLE();
+ }
+
+ off_t Seek(off_t offset ATTRIBUTE_UNUSED, Whence whence ATTRIBUTE_UNUSED) OVERRIDE {
+ LOG(FATAL) << "UNREACHABLE";
+ UNREACHABLE();
+ }
+
+ bool Flush() OVERRIDE {
+ flush_called = true;
+ return true;
+ }
+
+ bool flush_called;
+ };
+
+ std::unique_ptr<CheckingOutputStream> cos = MakeUnique<CheckingOutputStream>();
+ CheckingOutputStream* checking_output_stream = cos.get();
+ BufferedOutputStream buffered(std::move(cos));
+ ASSERT_FALSE(checking_output_stream->flush_called);
+ bool flush_result = buffered.Flush();
+ ASSERT_TRUE(flush_result);
+ ASSERT_TRUE(checking_output_stream->flush_called);
+}
+
+} // namespace art
diff --git a/compiler/linker/vector_output_stream.cc b/compiler/linker/vector_output_stream.cc
new file mode 100644
index 0000000..f758005
--- /dev/null
+++ b/compiler/linker/vector_output_stream.cc
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "vector_output_stream.h"
+
+#include "base/logging.h"
+
+namespace art {
+
+VectorOutputStream::VectorOutputStream(const std::string& location, std::vector<uint8_t>* vector)
+ : OutputStream(location), offset_(vector->size()), vector_(vector) {}
+
+off_t VectorOutputStream::Seek(off_t offset, Whence whence) {
+ CHECK(whence == kSeekSet || whence == kSeekCurrent || whence == kSeekEnd) << whence;
+ off_t new_offset = 0;
+ switch (whence) {
+ case kSeekSet: {
+ new_offset = offset;
+ break;
+ }
+ case kSeekCurrent: {
+ new_offset = offset_ + offset;
+ break;
+ }
+ case kSeekEnd: {
+ new_offset = vector_->size() + offset;
+ break;
+ }
+ }
+ EnsureCapacity(new_offset);
+ offset_ = new_offset;
+ return offset_;
+}
+
+} // namespace art
diff --git a/compiler/linker/vector_output_stream.h b/compiler/linker/vector_output_stream.h
new file mode 100644
index 0000000..3210143
--- /dev/null
+++ b/compiler/linker/vector_output_stream.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_LINKER_VECTOR_OUTPUT_STREAM_H_
+#define ART_COMPILER_LINKER_VECTOR_OUTPUT_STREAM_H_
+
+#include "output_stream.h"
+
+#include <string>
+#include <string.h>
+#include <vector>
+
+namespace art {
+
+class VectorOutputStream FINAL : public OutputStream {
+ public:
+ VectorOutputStream(const std::string& location, std::vector<uint8_t>* vector);
+
+ ~VectorOutputStream() OVERRIDE {}
+
+ bool WriteFully(const void* buffer, size_t byte_count) OVERRIDE {
+ if (static_cast<size_t>(offset_) == vector_->size()) {
+ const uint8_t* start = reinterpret_cast<const uint8_t*>(buffer);
+ vector_->insert(vector_->end(), &start[0], &start[byte_count]);
+ offset_ += byte_count;
+ } else {
+ off_t new_offset = offset_ + byte_count;
+ EnsureCapacity(new_offset);
+ memcpy(&(*vector_)[offset_], buffer, byte_count);
+ offset_ = new_offset;
+ }
+ return true;
+ }
+
+ off_t Seek(off_t offset, Whence whence) OVERRIDE;
+
+ bool Flush() OVERRIDE {
+ return true;
+ }
+
+ private:
+ void EnsureCapacity(off_t new_offset) {
+ if (new_offset > static_cast<off_t>(vector_->size())) {
+ vector_->resize(new_offset);
+ }
+ }
+
+ off_t offset_;
+ std::vector<uint8_t>* const vector_;
+
+ DISALLOW_COPY_AND_ASSIGN(VectorOutputStream);
+};
+
+} // namespace art
+
+#endif // ART_COMPILER_LINKER_VECTOR_OUTPUT_STREAM_H_