blob: 8874ea918765447f927cd74b3680dc8891d48cc8 [file] [log] [blame]
jbauch13041cf2016-02-25 06:16:52 -08001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "rtc_base/copyonwritebuffer.h"
jbauch13041cf2016-02-25 06:16:52 -080012
13namespace rtc {
14
15CopyOnWriteBuffer::CopyOnWriteBuffer() {
16 RTC_DCHECK(IsConsistent());
17}
18
19CopyOnWriteBuffer::CopyOnWriteBuffer(const CopyOnWriteBuffer& buf)
Yves Gerey665174f2018-06-19 15:03:05 +020020 : buffer_(buf.buffer_) {}
jbauch13041cf2016-02-25 06:16:52 -080021
danilchapd8a9c532016-07-30 12:39:26 -070022CopyOnWriteBuffer::CopyOnWriteBuffer(CopyOnWriteBuffer&& buf)
Yves Gerey665174f2018-06-19 15:03:05 +020023 : buffer_(std::move(buf.buffer_)) {}
jbauch13041cf2016-02-25 06:16:52 -080024
25CopyOnWriteBuffer::CopyOnWriteBuffer(size_t size)
26 : buffer_(size > 0 ? new RefCountedObject<Buffer>(size) : nullptr) {
27 RTC_DCHECK(IsConsistent());
28}
29
30CopyOnWriteBuffer::CopyOnWriteBuffer(size_t size, size_t capacity)
31 : buffer_(size > 0 || capacity > 0
Yves Gerey665174f2018-06-19 15:03:05 +020032 ? new RefCountedObject<Buffer>(size, capacity)
33 : nullptr) {
jbauch13041cf2016-02-25 06:16:52 -080034 RTC_DCHECK(IsConsistent());
35}
36
37CopyOnWriteBuffer::~CopyOnWriteBuffer() = default;
38
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020039bool CopyOnWriteBuffer::operator==(const CopyOnWriteBuffer& buf) const {
40 // Must either use the same buffer internally or have the same contents.
41 RTC_DCHECK(IsConsistent());
42 RTC_DCHECK(buf.IsConsistent());
43 return buffer_.get() == buf.buffer_.get() ||
Yves Gerey665174f2018-06-19 15:03:05 +020044 (buffer_.get() && buf.buffer_.get() &&
45 *buffer_.get() == *buf.buffer_.get());
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020046}
47
48void CopyOnWriteBuffer::SetSize(size_t size) {
49 RTC_DCHECK(IsConsistent());
50 if (!buffer_) {
51 if (size > 0) {
52 buffer_ = new RefCountedObject<Buffer>(size);
53 }
54 RTC_DCHECK(IsConsistent());
55 return;
56 }
57
58 // Clone data if referenced.
59 if (!buffer_->HasOneRef()) {
Yves Gerey665174f2018-06-19 15:03:05 +020060 buffer_ = new RefCountedObject<Buffer>(buffer_->data(),
61 std::min(buffer_->size(), size),
62 std::max(buffer_->capacity(), size));
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020063 }
64 buffer_->SetSize(size);
65 RTC_DCHECK(IsConsistent());
66}
67
68void CopyOnWriteBuffer::EnsureCapacity(size_t capacity) {
69 RTC_DCHECK(IsConsistent());
70 if (!buffer_) {
71 if (capacity > 0) {
72 buffer_ = new RefCountedObject<Buffer>(0, capacity);
73 }
74 RTC_DCHECK(IsConsistent());
75 return;
76 } else if (capacity <= buffer_->capacity()) {
77 return;
78 }
79
80 CloneDataIfReferenced(std::max(buffer_->capacity(), capacity));
81 buffer_->EnsureCapacity(capacity);
82 RTC_DCHECK(IsConsistent());
83}
84
85void CopyOnWriteBuffer::Clear() {
86 if (!buffer_)
87 return;
88
89 if (buffer_->HasOneRef()) {
90 buffer_->Clear();
91 } else {
92 buffer_ = new RefCountedObject<Buffer>(0, buffer_->capacity());
93 }
94 RTC_DCHECK(IsConsistent());
95}
96
97void CopyOnWriteBuffer::CloneDataIfReferenced(size_t new_capacity) {
98 if (buffer_->HasOneRef()) {
99 return;
100 }
101
102 buffer_ = new RefCountedObject<Buffer>(buffer_->data(), buffer_->size(),
Yves Gerey665174f2018-06-19 15:03:05 +0200103 new_capacity);
Danil Chapovalov3626d7e2016-09-14 17:14:30 +0200104 RTC_DCHECK(IsConsistent());
105}
106
jbauch13041cf2016-02-25 06:16:52 -0800107} // namespace rtc