C++程序  |  213行  |  9.9 KB

// Copyright 2015 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef LIBBRILLO_BRILLO_STREAMS_MEMORY_STREAM_H_
#define LIBBRILLO_BRILLO_STREAMS_MEMORY_STREAM_H_

#include <string>
#include <vector>

#include <base/macros.h>
#include <base/memory/weak_ptr.h>
#include <brillo/brillo_export.h>
#include <brillo/streams/memory_containers.h>
#include <brillo/streams/stream.h>

namespace brillo {

// MemoryStream is a brillo::Stream implementation for memory buffer. A number
// of memory containers are supported, such as raw memory pointers, data stored
// in std::vector and std::string.
// MemoryStream offers support for constant read-only memory buffers as well as
// for writable buffers that can grow when needed.
// A memory stream is created by using the OpenNNN and CreateNNN factory methods
// to construct a read-only and writable streams respectively.
// The following factory methods overloads are provided:
//  - OpenRef    - overloads for constructing the stream on a constant read-only
//                 memory buffer that is not owned by the stream. The buffer
//                 pointer/reference must remain valid throughout the lifetime
//                 of the constructed stream object. The benefit of this is that
//                 no data copying is performed and the underlying container can
//                 be manipulated outside of the stream.
//  - OpenCopyOf - overloads to construct a stream that copies the data from the
//                 memory buffer and maintains the copied data until the stream
//                 is closed or destroyed. This makes it possible to construct
//                 a read-only streams on transient data or for cases where
//                 it is not possible or necessary to maintain the lifetime of
//                 the underlying memory buffer.
//  - Create     - creates a new internal memory buffer that can be written to
//                 or read from using the stream I/O interface.
//  - CreateRef  - constructs a read/write stream on a reference of data
//                 container such as std::vector or std::string which must
//                 remain valid throughout the lifetime of the memory stream.
//                 The data already stored in the container is maintained,
//                 however the stream pointer is set to the beginning of the
//                 data when the stream is created.
//  - CreateRefForAppend - similar to CreateRef except that it automatically
//                 positions the stream seek pointer at the end of the data,
//                 which makes it possible to append more data to the existing
//                 container.
class BRILLO_EXPORT MemoryStream : public Stream {
 public:
  // == Construction ==========================================================

  // Constructs a read-only stream on a generic memory buffer. The data
  // pointed to by |buffer| will be copied and owned by the stream object.
  static StreamPtr OpenCopyOf(const void* buffer, size_t size, ErrorPtr* error);
  static StreamPtr OpenCopyOf(std::string buffer, ErrorPtr* error);
  static StreamPtr OpenCopyOf(const char* buffer, ErrorPtr* error);
  // Only vectors of char and uint8_t are supported.
  template<typename T>
  inline static StreamPtr OpenCopyOf(std::vector<T> buffer, ErrorPtr* error) {
    std::unique_ptr<data_container::ReadOnlyVectorCopy<T>> container{
        new data_container::ReadOnlyVectorCopy<T>{std::move(buffer)}};
    return CreateEx(std::move(container), 0, error);
  }

  // Constructs a read-only stream on a generic memory buffer which is owned
  // by the caller.
  // ***WARNING***: The |buffer| pointer must be valid for as long as the stream
  // object is alive. The stream does not do any additional lifetime management
  // for the data pointed to by |buffer| and destroying that buffer before
  // the stream is closed will lead to unexpected behavior.
  static StreamPtr OpenRef(const void* buffer, size_t size, ErrorPtr* error);
  static StreamPtr OpenRef(const std::string& buffer, ErrorPtr* error);
  static StreamPtr OpenRef(const char* buffer, ErrorPtr* error);
  // Only vectors of char and uint8_t are supported.
  template<typename T>
  inline static StreamPtr OpenRef(const std::vector<T>& buffer,
                                  ErrorPtr* error) {
    std::unique_ptr<data_container::ReadOnlyVectorRef<T>> container{
        new data_container::ReadOnlyVectorRef<T>{buffer}};
    return CreateEx(std::move(container), 0, error);
  }

  ///------------------------------------------------------------------------
  // Creates new stream for reading/writing. This method creates an internal
  // memory buffer and maintains it until the stream is closed. |reserve_size|
  // parameter is a hint of the buffer size to pre-allocate. This does not
  // affect the memory buffer reported size. The buffer can grow past that
  // amount if needed.
  static StreamPtr Create(size_t reserve_size, ErrorPtr* error);

  inline static StreamPtr Create(ErrorPtr* error) { return Create(0, error); }

  // Creates new stream for reading/writing stored in a string. The string
  // |buffer| must remain valid during the lifetime of the stream.
  // The stream pointer will be at the beginning of the string and the string's
  // content is preserved.
  static StreamPtr CreateRef(std::string* buffer, ErrorPtr* error);

  // Creates new stream for reading/writing stored in a vector. The vector
  // |buffer| must remain valid during the lifetime of the stream.
  // The stream pointer will be at the beginning of the data and the vector's
  // content is preserved.
  // Only vectors of char and uint8_t are supported.
  template<typename T>
  static StreamPtr CreateRef(std::vector<T>* buffer, ErrorPtr* error) {
    std::unique_ptr<data_container::VectorPtr<T>> container{
        new data_container::VectorPtr<T>{buffer}};
    return CreateEx(std::move(container), 0, error);
  }

  // Creates new stream for reading/writing stored in a string. The string
  // |buffer| must remain valid during the lifetime of the stream.
  // The stream pointer will be at the end of the string and the string's
  // content is preserved.
  static StreamPtr CreateRefForAppend(std::string* buffer, ErrorPtr* error);

  // Creates new stream for reading/writing stored in a vector. The vector
  // |buffer| must remain valid during the lifetime of the stream.
  // The stream pointer will be at the end of the data and the vector's
  // content is preserved.
  // Only vectors of char and uint8_t are supported.
  template<typename T>
  static StreamPtr CreateRefForAppend(std::vector<T>* buffer, ErrorPtr* error) {
    std::unique_ptr<data_container::VectorPtr<T>> container{
        new data_container::VectorPtr<T>{buffer}};
    return CreateEx(std::move(container), buffer->size() * sizeof(T), error);
  }

  ///------------------------------------------------------------------------
  // Generic stream creation on a data container. Takes an arbitrary |container|
  // and constructs a stream using it. The container determines the traits of
  // the stream (e.g. whether it is read-only, what operations are supported
  // and so on). |stream_position| is the current stream pointer position at
  // creation time.
  static StreamPtr CreateEx(
      std::unique_ptr<data_container::DataContainerInterface> container,
      size_t stream_position,
      ErrorPtr* error);

  // == Stream capabilities ===================================================
  bool IsOpen() const override;
  bool CanRead() const override;
  bool CanWrite() const override;
  bool CanSeek() const override;
  bool CanGetSize() const override;

  // == Stream size operations ================================================
  uint64_t GetSize() const override;
  bool SetSizeBlocking(uint64_t size, ErrorPtr* error) override;
  uint64_t GetRemainingSize() const override;

  // == Seek operations =======================================================
  uint64_t GetPosition() const override;
  bool Seek(int64_t offset,
            Whence whence,
            uint64_t* new_position,
            ErrorPtr* error) override;

  // == Read operations =======================================================
  bool ReadNonBlocking(void* buffer,
                       size_t size_to_read,
                       size_t* size_read,
                       bool* end_of_stream,
                       ErrorPtr* error) override;

  // == Write operations ======================================================
  bool WriteNonBlocking(const void* buffer,
                        size_t size_to_write,
                        size_t* size_written,
                        ErrorPtr* error) override;

  // == Finalizing/closing streams  ===========================================
  bool FlushBlocking(ErrorPtr* error) override;
  bool CloseBlocking(ErrorPtr* error) override;

  // == Data availability monitoring ==========================================
  bool WaitForData(AccessMode mode,
                   const base::Callback<void(AccessMode)>& callback,
                   ErrorPtr* error) override;

  bool WaitForDataBlocking(AccessMode in_mode,
                           base::TimeDelta timeout,
                           AccessMode* out_mode,
                           ErrorPtr* error) override;

 private:
  friend class MemoryStreamTest;

  // Private constructor used by MemoryStream::OpenNNNN() and
  // MemoryStream::CreateNNNN() factory methods.
  MemoryStream(
      std::unique_ptr<data_container::DataContainerInterface> container,
      size_t stream_position);

  // Checks if the stream has a valid container.
  bool CheckContainer(ErrorPtr* error) const;

  // Data container the stream is using to write and/or read data.
  std::unique_ptr<data_container::DataContainerInterface> container_;

  // The current stream pointer position.
  size_t stream_position_{0};

  DISALLOW_COPY_AND_ASSIGN(MemoryStream);
};

}  // namespace brillo

#endif  // LIBBRILLO_BRILLO_STREAMS_MEMORY_STREAM_H_