Move MemoryStream to separate source files, and to a test target.

Also delete the base class MemoryStreamBase.

Bug: webrtc:6424
Change-Id: I7eec40ecff17c7c65fdf55882bccb2abaf1d5d84
Reviewed-on: https://webrtc-review.googlesource.com/c/108622
Commit-Queue: Niels Moller <nisse@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25494}
This commit is contained in:
Niels Möller 2018-11-01 09:33:08 +01:00 committed by Commit Bot
parent 9f878f6e97
commit e7547d5545
7 changed files with 206 additions and 195 deletions

View file

@ -15,8 +15,8 @@
#include "p2p/base/pseudotcp.h" #include "p2p/base/pseudotcp.h"
#include "rtc_base/gunit.h" #include "rtc_base/gunit.h"
#include "rtc_base/helpers.h" #include "rtc_base/helpers.h"
#include "rtc_base/memory_stream.h"
#include "rtc_base/messagehandler.h" #include "rtc_base/messagehandler.h"
#include "rtc_base/stream.h"
#include "rtc_base/thread.h" #include "rtc_base/thread.h"
#include "rtc_base/timeutils.h" #include "rtc_base/timeutils.h"

View file

@ -960,6 +960,8 @@ rtc_source_set("rtc_base_tests_utils") {
"firewallsocketserver.h", "firewallsocketserver.h",
"gunit.cc", "gunit.cc",
"gunit.h", "gunit.h",
"memory_stream.cc",
"memory_stream.h",
"memory_usage.cc", "memory_usage.cc",
"memory_usage.h", "memory_usage.h",
"natserver.cc", "natserver.cc",

143
rtc_base/memory_stream.cc Normal file
View file

@ -0,0 +1,143 @@
/*
* Copyright 2018 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <algorithm>
#include "rtc_base/memory_stream.h"
namespace rtc {
StreamState MemoryStream::GetState() const {
return SS_OPEN;
}
StreamResult MemoryStream::Read(void* buffer,
size_t bytes,
size_t* bytes_read,
int* error) {
if (seek_position_ >= data_length_) {
return SR_EOS;
}
size_t available = data_length_ - seek_position_;
if (bytes > available) {
// Read partial buffer
bytes = available;
}
memcpy(buffer, &buffer_[seek_position_], bytes);
seek_position_ += bytes;
if (bytes_read) {
*bytes_read = bytes;
}
return SR_SUCCESS;
}
StreamResult MemoryStream::Write(const void* buffer,
size_t bytes,
size_t* bytes_written,
int* error) {
size_t available = buffer_length_ - seek_position_;
if (0 == available) {
// Increase buffer size to the larger of:
// a) new position rounded up to next 256 bytes
// b) double the previous length
size_t new_buffer_length =
std::max(((seek_position_ + bytes) | 0xFF) + 1, buffer_length_ * 2);
StreamResult result = DoReserve(new_buffer_length, error);
if (SR_SUCCESS != result) {
return result;
}
RTC_DCHECK(buffer_length_ >= new_buffer_length);
available = buffer_length_ - seek_position_;
}
if (bytes > available) {
bytes = available;
}
memcpy(&buffer_[seek_position_], buffer, bytes);
seek_position_ += bytes;
if (data_length_ < seek_position_) {
data_length_ = seek_position_;
}
if (bytes_written) {
*bytes_written = bytes;
}
return SR_SUCCESS;
}
void MemoryStream::Close() {
// nothing to do
}
bool MemoryStream::SetPosition(size_t position) {
if (position > data_length_)
return false;
seek_position_ = position;
return true;
}
bool MemoryStream::GetPosition(size_t* position) const {
if (position)
*position = seek_position_;
return true;
}
bool MemoryStream::GetSize(size_t* size) const {
if (size)
*size = data_length_;
return true;
}
bool MemoryStream::ReserveSize(size_t size) {
return (SR_SUCCESS == DoReserve(size, nullptr));
}
///////////////////////////////////////////////////////////////////////////////
MemoryStream::MemoryStream() {}
MemoryStream::MemoryStream(const char* data) {
SetData(data, strlen(data));
}
MemoryStream::MemoryStream(const void* data, size_t length) {
SetData(data, length);
}
MemoryStream::~MemoryStream() {
delete[] buffer_;
}
void MemoryStream::SetData(const void* data, size_t length) {
data_length_ = buffer_length_ = length;
delete[] buffer_;
buffer_ = new char[buffer_length_];
memcpy(buffer_, data, data_length_);
seek_position_ = 0;
}
StreamResult MemoryStream::DoReserve(size_t size, int* error) {
if (buffer_length_ >= size)
return SR_SUCCESS;
if (char* new_buffer = new char[size]) {
memcpy(new_buffer, buffer_, data_length_);
delete[] buffer_;
buffer_ = new_buffer;
buffer_length_ = size;
return SR_SUCCESS;
}
if (error) {
*error = ENOMEM;
}
return SR_ERROR;
}
} // namespace rtc

59
rtc_base/memory_stream.h Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright 2018 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef RTC_BASE_MEMORY_STREAM_H_
#define RTC_BASE_MEMORY_STREAM_H_
#include "rtc_base/stream.h"
namespace rtc {
// MemoryStream dynamically resizes to accomodate written data.
class MemoryStream final : public StreamInterface {
public:
MemoryStream();
explicit MemoryStream(const char* data); // Calls SetData(data, strlen(data))
MemoryStream(const void* data, size_t length); // Calls SetData(data, length)
~MemoryStream() override;
StreamState GetState() const override;
StreamResult Read(void* buffer,
size_t bytes,
size_t* bytes_read,
int* error) override;
StreamResult Write(const void* buffer,
size_t bytes,
size_t* bytes_written,
int* error) override;
void Close() override;
bool SetPosition(size_t position) override;
bool GetPosition(size_t* position) const override;
bool GetSize(size_t* size) const override;
bool ReserveSize(size_t size) override;
char* GetBuffer() { return buffer_; }
const char* GetBuffer() const { return buffer_; }
void SetData(const void* data, size_t length);
private:
StreamResult DoReserve(size_t size, int* error);
// Invariant: 0 <= seek_position <= data_length_ <= buffer_length_
char* buffer_ = nullptr;
size_t buffer_length_ = 0;
size_t data_length_ = 0;
size_t seek_position_ = 0;
};
} // namespace rtc
#endif // RTC_BASE_MEMORY_STREAM_H_

View file

@ -17,6 +17,7 @@
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/gunit.h" #include "rtc_base/gunit.h"
#include "rtc_base/helpers.h" #include "rtc_base/helpers.h"
#include "rtc_base/memory_stream.h"
#include "rtc_base/messagedigest.h" #include "rtc_base/messagedigest.h"
#include "rtc_base/ssladapter.h" #include "rtc_base/ssladapter.h"
#include "rtc_base/sslidentity.h" #include "rtc_base/sslidentity.h"

View file

@ -347,143 +347,6 @@ void FileStream::DoClose() {
fclose(file_); fclose(file_);
} }
///////////////////////////////////////////////////////////////////////////////
// MemoryStream
///////////////////////////////////////////////////////////////////////////////
MemoryStreamBase::MemoryStreamBase()
: buffer_(nullptr), buffer_length_(0), data_length_(0), seek_position_(0) {}
StreamState MemoryStreamBase::GetState() const {
return SS_OPEN;
}
StreamResult MemoryStreamBase::Read(void* buffer,
size_t bytes,
size_t* bytes_read,
int* error) {
if (seek_position_ >= data_length_) {
return SR_EOS;
}
size_t available = data_length_ - seek_position_;
if (bytes > available) {
// Read partial buffer
bytes = available;
}
memcpy(buffer, &buffer_[seek_position_], bytes);
seek_position_ += bytes;
if (bytes_read) {
*bytes_read = bytes;
}
return SR_SUCCESS;
}
StreamResult MemoryStreamBase::Write(const void* buffer,
size_t bytes,
size_t* bytes_written,
int* error) {
size_t available = buffer_length_ - seek_position_;
if (0 == available) {
// Increase buffer size to the larger of:
// a) new position rounded up to next 256 bytes
// b) double the previous length
size_t new_buffer_length =
std::max(((seek_position_ + bytes) | 0xFF) + 1, buffer_length_ * 2);
StreamResult result = DoReserve(new_buffer_length, error);
if (SR_SUCCESS != result) {
return result;
}
RTC_DCHECK(buffer_length_ >= new_buffer_length);
available = buffer_length_ - seek_position_;
}
if (bytes > available) {
bytes = available;
}
memcpy(&buffer_[seek_position_], buffer, bytes);
seek_position_ += bytes;
if (data_length_ < seek_position_) {
data_length_ = seek_position_;
}
if (bytes_written) {
*bytes_written = bytes;
}
return SR_SUCCESS;
}
void MemoryStreamBase::Close() {
// nothing to do
}
bool MemoryStreamBase::SetPosition(size_t position) {
if (position > data_length_)
return false;
seek_position_ = position;
return true;
}
bool MemoryStreamBase::GetPosition(size_t* position) const {
if (position)
*position = seek_position_;
return true;
}
bool MemoryStreamBase::GetSize(size_t* size) const {
if (size)
*size = data_length_;
return true;
}
bool MemoryStreamBase::ReserveSize(size_t size) {
return (SR_SUCCESS == DoReserve(size, nullptr));
}
StreamResult MemoryStreamBase::DoReserve(size_t size, int* error) {
return (buffer_length_ >= size) ? SR_SUCCESS : SR_EOS;
}
///////////////////////////////////////////////////////////////////////////////
MemoryStream::MemoryStream() {}
MemoryStream::MemoryStream(const char* data) {
SetData(data, strlen(data));
}
MemoryStream::MemoryStream(const void* data, size_t length) {
SetData(data, length);
}
MemoryStream::~MemoryStream() {
delete[] buffer_;
}
void MemoryStream::SetData(const void* data, size_t length) {
data_length_ = buffer_length_ = length;
delete[] buffer_;
buffer_ = new char[buffer_length_];
memcpy(buffer_, data, data_length_);
seek_position_ = 0;
}
StreamResult MemoryStream::DoReserve(size_t size, int* error) {
if (buffer_length_ >= size)
return SR_SUCCESS;
if (char* new_buffer = new char[size]) {
memcpy(new_buffer, buffer_, data_length_);
delete[] buffer_;
buffer_ = new_buffer;
buffer_length_ = size;
return SR_SUCCESS;
}
if (error) {
*error = ENOMEM;
}
return SR_ERROR;
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// FifoBuffer // FifoBuffer
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View file

@ -261,63 +261,6 @@ class FileStream : public StreamInterface {
RTC_DISALLOW_COPY_AND_ASSIGN(FileStream); RTC_DISALLOW_COPY_AND_ASSIGN(FileStream);
}; };
///////////////////////////////////////////////////////////////////////////////
// MemoryStream is a simple implementation of a StreamInterface over in-memory
// data. Data is read and written at the current seek position. Reads return
// end-of-stream when they reach the end of data. Writes actually extend the
// end of data mark.
///////////////////////////////////////////////////////////////////////////////
class MemoryStreamBase : public StreamInterface {
public:
StreamState GetState() const override;
StreamResult Read(void* buffer,
size_t bytes,
size_t* bytes_read,
int* error) override;
StreamResult Write(const void* buffer,
size_t bytes,
size_t* bytes_written,
int* error) override;
void Close() override;
bool SetPosition(size_t position) override;
bool GetPosition(size_t* position) const override;
bool GetSize(size_t* size) const override;
bool ReserveSize(size_t size) override;
char* GetBuffer() { return buffer_; }
const char* GetBuffer() const { return buffer_; }
protected:
MemoryStreamBase();
virtual StreamResult DoReserve(size_t size, int* error);
// Invariant: 0 <= seek_position <= data_length_ <= buffer_length_
char* buffer_;
size_t buffer_length_;
size_t data_length_;
size_t seek_position_;
private:
RTC_DISALLOW_COPY_AND_ASSIGN(MemoryStreamBase);
};
// MemoryStream dynamically resizes to accomodate written data.
class MemoryStream : public MemoryStreamBase {
public:
MemoryStream();
explicit MemoryStream(const char* data); // Calls SetData(data, strlen(data))
MemoryStream(const void* data, size_t length); // Calls SetData(data, length)
~MemoryStream() override;
void SetData(const void* data, size_t length);
protected:
StreamResult DoReserve(size_t size, int* error) override;
};
// FifoBuffer allows for efficient, thread-safe buffering of data between // FifoBuffer allows for efficient, thread-safe buffering of data between
// writer and reader. As the data can wrap around the end of the buffer, // writer and reader. As the data can wrap around the end of the buffer,
// MemoryStreamBase can't help us here. // MemoryStreamBase can't help us here.