1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/base/io_buffer.h"
6 
7 #include "base/check_op.h"
8 #include "base/numerics/safe_math.h"
9 
10 namespace net {
11 
12 // TODO(eroman): IOBuffer is being converted to require buffer sizes and offsets
13 // be specified as "size_t" rather than "int" (crbug.com/488553). To facilitate
14 // this move (since LOTS of code needs to be updated), both "size_t" and "int
15 // are being accepted. When using "size_t" this function ensures that it can be
16 // safely converted to an "int" without truncation.
AssertValidBufferSize(size_t size)17 void IOBuffer::AssertValidBufferSize(size_t size) {
18   base::CheckedNumeric<int>(size).ValueOrDie();
19 }
20 
AssertValidBufferSize(int size)21 void IOBuffer::AssertValidBufferSize(int size) {
22   CHECK_GE(size, 0);
23 }
24 
IOBuffer()25 IOBuffer::IOBuffer() : data_(nullptr) {}
26 
IOBuffer(size_t buffer_size)27 IOBuffer::IOBuffer(size_t buffer_size) {
28   AssertValidBufferSize(buffer_size);
29   data_ = new char[buffer_size];
30 }
31 
IOBuffer(char * data)32 IOBuffer::IOBuffer(char* data)
33     : data_(data) {
34 }
35 
~IOBuffer()36 IOBuffer::~IOBuffer() {
37   delete[] data_;
38   data_ = nullptr;
39 }
40 
IOBufferWithSize(size_t size)41 IOBufferWithSize::IOBufferWithSize(size_t size) : IOBuffer(size), size_(size) {
42   // Note: Size check is done in superclass' constructor.
43 }
44 
IOBufferWithSize(char * data,size_t size)45 IOBufferWithSize::IOBufferWithSize(char* data, size_t size)
46     : IOBuffer(data), size_(size) {
47   AssertValidBufferSize(size);
48 }
49 
50 IOBufferWithSize::~IOBufferWithSize() = default;
51 
StringIOBuffer(const std::string & s)52 StringIOBuffer::StringIOBuffer(const std::string& s)
53     : IOBuffer(static_cast<char*>(nullptr)), string_data_(s) {
54   AssertValidBufferSize(s.size());
55   data_ = const_cast<char*>(string_data_.data());
56 }
57 
StringIOBuffer(std::unique_ptr<std::string> s)58 StringIOBuffer::StringIOBuffer(std::unique_ptr<std::string> s)
59     : IOBuffer(static_cast<char*>(nullptr)) {
60   AssertValidBufferSize(s->size());
61   string_data_.swap(*s.get());
62   data_ = const_cast<char*>(string_data_.data());
63 }
64 
~StringIOBuffer()65 StringIOBuffer::~StringIOBuffer() {
66   // We haven't allocated the buffer, so remove it before the base class
67   // destructor tries to delete[] it.
68   data_ = nullptr;
69 }
70 
DrainableIOBuffer(scoped_refptr<IOBuffer> base,int size)71 DrainableIOBuffer::DrainableIOBuffer(scoped_refptr<IOBuffer> base, int size)
72     : IOBuffer(base->data()), base_(std::move(base)), size_(size), used_(0) {
73   AssertValidBufferSize(size);
74 }
75 
DrainableIOBuffer(scoped_refptr<IOBuffer> base,size_t size)76 DrainableIOBuffer::DrainableIOBuffer(scoped_refptr<IOBuffer> base, size_t size)
77     : IOBuffer(base->data()), base_(std::move(base)), size_(size), used_(0) {
78   AssertValidBufferSize(size);
79 }
80 
DidConsume(int bytes)81 void DrainableIOBuffer::DidConsume(int bytes) {
82   SetOffset(used_ + bytes);
83 }
84 
BytesRemaining() const85 int DrainableIOBuffer::BytesRemaining() const {
86   return size_ - used_;
87 }
88 
89 // Returns the number of consumed bytes.
BytesConsumed() const90 int DrainableIOBuffer::BytesConsumed() const {
91   return used_;
92 }
93 
SetOffset(int bytes)94 void DrainableIOBuffer::SetOffset(int bytes) {
95   DCHECK_GE(bytes, 0);
96   DCHECK_LE(bytes, size_);
97   used_ = bytes;
98   data_ = base_->data() + used_;
99 }
100 
~DrainableIOBuffer()101 DrainableIOBuffer::~DrainableIOBuffer() {
102   // The buffer is owned by the |base_| instance.
103   data_ = nullptr;
104 }
105 
GrowableIOBuffer()106 GrowableIOBuffer::GrowableIOBuffer()
107     : IOBuffer(),
108       capacity_(0),
109       offset_(0) {
110 }
111 
SetCapacity(int capacity)112 void GrowableIOBuffer::SetCapacity(int capacity) {
113   DCHECK_GE(capacity, 0);
114   // realloc will crash if it fails.
115   real_data_.reset(static_cast<char*>(realloc(real_data_.release(), capacity)));
116   capacity_ = capacity;
117   if (offset_ > capacity)
118     set_offset(capacity);
119   else
120     set_offset(offset_);  // The pointer may have changed.
121 }
122 
set_offset(int offset)123 void GrowableIOBuffer::set_offset(int offset) {
124   DCHECK_GE(offset, 0);
125   DCHECK_LE(offset, capacity_);
126   offset_ = offset;
127   data_ = real_data_.get() + offset;
128 }
129 
RemainingCapacity()130 int GrowableIOBuffer::RemainingCapacity() {
131   return capacity_ - offset_;
132 }
133 
StartOfBuffer()134 char* GrowableIOBuffer::StartOfBuffer() {
135   return real_data_.get();
136 }
137 
~GrowableIOBuffer()138 GrowableIOBuffer::~GrowableIOBuffer() {
139   data_ = nullptr;
140 }
141 
PickledIOBuffer()142 PickledIOBuffer::PickledIOBuffer() : IOBuffer() {
143 }
144 
Done()145 void PickledIOBuffer::Done() {
146   data_ = const_cast<char*>(static_cast<const char*>(pickle_.data()));
147 }
148 
~PickledIOBuffer()149 PickledIOBuffer::~PickledIOBuffer() {
150   data_ = nullptr;
151 }
152 
WrappedIOBuffer(const char * data)153 WrappedIOBuffer::WrappedIOBuffer(const char* data)
154     : IOBuffer(const_cast<char*>(data)) {
155 }
156 
~WrappedIOBuffer()157 WrappedIOBuffer::~WrappedIOBuffer() {
158   data_ = nullptr;
159 }
160 
161 }  // namespace net
162