| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/base/io_buffer.h" |
| |
| #include "base/logging.h" |
| #include "base/numerics/safe_math.h" |
| #include "starboard/memory.h" |
| |
| namespace net { |
| |
| namespace { |
| |
| // TODO(eroman): IOBuffer is being converted to require buffer sizes and offsets |
| // be specified as "size_t" rather than "int" (crbug.com/488553). To facilitate |
| // this move (since LOTS of code needs to be updated), both "size_t" and "int |
| // are being accepted. When using "size_t" this function ensures that it can be |
| // safely converted to an "int" without truncation. |
| void AssertValidBufferSize(size_t size) { |
| base::CheckedNumeric<int>(size).ValueOrDie(); |
| } |
| |
| void AssertValidBufferSize(int size) { |
| CHECK_GE(size, 0); |
| } |
| |
| } // namespace |
| |
| IOBuffer::IOBuffer() |
| : data_(NULL) { |
| } |
| |
| IOBuffer::IOBuffer(int buffer_size) { |
| AssertValidBufferSize(buffer_size); |
| data_ = new char[buffer_size]; |
| } |
| |
| IOBuffer::IOBuffer(size_t buffer_size) { |
| AssertValidBufferSize(buffer_size); |
| data_ = new char[buffer_size]; |
| } |
| |
| IOBuffer::IOBuffer(char* data) |
| : data_(data) { |
| } |
| |
| IOBuffer::~IOBuffer() { |
| delete[] data_; |
| data_ = NULL; |
| } |
| |
| IOBufferWithSize::IOBufferWithSize(int size) |
| : IOBuffer(size), |
| size_(size) { |
| AssertValidBufferSize(size); |
| } |
| |
| IOBufferWithSize::IOBufferWithSize(size_t size) : IOBuffer(size), size_(size) { |
| // Note: Size check is done in superclass' constructor. |
| } |
| |
| IOBufferWithSize::IOBufferWithSize(char* data, int size) |
| : IOBuffer(data), |
| size_(size) { |
| AssertValidBufferSize(size); |
| } |
| |
| IOBufferWithSize::IOBufferWithSize(char* data, size_t size) |
| : IOBuffer(data), size_(size) { |
| AssertValidBufferSize(size); |
| } |
| |
| IOBufferWithSize::~IOBufferWithSize() = default; |
| |
| StringIOBuffer::StringIOBuffer(const std::string& s) |
| : IOBuffer(static_cast<char*>(NULL)), |
| string_data_(s) { |
| AssertValidBufferSize(s.size()); |
| data_ = const_cast<char*>(string_data_.data()); |
| } |
| |
| StringIOBuffer::StringIOBuffer(std::unique_ptr<std::string> s) |
| : IOBuffer(static_cast<char*>(NULL)) { |
| AssertValidBufferSize(s->size()); |
| string_data_.swap(*s.get()); |
| data_ = const_cast<char*>(string_data_.data()); |
| } |
| |
| StringIOBuffer::~StringIOBuffer() { |
| // We haven't allocated the buffer, so remove it before the base class |
| // destructor tries to delete[] it. |
| data_ = NULL; |
| } |
| |
| DrainableIOBuffer::DrainableIOBuffer(scoped_refptr<IOBuffer> base, int size) |
| : IOBuffer(base->data()), base_(std::move(base)), size_(size), used_(0) { |
| AssertValidBufferSize(size); |
| } |
| |
| DrainableIOBuffer::DrainableIOBuffer(scoped_refptr<IOBuffer> base, size_t size) |
| : IOBuffer(base->data()), base_(std::move(base)), size_(size), used_(0) { |
| AssertValidBufferSize(size); |
| } |
| |
| void DrainableIOBuffer::DidConsume(int bytes) { |
| SetOffset(used_ + bytes); |
| } |
| |
| int DrainableIOBuffer::BytesRemaining() const { |
| return size_ - used_; |
| } |
| |
| // Returns the number of consumed bytes. |
| int DrainableIOBuffer::BytesConsumed() const { |
| return used_; |
| } |
| |
| void DrainableIOBuffer::SetOffset(int bytes) { |
| DCHECK_GE(bytes, 0); |
| DCHECK_LE(bytes, size_); |
| used_ = bytes; |
| data_ = base_->data() + used_; |
| } |
| |
| DrainableIOBuffer::~DrainableIOBuffer() { |
| // The buffer is owned by the |base_| instance. |
| data_ = NULL; |
| } |
| |
| GrowableIOBuffer::GrowableIOBuffer() |
| : IOBuffer(), |
| capacity_(0), |
| offset_(0) { |
| } |
| |
| void GrowableIOBuffer::SetCapacity(int capacity) { |
| DCHECK_GE(capacity, 0); |
| // realloc will crash if it fails. |
| // Calling reallocate with size 0 and a non-null pointer causes memory leaks |
| // on many platforms, since it may return nullptr while also not deallocating |
| // the previously allocated memory. |
| if (real_data_ && capacity == 0) { |
| free(real_data_.release()); |
| real_data_.reset(); |
| } else { |
| real_data_.reset( |
| static_cast<char*>(realloc(real_data_.release(), capacity))); |
| } |
| capacity_ = capacity; |
| if (offset_ > capacity) |
| set_offset(capacity); |
| else |
| set_offset(offset_); // The pointer may have changed. |
| } |
| |
| void GrowableIOBuffer::set_offset(int offset) { |
| DCHECK_GE(offset, 0); |
| DCHECK_LE(offset, capacity_); |
| offset_ = offset; |
| data_ = real_data_.get() + offset; |
| } |
| |
| int GrowableIOBuffer::RemainingCapacity() { |
| return capacity_ - offset_; |
| } |
| |
| char* GrowableIOBuffer::StartOfBuffer() { |
| return real_data_.get(); |
| } |
| |
| GrowableIOBuffer::~GrowableIOBuffer() { |
| data_ = NULL; |
| } |
| |
| PickledIOBuffer::PickledIOBuffer() : IOBuffer() { |
| } |
| |
| void PickledIOBuffer::Done() { |
| data_ = const_cast<char*>(static_cast<const char*>(pickle_.data())); |
| } |
| |
| PickledIOBuffer::~PickledIOBuffer() { |
| data_ = NULL; |
| } |
| |
| WrappedIOBuffer::WrappedIOBuffer(const char* data) |
| : IOBuffer(const_cast<char*>(data)) { |
| } |
| |
| WrappedIOBuffer::~WrappedIOBuffer() { |
| data_ = NULL; |
| } |
| |
| } // namespace net |