blob: 541de070c7281cb8f7f499576e6c6dc1087196de [file] [log] [blame]
Niels Möllere7547d52018-11-01 09:33:08 +01001/*
2 * Copyright 2018 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include <algorithm>
12
13#include "rtc_base/memory_stream.h"
14
15namespace rtc {
16
17StreamState MemoryStream::GetState() const {
18 return SS_OPEN;
19}
20
21StreamResult MemoryStream::Read(void* buffer,
22 size_t bytes,
23 size_t* bytes_read,
24 int* error) {
25 if (seek_position_ >= data_length_) {
26 return SR_EOS;
27 }
28 size_t available = data_length_ - seek_position_;
29 if (bytes > available) {
30 // Read partial buffer
31 bytes = available;
32 }
33 memcpy(buffer, &buffer_[seek_position_], bytes);
34 seek_position_ += bytes;
35 if (bytes_read) {
36 *bytes_read = bytes;
37 }
38 return SR_SUCCESS;
39}
40
41StreamResult MemoryStream::Write(const void* buffer,
42 size_t bytes,
43 size_t* bytes_written,
44 int* error) {
45 size_t available = buffer_length_ - seek_position_;
46 if (0 == available) {
47 // Increase buffer size to the larger of:
48 // a) new position rounded up to next 256 bytes
49 // b) double the previous length
50 size_t new_buffer_length =
51 std::max(((seek_position_ + bytes) | 0xFF) + 1, buffer_length_ * 2);
52 StreamResult result = DoReserve(new_buffer_length, error);
53 if (SR_SUCCESS != result) {
54 return result;
55 }
56 RTC_DCHECK(buffer_length_ >= new_buffer_length);
57 available = buffer_length_ - seek_position_;
58 }
59
60 if (bytes > available) {
61 bytes = available;
62 }
63 memcpy(&buffer_[seek_position_], buffer, bytes);
64 seek_position_ += bytes;
65 if (data_length_ < seek_position_) {
66 data_length_ = seek_position_;
67 }
68 if (bytes_written) {
69 *bytes_written = bytes;
70 }
71 return SR_SUCCESS;
72}
73
74void MemoryStream::Close() {
75 // nothing to do
76}
77
78bool MemoryStream::SetPosition(size_t position) {
79 if (position > data_length_)
80 return false;
81 seek_position_ = position;
82 return true;
83}
84
85bool MemoryStream::GetPosition(size_t* position) const {
86 if (position)
87 *position = seek_position_;
88 return true;
89}
90
91bool MemoryStream::GetSize(size_t* size) const {
92 if (size)
93 *size = data_length_;
94 return true;
95}
96
97bool MemoryStream::ReserveSize(size_t size) {
98 return (SR_SUCCESS == DoReserve(size, nullptr));
99}
100
101///////////////////////////////////////////////////////////////////////////////
102
103MemoryStream::MemoryStream() {}
104
105MemoryStream::MemoryStream(const char* data) {
106 SetData(data, strlen(data));
107}
108
109MemoryStream::MemoryStream(const void* data, size_t length) {
110 SetData(data, length);
111}
112
113MemoryStream::~MemoryStream() {
114 delete[] buffer_;
115}
116
117void MemoryStream::SetData(const void* data, size_t length) {
118 data_length_ = buffer_length_ = length;
119 delete[] buffer_;
120 buffer_ = new char[buffer_length_];
121 memcpy(buffer_, data, data_length_);
122 seek_position_ = 0;
123}
124
125StreamResult MemoryStream::DoReserve(size_t size, int* error) {
126 if (buffer_length_ >= size)
127 return SR_SUCCESS;
128
129 if (char* new_buffer = new char[size]) {
130 memcpy(new_buffer, buffer_, data_length_);
131 delete[] buffer_;
132 buffer_ = new_buffer;
133 buffer_length_ = size;
134 return SR_SUCCESS;
135 }
136
137 if (error) {
138 *error = ENOMEM;
139 }
140 return SR_ERROR;
141}
142
143} // namespace rtc