blob: 8ceab7aa9b7a95db58f634d43fd94f508c7d6b6b [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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "rtc_base/memory_stream.h"
12
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <errno.h>
14#include <string.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020015
Niels Möllere7547d52018-11-01 09:33:08 +010016#include <algorithm>
17
Yves Gerey3e707812018-11-28 16:47:49 +010018#include "rtc_base/checks.h"
Niels Möllere7547d52018-11-01 09:33:08 +010019
20namespace rtc {
21
22StreamState MemoryStream::GetState() const {
23 return SS_OPEN;
24}
25
Harald Alvestranddd4c4062022-11-16 07:29:57 +000026StreamResult MemoryStream::Read(rtc::ArrayView<uint8_t> buffer,
27 size_t& bytes_read,
28 int& error) {
Niels Möllere7547d52018-11-01 09:33:08 +010029 if (seek_position_ >= data_length_) {
30 return SR_EOS;
31 }
32 size_t available = data_length_ - seek_position_;
Harald Alvestranddd4c4062022-11-16 07:29:57 +000033 size_t bytes;
34 if (buffer.size() > available) {
Niels Möllere7547d52018-11-01 09:33:08 +010035 // Read partial buffer
36 bytes = available;
Harald Alvestranddd4c4062022-11-16 07:29:57 +000037 } else {
38 bytes = buffer.size();
Niels Möllere7547d52018-11-01 09:33:08 +010039 }
Harald Alvestranddd4c4062022-11-16 07:29:57 +000040 memcpy(buffer.data(), &buffer_[seek_position_], bytes);
Niels Möllere7547d52018-11-01 09:33:08 +010041 seek_position_ += bytes;
Harald Alvestranddd4c4062022-11-16 07:29:57 +000042 bytes_read = bytes;
Niels Möllere7547d52018-11-01 09:33:08 +010043 return SR_SUCCESS;
44}
45
Harald Alvestranddd4c4062022-11-16 07:29:57 +000046StreamResult MemoryStream::Write(rtc::ArrayView<const uint8_t> buffer,
47 size_t& bytes_written,
48 int& error) {
Niels Möllere7547d52018-11-01 09:33:08 +010049 size_t available = buffer_length_ - seek_position_;
50 if (0 == available) {
51 // Increase buffer size to the larger of:
52 // a) new position rounded up to next 256 bytes
53 // b) double the previous length
Harald Alvestranddd4c4062022-11-16 07:29:57 +000054 size_t new_buffer_length = std::max(
55 ((seek_position_ + buffer.size()) | 0xFF) + 1, buffer_length_ * 2);
56 StreamResult result = DoReserve(new_buffer_length, &error);
Niels Möllere7547d52018-11-01 09:33:08 +010057 if (SR_SUCCESS != result) {
58 return result;
59 }
60 RTC_DCHECK(buffer_length_ >= new_buffer_length);
61 available = buffer_length_ - seek_position_;
62 }
63
Harald Alvestranddd4c4062022-11-16 07:29:57 +000064 size_t bytes = buffer.size();
Niels Möllere7547d52018-11-01 09:33:08 +010065 if (bytes > available) {
66 bytes = available;
67 }
Harald Alvestranddd4c4062022-11-16 07:29:57 +000068 memcpy(&buffer_[seek_position_], buffer.data(), bytes);
Niels Möllere7547d52018-11-01 09:33:08 +010069 seek_position_ += bytes;
70 if (data_length_ < seek_position_) {
71 data_length_ = seek_position_;
72 }
Harald Alvestranddd4c4062022-11-16 07:29:57 +000073 bytes_written = bytes;
Niels Möllere7547d52018-11-01 09:33:08 +010074 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
Niels Möllere7547d52018-11-01 09:33:08 +0100112MemoryStream::~MemoryStream() {
113 delete[] buffer_;
114}
115
116void MemoryStream::SetData(const void* data, size_t length) {
117 data_length_ = buffer_length_ = length;
118 delete[] buffer_;
119 buffer_ = new char[buffer_length_];
120 memcpy(buffer_, data, data_length_);
121 seek_position_ = 0;
122}
123
124StreamResult MemoryStream::DoReserve(size_t size, int* error) {
125 if (buffer_length_ >= size)
126 return SR_SUCCESS;
127
128 if (char* new_buffer = new char[size]) {
Byoungchan Lee8c725f32022-09-13 17:53:49 +0900129 if (buffer_ != nullptr && data_length_ > 0) {
130 memcpy(new_buffer, buffer_, data_length_);
131 }
Niels Möllere7547d52018-11-01 09:33:08 +0100132 delete[] buffer_;
133 buffer_ = new_buffer;
134 buffer_length_ = size;
135 return SR_SUCCESS;
136 }
137
138 if (error) {
139 *error = ENOMEM;
140 }
141 return SR_ERROR;
142}
143
144} // namespace rtc