• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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