blob: e71c0e65d0cb017a352ca3d3c775e0aa72189136 [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
94bool MemoryStream::GetSize(size_t* size) const {
95 if (size)
96 *size = data_length_;
97 return true;
98}
99
100bool MemoryStream::ReserveSize(size_t size) {
101 return (SR_SUCCESS == DoReserve(size, nullptr));
102}
103
104///////////////////////////////////////////////////////////////////////////////
105
106MemoryStream::MemoryStream() {}
107
108MemoryStream::MemoryStream(const char* data) {
109 SetData(data, strlen(data));
110}
111
112MemoryStream::MemoryStream(const void* data, size_t length) {
113 SetData(data, length);
114}
115
116MemoryStream::~MemoryStream() {
117 delete[] buffer_;
118}
119
120void MemoryStream::SetData(const void* data, size_t length) {
121 data_length_ = buffer_length_ = length;
122 delete[] buffer_;
123 buffer_ = new char[buffer_length_];
124 memcpy(buffer_, data, data_length_);
125 seek_position_ = 0;
126}
127
128StreamResult MemoryStream::DoReserve(size_t size, int* error) {
129 if (buffer_length_ >= size)
130 return SR_SUCCESS;
131
132 if (char* new_buffer = new char[size]) {
133 memcpy(new_buffer, buffer_, data_length_);
134 delete[] buffer_;
135 buffer_ = new_buffer;
136 buffer_length_ = size;
137 return SR_SUCCESS;
138 }
139
140 if (error) {
141 *error = ENOMEM;
142 }
143 return SR_ERROR;
144}
145
146} // namespace rtc