Home | History | Annotate | Download | only in streams
      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