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_containers.h>
6
7#include <base/callback.h>
8#include <brillo/streams/stream_errors.h>
9
10namespace brillo {
11namespace data_container {
12
13namespace {
14
15bool ErrorStreamReadOnly(const tracked_objects::Location& location,
16                         ErrorPtr* error) {
17  Error::AddTo(error,
18               location,
19               errors::stream::kDomain,
20               errors::stream::kOperationNotSupported,
21               "Stream is read-only");
22  return false;
23}
24
25}  // anonymous namespace
26
27void ContiguousBufferBase::CopyMemoryBlock(void* dest,
28                                           const void* src,
29                                           size_t size) const {
30  memcpy(dest, src, size);
31}
32
33bool ContiguousBufferBase::Read(void* buffer,
34                                size_t size_to_read,
35                                size_t offset,
36                                size_t* size_read,
37                                ErrorPtr* error) {
38  size_t buf_size = GetSize();
39  if (offset < buf_size) {
40    size_t remaining = buf_size - offset;
41    if (size_to_read >= remaining) {
42      size_to_read = remaining;
43    }
44    const void* src_buffer = GetReadOnlyBuffer(offset, error);
45    if (!src_buffer)
46      return false;
47
48    CopyMemoryBlock(buffer, src_buffer, size_to_read);
49  } else {
50    size_to_read = 0;
51  }
52  if (size_read)
53    *size_read = size_to_read;
54  return true;
55}
56
57bool ContiguousBufferBase::Write(const void* buffer,
58                                 size_t size_to_write,
59                                 size_t offset,
60                                 size_t* size_written,
61                                 ErrorPtr* error) {
62  if (size_to_write) {
63    size_t new_size = offset + size_to_write;
64    if (GetSize() < new_size && !Resize(new_size, error))
65      return false;
66    void* ptr = GetBuffer(offset, error);
67    if (!ptr)
68      return false;
69    CopyMemoryBlock(ptr, buffer, size_to_write);
70    if (size_written)
71      *size_written = size_to_write;
72  }
73  return true;
74}
75
76bool ContiguousReadOnlyBufferBase::Write(const void* /* buffer */,
77                                         size_t /* size_to_write */,
78                                         size_t /* offset */,
79                                         size_t* /* size_written */,
80                                         ErrorPtr* error) {
81  return ErrorStreamReadOnly(FROM_HERE, error);
82}
83
84bool ContiguousReadOnlyBufferBase::Resize(size_t /* new_size */,
85                                          ErrorPtr* error) {
86  return ErrorStreamReadOnly(FROM_HERE, error);
87}
88
89void* ContiguousReadOnlyBufferBase::GetBuffer(size_t /* offset */,
90                                              ErrorPtr* error) {
91  ErrorStreamReadOnly(FROM_HERE, error);
92  return nullptr;
93}
94
95ByteBuffer::ByteBuffer(size_t reserve_size)
96    : VectorPtr(new std::vector<uint8_t>()) {
97  vector_ptr_->reserve(reserve_size);
98}
99
100ByteBuffer::~ByteBuffer() {
101  delete vector_ptr_;
102}
103
104StringPtr::StringPtr(std::string* string) : string_ptr_(string) {}
105
106bool StringPtr::Resize(size_t new_size, ErrorPtr* /* error */) {
107  string_ptr_->resize(new_size);
108  return true;
109}
110
111const void* StringPtr::GetReadOnlyBuffer(size_t offset,
112                                         ErrorPtr* /* error */) const {
113  return string_ptr_->data() + offset;
114}
115
116void* StringPtr::GetBuffer(size_t offset, ErrorPtr* /* error */) {
117  return &(*string_ptr_)[offset];
118}
119
120ReadOnlyStringRef::ReadOnlyStringRef(const std::string& string)
121    : string_ref_(string) {}
122
123const void* ReadOnlyStringRef::GetReadOnlyBuffer(size_t offset,
124                                                 ErrorPtr* /* error */) const {
125  return string_ref_.data() + offset;
126}
127
128ReadOnlyStringCopy::ReadOnlyStringCopy(std::string string)
129    : ReadOnlyStringRef(string_copy_), string_copy_(std::move(string)) {}
130
131}  // namespace data_container
132}  // namespace brillo
133