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