blob: 73182a12b175419e2184c48b1a7312e1c3a16a0a [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)
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020035 : buffer_(size > 0 ? new RefCountedObject<Buffer>(size) : nullptr),
36 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)
42 : buffer_(size > 0 || capacity > 0
Yves Gerey665174f2018-06-19 15:03:05 +020043 ? new RefCountedObject<Buffer>(size, capacity)
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020044 : nullptr),
45 offset_(0),
46 size_(size) {
jbauch13041cf2016-02-25 06:16:52 -080047 RTC_DCHECK(IsConsistent());
48}
49
50CopyOnWriteBuffer::~CopyOnWriteBuffer() = default;
51
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020052bool CopyOnWriteBuffer::operator==(const CopyOnWriteBuffer& buf) const {
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020053 // Must either be the same view of the same buffer or have the same contents.
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020054 RTC_DCHECK(IsConsistent());
55 RTC_DCHECK(buf.IsConsistent());
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020056 return size_ == buf.size_ &&
57 (cdata() == buf.cdata() || memcmp(cdata(), buf.cdata(), size_) == 0);
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020058}
59
60void CopyOnWriteBuffer::SetSize(size_t size) {
61 RTC_DCHECK(IsConsistent());
62 if (!buffer_) {
63 if (size > 0) {
64 buffer_ = new RefCountedObject<Buffer>(size);
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020065 offset_ = 0;
66 size_ = size;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020067 }
68 RTC_DCHECK(IsConsistent());
69 return;
70 }
71
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020072 if (size <= size_) {
73 size_ = size;
74 return;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020075 }
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020076
77 UnshareAndEnsureCapacity(std::max(capacity(), size));
78 buffer_->SetSize(size + offset_);
79 size_ = size;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020080 RTC_DCHECK(IsConsistent());
81}
82
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020083void CopyOnWriteBuffer::EnsureCapacity(size_t new_capacity) {
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020084 RTC_DCHECK(IsConsistent());
85 if (!buffer_) {
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020086 if (new_capacity > 0) {
87 buffer_ = new RefCountedObject<Buffer>(0, new_capacity);
88 offset_ = 0;
89 size_ = 0;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020090 }
91 RTC_DCHECK(IsConsistent());
92 return;
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020093 } else if (new_capacity <= capacity()) {
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020094 return;
95 }
96
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +020097 UnshareAndEnsureCapacity(new_capacity);
Danil Chapovalov3626d7e2016-09-14 17:14:30 +020098 RTC_DCHECK(IsConsistent());
99}
100
101void CopyOnWriteBuffer::Clear() {
102 if (!buffer_)
103 return;
104
105 if (buffer_->HasOneRef()) {
106 buffer_->Clear();
107 } else {
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +0200108 buffer_ = new RefCountedObject<Buffer>(0, capacity());
Danil Chapovalov3626d7e2016-09-14 17:14:30 +0200109 }
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +0200110 offset_ = 0;
111 size_ = 0;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +0200112 RTC_DCHECK(IsConsistent());
113}
114
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +0200115void CopyOnWriteBuffer::UnshareAndEnsureCapacity(size_t new_capacity) {
116 if (buffer_->HasOneRef() && new_capacity <= capacity()) {
Danil Chapovalov3626d7e2016-09-14 17:14:30 +0200117 return;
118 }
119
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +0200120 buffer_ = new RefCountedObject<Buffer>(buffer_->data() + offset_, size_,
Yves Gerey665174f2018-06-19 15:03:05 +0200121 new_capacity);
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +0200122 offset_ = 0;
Danil Chapovalov3626d7e2016-09-14 17:14:30 +0200123 RTC_DCHECK(IsConsistent());
124}
125
jbauch13041cf2016-02-25 06:16:52 -0800126} // namespace rtc