xref: /aosp_15_r20/external/webrtc/rtc_base/memory_stream.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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