blob: a30aacd139d7b895c90fcc05641c7804e2a44dc1 [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
Yves Gerey3e707812018-11-28 16:47:49 +010011#include <errno.h>
12#include <string.h>
Niels Möllere7547d52018-11-01 09:33:08 +010013#include <algorithm>
14
Yves Gerey3e707812018-11-28 16:47:49 +010015#include "rtc_base/checks.h"
Niels Möllere7547d52018-11-01 09:33:08 +010016#include "rtc_base/memory_stream.h"
17
18namespace rtc {
19
20StreamState MemoryStream::GetState() const {
21 return SS_OPEN;
22}
23
24StreamResult MemoryStream::Read(void* buffer,
25 size_t bytes,
26 size_t* bytes_read,
27 int* error) {
28 if (seek_position_ >= data_length_) {
29 return SR_EOS;
30 }
31 size_t available = data_length_ - seek_position_;
32 if (bytes > available) {
33 // Read partial buffer
34 bytes = available;
35 }
36 memcpy(buffer, &buffer_[seek_position_], bytes);
37 seek_position_ += bytes;
38 if (bytes_read) {
39 *bytes_read = bytes;
40 }
41 return SR_SUCCESS;
42}
43
44StreamResult MemoryStream::Write(const void* buffer,
45 size_t bytes,
46 size_t* bytes_written,
47 int* error) {
48 size_t available = buffer_length_ - seek_position_;
49 if (0 == available) {
50 // Increase buffer size to the larger of:
51 // a) new position rounded up to next 256 bytes
52 // b) double the previous length
53 size_t new_buffer_length =
54 std::max(((seek_position_ + bytes) | 0xFF) + 1, buffer_length_ * 2);
55 StreamResult result = DoReserve(new_buffer_length, error);
56 if (SR_SUCCESS != result) {
57 return result;
58 }
59 RTC_DCHECK(buffer_length_ >= new_buffer_length);
60 available = buffer_length_ - seek_position_;
61 }
62
63 if (bytes > available) {
64 bytes = available;
65 }
66 memcpy(&buffer_[seek_position_], buffer, bytes);
67 seek_position_ += bytes;
68 if (data_length_ < seek_position_) {
69 data_length_ = seek_position_;
70 }
71 if (bytes_written) {
72 *bytes_written = bytes;
73 }
74 return SR_SUCCESS;
75}
76
77void MemoryStream::Close() {
78 // nothing to do
79}
80
81bool MemoryStream::SetPosition(size_t position) {
82 if (position > data_length_)
83 return false;
84 seek_position_ = position;
85 return true;
86}
87
88bool MemoryStream::GetPosition(size_t* position) const {
89 if (position)
90 *position = seek_position_;
91 return true;
92}
93
Niels Möller1a86b782019-01-14 12:48:53 +010094void MemoryStream::Rewind() {
95 seek_position_ = 0;
96}
97
Niels Möllere7547d52018-11-01 09:33:08 +010098bool MemoryStream::GetSize(size_t* size) const {
99 if (size)
100 *size = data_length_;
101 return true;
102}
103
104bool MemoryStream::ReserveSize(size_t size) {
105 return (SR_SUCCESS == DoReserve(size, nullptr));
106}
107
108///////////////////////////////////////////////////////////////////////////////
109
110MemoryStream::MemoryStream() {}
111
112MemoryStream::MemoryStream(const char* data) {
113 SetData(data, strlen(data));
114}
115
116MemoryStream::MemoryStream(const void* data, size_t length) {
117 SetData(data, length);
118}
119
120MemoryStream::~MemoryStream() {
121 delete[] buffer_;
122}
123
124void MemoryStream::SetData(const void* data, size_t length) {
125 data_length_ = buffer_length_ = length;
126 delete[] buffer_;
127 buffer_ = new char[buffer_length_];
128 memcpy(buffer_, data, data_length_);
129 seek_position_ = 0;
130}
131
132StreamResult MemoryStream::DoReserve(size_t size, int* error) {
133 if (buffer_length_ >= size)
134 return SR_SUCCESS;
135
136 if (char* new_buffer = new char[size]) {
137 memcpy(new_buffer, buffer_, data_length_);
138 delete[] buffer_;
139 buffer_ = new_buffer;
140 buffer_length_ = size;
141 return SR_SUCCESS;
142 }
143
144 if (error) {
145 *error = ENOMEM;
146 }
147 return SR_ERROR;
148}
149
150} // namespace rtc