xref: /aosp_15_r20/external/webrtc/rtc_base/copy_on_write_buffer.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2016 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "rtc_base/copy_on_write_buffer.h"
12 
13 #include <stddef.h>
14 
15 #include "absl/strings/string_view.h"
16 
17 namespace rtc {
18 
CopyOnWriteBuffer()19 CopyOnWriteBuffer::CopyOnWriteBuffer() : offset_(0), size_(0) {
20   RTC_DCHECK(IsConsistent());
21 }
22 
CopyOnWriteBuffer(const CopyOnWriteBuffer & buf)23 CopyOnWriteBuffer::CopyOnWriteBuffer(const CopyOnWriteBuffer& buf)
24     : buffer_(buf.buffer_), offset_(buf.offset_), size_(buf.size_) {}
25 
CopyOnWriteBuffer(CopyOnWriteBuffer && buf)26 CopyOnWriteBuffer::CopyOnWriteBuffer(CopyOnWriteBuffer&& buf)
27     : buffer_(std::move(buf.buffer_)), offset_(buf.offset_), size_(buf.size_) {
28   buf.offset_ = 0;
29   buf.size_ = 0;
30   RTC_DCHECK(IsConsistent());
31 }
32 
CopyOnWriteBuffer(absl::string_view s)33 CopyOnWriteBuffer::CopyOnWriteBuffer(absl::string_view s)
34     : CopyOnWriteBuffer(s.data(), s.length()) {}
35 
CopyOnWriteBuffer(size_t size)36 CopyOnWriteBuffer::CopyOnWriteBuffer(size_t size)
37     : buffer_(size > 0 ? new RefCountedBuffer(size) : nullptr),
38       offset_(0),
39       size_(size) {
40   RTC_DCHECK(IsConsistent());
41 }
42 
CopyOnWriteBuffer(size_t size,size_t capacity)43 CopyOnWriteBuffer::CopyOnWriteBuffer(size_t size, size_t capacity)
44     : buffer_(size > 0 || capacity > 0 ? new RefCountedBuffer(size, capacity)
45                                        : nullptr),
46       offset_(0),
47       size_(size) {
48   RTC_DCHECK(IsConsistent());
49 }
50 
51 CopyOnWriteBuffer::~CopyOnWriteBuffer() = default;
52 
operator ==(const CopyOnWriteBuffer & buf) const53 bool CopyOnWriteBuffer::operator==(const CopyOnWriteBuffer& buf) const {
54   // Must either be the same view of the same buffer or have the same contents.
55   RTC_DCHECK(IsConsistent());
56   RTC_DCHECK(buf.IsConsistent());
57   return size_ == buf.size_ &&
58          (cdata() == buf.cdata() || memcmp(cdata(), buf.cdata(), size_) == 0);
59 }
60 
SetSize(size_t size)61 void CopyOnWriteBuffer::SetSize(size_t size) {
62   RTC_DCHECK(IsConsistent());
63   if (!buffer_) {
64     if (size > 0) {
65       buffer_ = new RefCountedBuffer(size);
66       offset_ = 0;
67       size_ = size;
68     }
69     RTC_DCHECK(IsConsistent());
70     return;
71   }
72 
73   if (size <= size_) {
74     size_ = size;
75     return;
76   }
77 
78   UnshareAndEnsureCapacity(std::max(capacity(), size));
79   buffer_->SetSize(size + offset_);
80   size_ = size;
81   RTC_DCHECK(IsConsistent());
82 }
83 
EnsureCapacity(size_t new_capacity)84 void CopyOnWriteBuffer::EnsureCapacity(size_t new_capacity) {
85   RTC_DCHECK(IsConsistent());
86   if (!buffer_) {
87     if (new_capacity > 0) {
88       buffer_ = new RefCountedBuffer(0, new_capacity);
89       offset_ = 0;
90       size_ = 0;
91     }
92     RTC_DCHECK(IsConsistent());
93     return;
94   } else if (new_capacity <= capacity()) {
95     return;
96   }
97 
98   UnshareAndEnsureCapacity(new_capacity);
99   RTC_DCHECK(IsConsistent());
100 }
101 
Clear()102 void CopyOnWriteBuffer::Clear() {
103   if (!buffer_)
104     return;
105 
106   if (buffer_->HasOneRef()) {
107     buffer_->Clear();
108   } else {
109     buffer_ = new RefCountedBuffer(0, capacity());
110   }
111   offset_ = 0;
112   size_ = 0;
113   RTC_DCHECK(IsConsistent());
114 }
115 
UnshareAndEnsureCapacity(size_t new_capacity)116 void CopyOnWriteBuffer::UnshareAndEnsureCapacity(size_t new_capacity) {
117   if (buffer_->HasOneRef() && new_capacity <= capacity()) {
118     return;
119   }
120 
121   buffer_ =
122       new RefCountedBuffer(buffer_->data() + offset_, size_, new_capacity);
123   offset_ = 0;
124   RTC_DCHECK(IsConsistent());
125 }
126 
127 }  // namespace rtc
128