1 // Copyright 2015 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <brillo/streams/memory_stream.h> 6 7 #include <limits> 8 9 #include <base/bind.h> 10 #include <brillo/message_loops/message_loop.h> 11 #include <brillo/streams/stream_errors.h> 12 #include <brillo/streams/stream_utils.h> 13 14 namespace brillo { 15 16 MemoryStream::MemoryStream( 17 std::unique_ptr<data_container::DataContainerInterface> container, 18 size_t stream_position) 19 : container_{std::move(container)}, stream_position_{stream_position} {} 20 21 StreamPtr MemoryStream::OpenRef(const void* buffer, 22 size_t size, 23 ErrorPtr* error) { 24 std::unique_ptr<data_container::ReadOnlyBuffer> container{ 25 new data_container::ReadOnlyBuffer{buffer, size}}; 26 return CreateEx(std::move(container), 0, error); 27 } 28 29 StreamPtr MemoryStream::OpenCopyOf(const void* buffer, 30 size_t size, 31 ErrorPtr* error) { 32 std::unique_ptr<data_container::ReadOnlyVectorCopy<uint8_t>> container{ 33 new data_container::ReadOnlyVectorCopy<uint8_t>{ 34 reinterpret_cast<const uint8_t*>(buffer), size}}; 35 return CreateEx(std::move(container), 0, error); 36 } 37 38 StreamPtr MemoryStream::OpenRef(const std::string& buffer, ErrorPtr* error) { 39 std::unique_ptr<data_container::ReadOnlyStringRef> container{ 40 new data_container::ReadOnlyStringRef{buffer}}; 41 return CreateEx(std::move(container), 0, error); 42 } 43 44 StreamPtr MemoryStream::OpenCopyOf(std::string buffer, ErrorPtr* error) { 45 std::unique_ptr<data_container::ReadOnlyStringCopy> container{ 46 new data_container::ReadOnlyStringCopy{std::move(buffer)}}; 47 return CreateEx(std::move(container), 0, error); 48 } 49 50 StreamPtr MemoryStream::OpenRef(const char* buffer, ErrorPtr* error) { 51 return OpenRef(buffer, std::strlen(buffer), error); 52 } 53 54 StreamPtr MemoryStream::OpenCopyOf(const char* buffer, ErrorPtr* error) { 55 return OpenCopyOf(buffer, std::strlen(buffer), error); 56 } 57 58 StreamPtr MemoryStream::Create(size_t reserve_size, ErrorPtr* error) { 59 std::unique_ptr<data_container::ByteBuffer> container{ 60 new data_container::ByteBuffer{reserve_size}}; 61 return CreateEx(std::move(container), 0, error); 62 } 63 64 StreamPtr MemoryStream::CreateRef(std::string* buffer, ErrorPtr* error) { 65 std::unique_ptr<data_container::StringPtr> container{ 66 new data_container::StringPtr{buffer}}; 67 return CreateEx(std::move(container), 0, error); 68 } 69 70 StreamPtr MemoryStream::CreateRefForAppend(std::string* buffer, 71 ErrorPtr* error) { 72 std::unique_ptr<data_container::StringPtr> container{ 73 new data_container::StringPtr{buffer}}; 74 return CreateEx(std::move(container), buffer->size(), error); 75 } 76 77 StreamPtr MemoryStream::CreateEx( 78 std::unique_ptr<data_container::DataContainerInterface> container, 79 size_t stream_position, 80 ErrorPtr* error) { 81 ignore_result(error); // Unused. 82 return StreamPtr{new MemoryStream(std::move(container), stream_position)}; 83 } 84 85 bool MemoryStream::IsOpen() const { return container_ != nullptr; } 86 bool MemoryStream::CanRead() const { return IsOpen(); } 87 88 bool MemoryStream::CanWrite() const { 89 return IsOpen() && !container_->IsReadOnly(); 90 } 91 92 bool MemoryStream::CanSeek() const { return IsOpen(); } 93 bool MemoryStream::CanGetSize() const { return IsOpen(); } 94 95 uint64_t MemoryStream::GetSize() const { 96 return IsOpen() ? container_->GetSize() : 0; 97 } 98 99 bool MemoryStream::SetSizeBlocking(uint64_t size, ErrorPtr* error) { 100 if (!CheckContainer(error)) 101 return false; 102 return container_->Resize(size, error); 103 } 104 105 uint64_t MemoryStream::GetRemainingSize() const { 106 uint64_t pos = GetPosition(); 107 uint64_t size = GetSize(); 108 return (pos < size) ? size - pos : 0; 109 } 110 111 uint64_t MemoryStream::GetPosition() const { 112 return IsOpen() ? stream_position_ : 0; 113 } 114 115 bool MemoryStream::Seek(int64_t offset, 116 Whence whence, 117 uint64_t* new_position, 118 ErrorPtr* error) { 119 uint64_t pos = 0; 120 if (!CheckContainer(error) || 121 !stream_utils::CalculateStreamPosition(FROM_HERE, offset, whence, 122 stream_position_, GetSize(), &pos, 123 error)) { 124 return false; 125 } 126 if (pos > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) { 127 // This can only be the case on 32 bit systems. 128 brillo::Error::AddTo(error, FROM_HERE, errors::stream::kDomain, 129 errors::stream::kInvalidParameter, 130 "Stream pointer position is outside allowed limits"); 131 return false; 132 } 133 134 stream_position_ = static_cast<size_t>(pos); 135 if (new_position) 136 *new_position = stream_position_; 137 return true; 138 } 139 140 bool MemoryStream::ReadNonBlocking(void* buffer, 141 size_t size_to_read, 142 size_t* size_read, 143 bool* end_of_stream, 144 ErrorPtr* error) { 145 if (!CheckContainer(error)) 146 return false; 147 size_t read = 0; 148 if (!container_->Read(buffer, size_to_read, stream_position_, &read, error)) 149 return false; 150 stream_position_ += read; 151 *size_read = read; 152 if (end_of_stream) 153 *end_of_stream = (read == 0) && (size_to_read != 0); 154 return true; 155 } 156 157 bool MemoryStream::WriteNonBlocking(const void* buffer, 158 size_t size_to_write, 159 size_t* size_written, 160 ErrorPtr* error) { 161 if (!CheckContainer(error)) 162 return false; 163 if (!container_->Write(buffer, size_to_write, stream_position_, size_written, 164 error)) { 165 return false; 166 } 167 stream_position_ += *size_written; 168 return true; 169 } 170 171 bool MemoryStream::FlushBlocking(ErrorPtr* error) { 172 return CheckContainer(error); 173 } 174 175 bool MemoryStream::CloseBlocking(ErrorPtr* error) { 176 ignore_result(error); // Unused. 177 container_.reset(); 178 return true; 179 } 180 181 bool MemoryStream::CheckContainer(ErrorPtr* error) const { 182 return container_ || stream_utils::ErrorStreamClosed(FROM_HERE, error); 183 } 184 185 bool MemoryStream::WaitForData(AccessMode mode, 186 const base::Callback<void(AccessMode)>& callback, 187 ErrorPtr* /* error */) { 188 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, mode)); 189 return true; 190 } 191 192 bool MemoryStream::WaitForDataBlocking(AccessMode in_mode, 193 base::TimeDelta /* timeout */, 194 AccessMode* out_mode, 195 ErrorPtr* /* error */) { 196 if (out_mode) 197 *out_mode = in_mode; 198 return true; 199 } 200 201 } // namespace brillo 202