xref: /aosp_15_r20/external/cronet/net/base/io_buffer.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "net/base/io_buffer.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <utility>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/containers/heap_array.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/numerics/safe_math.h"
12*6777b538SAndroid Build Coastguard Worker 
13*6777b538SAndroid Build Coastguard Worker namespace net {
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker // TODO(eroman): IOBuffer is being converted to require buffer sizes and offsets
16*6777b538SAndroid Build Coastguard Worker // be specified as "size_t" rather than "int" (crbug.com/488553). To facilitate
17*6777b538SAndroid Build Coastguard Worker // this move (since LOTS of code needs to be updated), this function ensures
18*6777b538SAndroid Build Coastguard Worker // that sizes can be safely converted to an "int" without truncation. The
19*6777b538SAndroid Build Coastguard Worker // assert ensures calling this with an "int" argument is also safe.
AssertValidBufferSize(size_t size)20*6777b538SAndroid Build Coastguard Worker void IOBuffer::AssertValidBufferSize(size_t size) {
21*6777b538SAndroid Build Coastguard Worker   static_assert(sizeof(size_t) >= sizeof(int));
22*6777b538SAndroid Build Coastguard Worker   base::CheckedNumeric<int>(size).ValueOrDie();
23*6777b538SAndroid Build Coastguard Worker }
24*6777b538SAndroid Build Coastguard Worker 
25*6777b538SAndroid Build Coastguard Worker IOBuffer::IOBuffer() = default;
26*6777b538SAndroid Build Coastguard Worker 
IOBuffer(base::span<char> data)27*6777b538SAndroid Build Coastguard Worker IOBuffer::IOBuffer(base::span<char> data)
28*6777b538SAndroid Build Coastguard Worker     : data_(data.data()), size_(data.size()) {
29*6777b538SAndroid Build Coastguard Worker   AssertValidBufferSize(size_);
30*6777b538SAndroid Build Coastguard Worker }
31*6777b538SAndroid Build Coastguard Worker 
IOBuffer(base::span<uint8_t> data)32*6777b538SAndroid Build Coastguard Worker IOBuffer::IOBuffer(base::span<uint8_t> data)
33*6777b538SAndroid Build Coastguard Worker     : IOBuffer(base::as_writable_chars(data)) {}
34*6777b538SAndroid Build Coastguard Worker 
35*6777b538SAndroid Build Coastguard Worker IOBuffer::~IOBuffer() = default;
36*6777b538SAndroid Build Coastguard Worker 
37*6777b538SAndroid Build Coastguard Worker IOBufferWithSize::IOBufferWithSize() = default;
38*6777b538SAndroid Build Coastguard Worker 
IOBufferWithSize(size_t buffer_size)39*6777b538SAndroid Build Coastguard Worker IOBufferWithSize::IOBufferWithSize(size_t buffer_size) {
40*6777b538SAndroid Build Coastguard Worker   AssertValidBufferSize(buffer_size);
41*6777b538SAndroid Build Coastguard Worker   storage_ = base::HeapArray<char>::Uninit(buffer_size);
42*6777b538SAndroid Build Coastguard Worker   size_ = storage_.size();
43*6777b538SAndroid Build Coastguard Worker   data_ = storage_.data();
44*6777b538SAndroid Build Coastguard Worker }
45*6777b538SAndroid Build Coastguard Worker 
~IOBufferWithSize()46*6777b538SAndroid Build Coastguard Worker IOBufferWithSize::~IOBufferWithSize() {
47*6777b538SAndroid Build Coastguard Worker   // Clear pointer before this destructor makes it dangle.
48*6777b538SAndroid Build Coastguard Worker   data_ = nullptr;
49*6777b538SAndroid Build Coastguard Worker }
50*6777b538SAndroid Build Coastguard Worker 
StringIOBuffer(std::string s)51*6777b538SAndroid Build Coastguard Worker StringIOBuffer::StringIOBuffer(std::string s) : string_data_(std::move(s)) {
52*6777b538SAndroid Build Coastguard Worker   // Can't pass `s.data()` directly to IOBuffer constructor since moving
53*6777b538SAndroid Build Coastguard Worker   // from `s` may invalidate it. This is especially true for libc++ short
54*6777b538SAndroid Build Coastguard Worker   // string optimization where the data may be held in the string variable
55*6777b538SAndroid Build Coastguard Worker   // itself, instead of in a movable backing store.
56*6777b538SAndroid Build Coastguard Worker   AssertValidBufferSize(string_data_.size());
57*6777b538SAndroid Build Coastguard Worker   data_ = string_data_.data();
58*6777b538SAndroid Build Coastguard Worker   size_ = string_data_.size();
59*6777b538SAndroid Build Coastguard Worker }
60*6777b538SAndroid Build Coastguard Worker 
~StringIOBuffer()61*6777b538SAndroid Build Coastguard Worker StringIOBuffer::~StringIOBuffer() {
62*6777b538SAndroid Build Coastguard Worker   // Clear pointer before this destructor makes it dangle.
63*6777b538SAndroid Build Coastguard Worker   data_ = nullptr;
64*6777b538SAndroid Build Coastguard Worker }
65*6777b538SAndroid Build Coastguard Worker 
DrainableIOBuffer(scoped_refptr<IOBuffer> base,size_t size)66*6777b538SAndroid Build Coastguard Worker DrainableIOBuffer::DrainableIOBuffer(scoped_refptr<IOBuffer> base, size_t size)
67*6777b538SAndroid Build Coastguard Worker     : IOBuffer(base->span().first(size)), base_(std::move(base)) {}
68*6777b538SAndroid Build Coastguard Worker 
DidConsume(int bytes)69*6777b538SAndroid Build Coastguard Worker void DrainableIOBuffer::DidConsume(int bytes) {
70*6777b538SAndroid Build Coastguard Worker   SetOffset(used_ + bytes);
71*6777b538SAndroid Build Coastguard Worker }
72*6777b538SAndroid Build Coastguard Worker 
BytesRemaining() const73*6777b538SAndroid Build Coastguard Worker int DrainableIOBuffer::BytesRemaining() const {
74*6777b538SAndroid Build Coastguard Worker   return size_ - used_;
75*6777b538SAndroid Build Coastguard Worker }
76*6777b538SAndroid Build Coastguard Worker 
77*6777b538SAndroid Build Coastguard Worker // Returns the number of consumed bytes.
BytesConsumed() const78*6777b538SAndroid Build Coastguard Worker int DrainableIOBuffer::BytesConsumed() const {
79*6777b538SAndroid Build Coastguard Worker   return used_;
80*6777b538SAndroid Build Coastguard Worker }
81*6777b538SAndroid Build Coastguard Worker 
SetOffset(int bytes)82*6777b538SAndroid Build Coastguard Worker void DrainableIOBuffer::SetOffset(int bytes) {
83*6777b538SAndroid Build Coastguard Worker   CHECK_GE(bytes, 0);
84*6777b538SAndroid Build Coastguard Worker   CHECK_LE(bytes, size_);
85*6777b538SAndroid Build Coastguard Worker   used_ = bytes;
86*6777b538SAndroid Build Coastguard Worker   data_ = base_->data() + used_;
87*6777b538SAndroid Build Coastguard Worker }
88*6777b538SAndroid Build Coastguard Worker 
~DrainableIOBuffer()89*6777b538SAndroid Build Coastguard Worker DrainableIOBuffer::~DrainableIOBuffer() {
90*6777b538SAndroid Build Coastguard Worker   // Clear ptr before this destructor destroys the |base_| instance,
91*6777b538SAndroid Build Coastguard Worker   // making it dangle.
92*6777b538SAndroid Build Coastguard Worker   data_ = nullptr;
93*6777b538SAndroid Build Coastguard Worker }
94*6777b538SAndroid Build Coastguard Worker 
95*6777b538SAndroid Build Coastguard Worker GrowableIOBuffer::GrowableIOBuffer() = default;
96*6777b538SAndroid Build Coastguard Worker 
SetCapacity(int capacity)97*6777b538SAndroid Build Coastguard Worker void GrowableIOBuffer::SetCapacity(int capacity) {
98*6777b538SAndroid Build Coastguard Worker   CHECK_GE(capacity, 0);
99*6777b538SAndroid Build Coastguard Worker   // this will get reset in `set_offset`.
100*6777b538SAndroid Build Coastguard Worker   data_ = nullptr;
101*6777b538SAndroid Build Coastguard Worker   size_ = 0;
102*6777b538SAndroid Build Coastguard Worker 
103*6777b538SAndroid Build Coastguard Worker   // realloc will crash if it fails.
104*6777b538SAndroid Build Coastguard Worker   real_data_.reset(static_cast<char*>(realloc(real_data_.release(), capacity)));
105*6777b538SAndroid Build Coastguard Worker 
106*6777b538SAndroid Build Coastguard Worker   capacity_ = capacity;
107*6777b538SAndroid Build Coastguard Worker   if (offset_ > capacity)
108*6777b538SAndroid Build Coastguard Worker     set_offset(capacity);
109*6777b538SAndroid Build Coastguard Worker   else
110*6777b538SAndroid Build Coastguard Worker     set_offset(offset_);  // The pointer may have changed.
111*6777b538SAndroid Build Coastguard Worker }
112*6777b538SAndroid Build Coastguard Worker 
set_offset(int offset)113*6777b538SAndroid Build Coastguard Worker void GrowableIOBuffer::set_offset(int offset) {
114*6777b538SAndroid Build Coastguard Worker   CHECK_GE(offset, 0);
115*6777b538SAndroid Build Coastguard Worker   CHECK_LE(offset, capacity_);
116*6777b538SAndroid Build Coastguard Worker   offset_ = offset;
117*6777b538SAndroid Build Coastguard Worker   data_ = real_data_.get() + offset;
118*6777b538SAndroid Build Coastguard Worker   size_ = capacity_ - offset;
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker 
RemainingCapacity()121*6777b538SAndroid Build Coastguard Worker int GrowableIOBuffer::RemainingCapacity() {
122*6777b538SAndroid Build Coastguard Worker   return capacity_ - offset_;
123*6777b538SAndroid Build Coastguard Worker }
124*6777b538SAndroid Build Coastguard Worker 
StartOfBuffer()125*6777b538SAndroid Build Coastguard Worker char* GrowableIOBuffer::StartOfBuffer() {
126*6777b538SAndroid Build Coastguard Worker   return real_data_.get();
127*6777b538SAndroid Build Coastguard Worker }
128*6777b538SAndroid Build Coastguard Worker 
everything()129*6777b538SAndroid Build Coastguard Worker base::span<uint8_t> GrowableIOBuffer::everything() {
130*6777b538SAndroid Build Coastguard Worker   return base::as_writable_bytes(
131*6777b538SAndroid Build Coastguard Worker       // SAFETY: The capacity_ is the size of the allocation.
132*6777b538SAndroid Build Coastguard Worker       UNSAFE_BUFFERS(
133*6777b538SAndroid Build Coastguard Worker           base::span(real_data_.get(), base::checked_cast<size_t>(capacity_))));
134*6777b538SAndroid Build Coastguard Worker }
135*6777b538SAndroid Build Coastguard Worker 
everything() const136*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> GrowableIOBuffer::everything() const {
137*6777b538SAndroid Build Coastguard Worker   return base::as_bytes(
138*6777b538SAndroid Build Coastguard Worker       // SAFETY: The capacity_ is the size of the allocation.
139*6777b538SAndroid Build Coastguard Worker       UNSAFE_BUFFERS(
140*6777b538SAndroid Build Coastguard Worker           base::span(real_data_.get(), base::checked_cast<size_t>(capacity_))));
141*6777b538SAndroid Build Coastguard Worker }
142*6777b538SAndroid Build Coastguard Worker 
~GrowableIOBuffer()143*6777b538SAndroid Build Coastguard Worker GrowableIOBuffer::~GrowableIOBuffer() {
144*6777b538SAndroid Build Coastguard Worker   data_ = nullptr;
145*6777b538SAndroid Build Coastguard Worker }
146*6777b538SAndroid Build Coastguard Worker 
147*6777b538SAndroid Build Coastguard Worker PickledIOBuffer::PickledIOBuffer() = default;
148*6777b538SAndroid Build Coastguard Worker 
Done()149*6777b538SAndroid Build Coastguard Worker void PickledIOBuffer::Done() {
150*6777b538SAndroid Build Coastguard Worker   data_ = const_cast<char*>(pickle_.data_as_char());
151*6777b538SAndroid Build Coastguard Worker   size_ = pickle_.size();
152*6777b538SAndroid Build Coastguard Worker }
153*6777b538SAndroid Build Coastguard Worker 
~PickledIOBuffer()154*6777b538SAndroid Build Coastguard Worker PickledIOBuffer::~PickledIOBuffer() {
155*6777b538SAndroid Build Coastguard Worker   // Avoid dangling ptr when this destructor destroys the pickle.
156*6777b538SAndroid Build Coastguard Worker   data_ = nullptr;
157*6777b538SAndroid Build Coastguard Worker }
158*6777b538SAndroid Build Coastguard Worker 
WrappedIOBuffer(base::span<const char> data)159*6777b538SAndroid Build Coastguard Worker WrappedIOBuffer::WrappedIOBuffer(base::span<const char> data)
160*6777b538SAndroid Build Coastguard Worker     : IOBuffer(base::make_span(const_cast<char*>(data.data()), data.size())) {}
161*6777b538SAndroid Build Coastguard Worker 
WrappedIOBuffer(base::span<const uint8_t> data)162*6777b538SAndroid Build Coastguard Worker WrappedIOBuffer::WrappedIOBuffer(base::span<const uint8_t> data)
163*6777b538SAndroid Build Coastguard Worker     : WrappedIOBuffer(base::as_chars(data)) {}
164*6777b538SAndroid Build Coastguard Worker 
165*6777b538SAndroid Build Coastguard Worker WrappedIOBuffer::~WrappedIOBuffer() = default;
166*6777b538SAndroid Build Coastguard Worker 
167*6777b538SAndroid Build Coastguard Worker }  // namespace net
168