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 14namespace brillo { 15 16MemoryStream::MemoryStream( 17 std::unique_ptr<data_container::DataContainerInterface> container, 18 size_t stream_position) 19 : container_{std::move(container)}, stream_position_{stream_position} {} 20 21StreamPtr 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 29StreamPtr 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 38StreamPtr 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 44StreamPtr 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 50StreamPtr MemoryStream::OpenRef(const char* buffer, ErrorPtr* error) { 51 return OpenRef(buffer, std::strlen(buffer), error); 52} 53 54StreamPtr MemoryStream::OpenCopyOf(const char* buffer, ErrorPtr* error) { 55 return OpenCopyOf(buffer, std::strlen(buffer), error); 56} 57 58StreamPtr 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 64StreamPtr 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 70StreamPtr 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 77StreamPtr 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 85bool MemoryStream::IsOpen() const { return container_ != nullptr; } 86bool MemoryStream::CanRead() const { return IsOpen(); } 87 88bool MemoryStream::CanWrite() const { 89 return IsOpen() && !container_->IsReadOnly(); 90} 91 92bool MemoryStream::CanSeek() const { return IsOpen(); } 93bool MemoryStream::CanGetSize() const { return IsOpen(); } 94 95uint64_t MemoryStream::GetSize() const { 96 return IsOpen() ? container_->GetSize() : 0; 97} 98 99bool MemoryStream::SetSizeBlocking(uint64_t size, ErrorPtr* error) { 100 if (!CheckContainer(error)) 101 return false; 102 return container_->Resize(size, error); 103} 104 105uint64_t MemoryStream::GetRemainingSize() const { 106 uint64_t pos = GetPosition(); 107 uint64_t size = GetSize(); 108 return (pos < size) ? size - pos : 0; 109} 110 111uint64_t MemoryStream::GetPosition() const { 112 return IsOpen() ? stream_position_ : 0; 113} 114 115bool 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 140bool 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 157bool 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 171bool MemoryStream::FlushBlocking(ErrorPtr* error) { 172 return CheckContainer(error); 173} 174 175bool MemoryStream::CloseBlocking(ErrorPtr* error) { 176 ignore_result(error); // Unused. 177 container_.reset(); 178 return true; 179} 180 181bool MemoryStream::CheckContainer(ErrorPtr* error) const { 182 return container_ || stream_utils::ErrorStreamClosed(FROM_HERE, error); 183} 184 185bool 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 192bool 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