blob: f3cc710f850f8e25a3e437f630b5cc7c9d940830 [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
Steve Anton10542f22019-01-11 09:11:00 -080011#include "rtc_base/copy_on_write_buffer.h"
jbauch13041cf2016-02-25 06:16:52 -080012
Yves Gerey988cc082018-10-23 12:03:01 +020013#include <stddef.h>
14
jbauch13041cf2016-02-25 06:16:52 -080015namespace rtc {
16
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020017CopyOnWriteBuffer::CopyOnWriteBuffer() : offset_(0), size_(0) {
jbauch13041cf2016-02-25 06:16:52 -080018 RTC_DCHECK(IsConsistent());
19}
20
21CopyOnWriteBuffer::CopyOnWriteBuffer(const CopyOnWriteBuffer& buf)
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020022 : buffer_(buf.buffer_), offset_(buf.offset_), size_(buf.size_) {}
jbauch13041cf2016-02-25 06:16:52 -080023
danilchapd8a9c532016-07-30 12:39:26 -070024CopyOnWriteBuffer::CopyOnWriteBuffer(CopyOnWriteBuffer&& buf)
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020025 : buffer_(std::move(buf.buffer_)), offset_(buf.offset_), size_(buf.size_) {
26 buf.offset_ = 0;
27 buf.size_ = 0;
28 RTC_DCHECK(IsConsistent());
29}
jbauch13041cf2016-02-25 06:16:52 -080030
Jeroen de Borst4f6d2332018-07-18 11:25:12 -070031CopyOnWriteBuffer::CopyOnWriteBuffer(const std::string& s)
32 : CopyOnWriteBuffer(s.data(), s.length()) {}
33
jbauch13041cf2016-02-25 06:16:52 -080034CopyOnWriteBuffer::CopyOnWriteBuffer(size_t size)
Danil Chapovalov8df643b2021-01-22 16:11:10 +010035 : buffer_(size > 0 ? new RefCountedBuffer(size) : nullptr),
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020036 offset_(0),
37 size_(size) {
jbauch13041cf2016-02-25 06:16:52 -080038 RTC_DCHECK(IsConsistent());
39}
40
41CopyOnWriteBuffer::CopyOnWriteBuffer(size_t size, size_t capacity)
Danil Chapovalov8df643b2021-01-22 16:11:10 +010042 : buffer_(size > 0 || capacity > 0 ? new RefCountedBuffer(size, capacity)
43 : nullptr),
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020044 offset_(0),
45 size_(size) {
jbauch13041cf2016-02-25 06:16:52 -080046 RTC_DCHECK(IsConsistent());
47}
48
49CopyOnWriteBuffer::~CopyOnWriteBuffer() = default;
50
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020051bool CopyOnWriteBuffer::operator==(const CopyOnWriteBuffer& buf) const {
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020052 // Must either be the same view of the same buffer or have the same contents.
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020053 RTC_DCHECK(IsConsistent());
54 RTC_DCHECK(buf.IsConsistent());
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020055 return size_ == buf.size_ &&
56 (cdata() == buf.cdata() || memcmp(cdata(), buf.cdata(), size_) == 0);
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020057}
58
59void CopyOnWriteBuffer::SetSize(size_t size) {
60 RTC_DCHECK(IsConsistent());
61 if (!buffer_) {
62 if (size > 0) {
Danil Chapovalov8df643b2021-01-22 16:11:10 +010063 buffer_ = new RefCountedBuffer(size);
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020064 offset_ = 0;
65 size_ = size;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020066 }
67 RTC_DCHECK(IsConsistent());
68 return;
69 }
70
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020071 if (size <= size_) {
72 size_ = size;
73 return;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020074 }
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020075
76 UnshareAndEnsureCapacity(std::max(capacity(), size));
77 buffer_->SetSize(size + offset_);
78 size_ = size;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020079 RTC_DCHECK(IsConsistent());
80}
81
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020082void CopyOnWriteBuffer::EnsureCapacity(size_t new_capacity) {
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020083 RTC_DCHECK(IsConsistent());
84 if (!buffer_) {
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020085 if (new_capacity > 0) {
Danil Chapovalov8df643b2021-01-22 16:11:10 +010086 buffer_ = new RefCountedBuffer(0, new_capacity);
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020087 offset_ = 0;
88 size_ = 0;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020089 }
90 RTC_DCHECK(IsConsistent());
91 return;
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020092 } else if (new_capacity <= capacity()) {
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020093 return;
94 }
95
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020096 UnshareAndEnsureCapacity(new_capacity);
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020097 RTC_DCHECK(IsConsistent());
98}
99
100void CopyOnWriteBuffer::Clear() {
101 if (!buffer_)
102 return;
103
104 if (buffer_->HasOneRef()) {
105 buffer_->Clear();
106 } else {
Danil Chapovalov8df643b2021-01-22 16:11:10 +0100107 buffer_ = new RefCountedBuffer(0, capacity());
Danil Chapovalov3626d7e2016-09-14 17:14:30 +0200108 }
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +0200109 offset_ = 0;
110 size_ = 0;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +0200111 RTC_DCHECK(IsConsistent());
112}
113
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +0200114void CopyOnWriteBuffer::UnshareAndEnsureCapacity(size_t new_capacity) {
115 if (buffer_->HasOneRef() && new_capacity <= capacity()) {
Danil Chapovalov3626d7e2016-09-14 17:14:30 +0200116 return;
117 }
118
Danil Chapovalov8df643b2021-01-22 16:11:10 +0100119 buffer_ =
120 new RefCountedBuffer(buffer_->data() + offset_, size_, new_capacity);
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +0200121 offset_ = 0;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +0200122 RTC_DCHECK(IsConsistent());
123}
124
jbauch13041cf2016-02-25 06:16:52 -0800125} // namespace rtc