| // 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) { | |
| SbMemoryDeallocate(real_data_.release()); | |
| real_data_.reset(); | |
| } else { | |
| real_data_.reset( | |
| static_cast<char*>(SbMemoryReallocate(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 |