• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
11 #include "rtc_base/memory_stream.h"
12 
13 #include <errno.h>
14 #include <string.h>
15 
16 #include <algorithm>
17 
18 #include "rtc_base/checks.h"
19 
20 namespace rtc {
21 
GetState() const22 StreamState MemoryStream::GetState() const {
23   return SS_OPEN;
24 }
25 
Read(rtc::ArrayView<uint8_t> buffer,size_t & bytes_read,int & error)26 StreamResult MemoryStream::Read(rtc::ArrayView<uint8_t> buffer,
27                                 size_t& bytes_read,
28                                 int& error) {
29   if (seek_position_ >= data_length_) {
30     return SR_EOS;
31   }
32   size_t available = data_length_ - seek_position_;
33   size_t bytes;
34   if (buffer.size() > available) {
35     // Read partial buffer
36     bytes = available;
37   } else {
38     bytes = buffer.size();
39   }
40   memcpy(buffer.data(), &buffer_[seek_position_], bytes);
41   seek_position_ += bytes;
42   bytes_read = bytes;
43   return SR_SUCCESS;
44 }
45 
Write(rtc::ArrayView<const uint8_t> buffer,size_t & bytes_written,int & error)46 StreamResult MemoryStream::Write(rtc::ArrayView<const uint8_t> buffer,
47                                  size_t& bytes_written,
48                                  int& error) {
49   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
54     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);
57     if (SR_SUCCESS != result) {
58       return result;
59     }
60     RTC_DCHECK(buffer_length_ >= new_buffer_length);
61     available = buffer_length_ - seek_position_;
62   }
63 
64   size_t bytes = buffer.size();
65   if (bytes > available) {
66     bytes = available;
67   }
68   memcpy(&buffer_[seek_position_], buffer.data(), bytes);
69   seek_position_ += bytes;
70   if (data_length_ < seek_position_) {
71     data_length_ = seek_position_;
72   }
73   bytes_written = bytes;
74   return SR_SUCCESS;
75 }
76 
Close()77 void MemoryStream::Close() {
78   // nothing to do
79 }
80 
SetPosition(size_t position)81 bool MemoryStream::SetPosition(size_t position) {
82   if (position > data_length_)
83     return false;
84   seek_position_ = position;
85   return true;
86 }
87 
GetPosition(size_t * position) const88 bool MemoryStream::GetPosition(size_t* position) const {
89   if (position)
90     *position = seek_position_;
91   return true;
92 }
93 
Rewind()94 void MemoryStream::Rewind() {
95   seek_position_ = 0;
96 }
97 
GetSize(size_t * size) const98 bool MemoryStream::GetSize(size_t* size) const {
99   if (size)
100     *size = data_length_;
101   return true;
102 }
103 
ReserveSize(size_t size)104 bool MemoryStream::ReserveSize(size_t size) {
105   return (SR_SUCCESS == DoReserve(size, nullptr));
106 }
107 
108 ///////////////////////////////////////////////////////////////////////////////
109 
MemoryStream()110 MemoryStream::MemoryStream() {}
111 
~MemoryStream()112 MemoryStream::~MemoryStream() {
113   delete[] buffer_;
114 }
115 
SetData(const void * data,size_t length)116 void 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 
DoReserve(size_t size,int * error)124 StreamResult 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]) {
129     if (buffer_ != nullptr && data_length_ > 0) {
130       memcpy(new_buffer, buffer_, data_length_);
131     }
132     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
145