blob: 850327b0887c657e2e853d1a56d83c303d688036 [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
Ali Tofighe00d7d02022-05-09 13:33:36 +020015#include "absl/strings/string_view.h"
16
jbauch13041cf2016-02-25 06:16:52 -080017namespace rtc {
18
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020019CopyOnWriteBuffer::CopyOnWriteBuffer() : offset_(0), size_(0) {
jbauch13041cf2016-02-25 06:16:52 -080020 RTC_DCHECK(IsConsistent());
21}
22
23CopyOnWriteBuffer::CopyOnWriteBuffer(const CopyOnWriteBuffer& buf)
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020024 : buffer_(buf.buffer_), offset_(buf.offset_), size_(buf.size_) {}
jbauch13041cf2016-02-25 06:16:52 -080025
danilchapd8a9c532016-07-30 12:39:26 -070026CopyOnWriteBuffer::CopyOnWriteBuffer(CopyOnWriteBuffer&& buf)
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020027 : buffer_(std::move(buf.buffer_)), offset_(buf.offset_), size_(buf.size_) {
28 buf.offset_ = 0;
29 buf.size_ = 0;
30 RTC_DCHECK(IsConsistent());
31}
jbauch13041cf2016-02-25 06:16:52 -080032
Ali Tofighe00d7d02022-05-09 13:33:36 +020033CopyOnWriteBuffer::CopyOnWriteBuffer(absl::string_view s)
Jeroen de Borst4f6d2332018-07-18 11:25:12 -070034 : CopyOnWriteBuffer(s.data(), s.length()) {}
35
jbauch13041cf2016-02-25 06:16:52 -080036CopyOnWriteBuffer::CopyOnWriteBuffer(size_t size)
Danil Chapovalov8df643b2021-01-22 16:11:10 +010037 : buffer_(size > 0 ? new RefCountedBuffer(size) : nullptr),
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020038 offset_(0),
39 size_(size) {
jbauch13041cf2016-02-25 06:16:52 -080040 RTC_DCHECK(IsConsistent());
41}
42
43CopyOnWriteBuffer::CopyOnWriteBuffer(size_t size, size_t capacity)
Danil Chapovalov8df643b2021-01-22 16:11:10 +010044 : buffer_(size > 0 || capacity > 0 ? new RefCountedBuffer(size, capacity)
45 : nullptr),
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020046 offset_(0),
47 size_(size) {
jbauch13041cf2016-02-25 06:16:52 -080048 RTC_DCHECK(IsConsistent());
49}
50
51CopyOnWriteBuffer::~CopyOnWriteBuffer() = default;
52
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020053bool CopyOnWriteBuffer::operator==(const CopyOnWriteBuffer& buf) const {
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020054 // Must either be the same view of the same buffer or have the same contents.
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020055 RTC_DCHECK(IsConsistent());
56 RTC_DCHECK(buf.IsConsistent());
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020057 return size_ == buf.size_ &&
58 (cdata() == buf.cdata() || memcmp(cdata(), buf.cdata(), size_) == 0);
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020059}
60
61void CopyOnWriteBuffer::SetSize(size_t size) {
62 RTC_DCHECK(IsConsistent());
63 if (!buffer_) {
64 if (size > 0) {
Danil Chapovalov8df643b2021-01-22 16:11:10 +010065 buffer_ = new RefCountedBuffer(size);
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020066 offset_ = 0;
67 size_ = size;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020068 }
69 RTC_DCHECK(IsConsistent());
70 return;
71 }
72
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020073 if (size <= size_) {
74 size_ = size;
75 return;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020076 }
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020077
78 UnshareAndEnsureCapacity(std::max(capacity(), size));
79 buffer_->SetSize(size + offset_);
80 size_ = size;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020081 RTC_DCHECK(IsConsistent());
82}
83
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020084void CopyOnWriteBuffer::EnsureCapacity(size_t new_capacity) {
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020085 RTC_DCHECK(IsConsistent());
86 if (!buffer_) {
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020087 if (new_capacity > 0) {
Danil Chapovalov8df643b2021-01-22 16:11:10 +010088 buffer_ = new RefCountedBuffer(0, new_capacity);
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020089 offset_ = 0;
90 size_ = 0;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020091 }
92 RTC_DCHECK(IsConsistent());
93 return;
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020094 } else if (new_capacity <= capacity()) {
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020095 return;
96 }
97
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020098 UnshareAndEnsureCapacity(new_capacity);
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020099 RTC_DCHECK(IsConsistent());
100}
101
102void CopyOnWriteBuffer::Clear() {
103 if (!buffer_)
104 return;
105
106 if (buffer_->HasOneRef()) {
107 buffer_->Clear();
108 } else {
Danil Chapovalov8df643b2021-01-22 16:11:10 +0100109 buffer_ = new RefCountedBuffer(0, capacity());
Danil Chapovalov3626d7e2016-09-14 17:14:30 +0200110 }
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +0200111 offset_ = 0;
112 size_ = 0;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +0200113 RTC_DCHECK(IsConsistent());
114}
115
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +0200116void CopyOnWriteBuffer::UnshareAndEnsureCapacity(size_t new_capacity) {
117 if (buffer_->HasOneRef() && new_capacity <= capacity()) {
Danil Chapovalov3626d7e2016-09-14 17:14:30 +0200118 return;
119 }
120
Danil Chapovalov8df643b2021-01-22 16:11:10 +0100121 buffer_ =
122 new RefCountedBuffer(buffer_->data() + offset_, size_, new_capacity);
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +0200123 offset_ = 0;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +0200124 RTC_DCHECK(IsConsistent());
125}
126
jbauch13041cf2016-02-25 06:16:52 -0800127} // namespace rtc