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 namespace rtc {
16
CopyOnWriteBuffer()17 CopyOnWriteBuffer::CopyOnWriteBuffer() : offset_(0), size_(0) {
18 RTC_DCHECK(IsConsistent());
19 }
20
CopyOnWriteBuffer(const CopyOnWriteBuffer & buf)21 CopyOnWriteBuffer::CopyOnWriteBuffer(const CopyOnWriteBuffer& buf)
22 : buffer_(buf.buffer_), offset_(buf.offset_), size_(buf.size_) {}
23
CopyOnWriteBuffer(CopyOnWriteBuffer && buf)24 CopyOnWriteBuffer::CopyOnWriteBuffer(CopyOnWriteBuffer&& buf)
25 : buffer_(std::move(buf.buffer_)), offset_(buf.offset_), size_(buf.size_) {
26 buf.offset_ = 0;
27 buf.size_ = 0;
28 RTC_DCHECK(IsConsistent());
29 }
30
CopyOnWriteBuffer(const std::string & s)31 CopyOnWriteBuffer::CopyOnWriteBuffer(const std::string& s)
32 : CopyOnWriteBuffer(s.data(), s.length()) {}
33
CopyOnWriteBuffer(size_t size)34 CopyOnWriteBuffer::CopyOnWriteBuffer(size_t size)
35 : buffer_(size > 0 ? new RefCountedObject<Buffer>(size) : nullptr),
36 offset_(0),
37 size_(size) {
38 RTC_DCHECK(IsConsistent());
39 }
40
CopyOnWriteBuffer(size_t size,size_t capacity)41 CopyOnWriteBuffer::CopyOnWriteBuffer(size_t size, size_t capacity)
42 : buffer_(size > 0 || capacity > 0
43 ? new RefCountedObject<Buffer>(size, capacity)
44 : nullptr),
45 offset_(0),
46 size_(size) {
47 RTC_DCHECK(IsConsistent());
48 }
49
50 CopyOnWriteBuffer::~CopyOnWriteBuffer() = default;
51
operator ==(const CopyOnWriteBuffer & buf) const52 bool CopyOnWriteBuffer::operator==(const CopyOnWriteBuffer& buf) const {
53 // Must either be the same view of the same buffer or have the same contents.
54 RTC_DCHECK(IsConsistent());
55 RTC_DCHECK(buf.IsConsistent());
56 return size_ == buf.size_ &&
57 (cdata() == buf.cdata() || memcmp(cdata(), buf.cdata(), size_) == 0);
58 }
59
SetSize(size_t size)60 void CopyOnWriteBuffer::SetSize(size_t size) {
61 RTC_DCHECK(IsConsistent());
62 if (!buffer_) {
63 if (size > 0) {
64 buffer_ = new RefCountedObject<Buffer>(size);
65 offset_ = 0;
66 size_ = size;
67 }
68 RTC_DCHECK(IsConsistent());
69 return;
70 }
71
72 if (size <= size_) {
73 size_ = size;
74 return;
75 }
76
77 UnshareAndEnsureCapacity(std::max(capacity(), size));
78 buffer_->SetSize(size + offset_);
79 size_ = size;
80 RTC_DCHECK(IsConsistent());
81 }
82
EnsureCapacity(size_t new_capacity)83 void CopyOnWriteBuffer::EnsureCapacity(size_t new_capacity) {
84 RTC_DCHECK(IsConsistent());
85 if (!buffer_) {
86 if (new_capacity > 0) {
87 buffer_ = new RefCountedObject<Buffer>(0, new_capacity);
88 offset_ = 0;
89 size_ = 0;
90 }
91 RTC_DCHECK(IsConsistent());
92 return;
93 } else if (new_capacity <= capacity()) {
94 return;
95 }
96
97 UnshareAndEnsureCapacity(new_capacity);
98 RTC_DCHECK(IsConsistent());
99 }
100
Clear()101 void CopyOnWriteBuffer::Clear() {
102 if (!buffer_)
103 return;
104
105 if (buffer_->HasOneRef()) {
106 buffer_->Clear();
107 } else {
108 buffer_ = new RefCountedObject<Buffer>(0, capacity());
109 }
110 offset_ = 0;
111 size_ = 0;
112 RTC_DCHECK(IsConsistent());
113 }
114
UnshareAndEnsureCapacity(size_t new_capacity)115 void CopyOnWriteBuffer::UnshareAndEnsureCapacity(size_t new_capacity) {
116 if (buffer_->HasOneRef() && new_capacity <= capacity()) {
117 return;
118 }
119
120 buffer_ = new RefCountedObject<Buffer>(buffer_->data() + offset_, size_,
121 new_capacity);
122 offset_ = 0;
123 RTC_DCHECK(IsConsistent());
124 }
125
126 } // namespace rtc
127