MPD: util/ForeignFifoBuffer.hxx Source File

MPD 0.20.15

ForeignFifoBuffer.hxx
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2003-2014 Max Kellermann <max.kellermann@gmail.com>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the
14 * distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
27 * OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #ifndef FOREIGN_FIFO_BUFFER_HXX
31 #define FOREIGN_FIFO_BUFFER_HXX
32
33 #include "WritableBuffer.hxx"
34
35 #include <utility>
36 #include <algorithm>
37
38 #include <cstddef>
39
40 #include <assert.h>
41
51 template<typename T>
52 class ForeignFifoBuffer {
53 public:
54 typedef size_t size_type;
55 typedef WritableBuffer<T> Range;
56 typedef typename Range::pointer_type pointer_type;
57 typedef typename Range::const_pointer_type const_pointer_type;
58
59 protected:
60 size_type head, tail, capacity;
61 T *data;
62
63 public:
64 explicit constexpr ForeignFifoBuffer(std::nullptr_t n)
65 :head(0), tail(0), capacity(0), data(n) {}
66
67 constexpr ForeignFifoBuffer(T *_data, size_type _capacity)
68 :head(0), tail(0), capacity(_capacity), data(_data) {}
69
70 ForeignFifoBuffer(ForeignFifoBuffer &&src)
71 :head(src.head), tail(src.tail),
72 capacity(src.capacity), data(src.data) {
73 src.SetNull();
74 }
75
76 ForeignFifoBuffer &operator=(ForeignFifoBuffer &&src) {
77 head = src.head;
78 tail = src.tail;
79 capacity = src.capacity;
80 data = src.data;
81 src.SetNull();
82 return *this;
83 }
84
85 void Swap(ForeignFifoBuffer<T> &other) {
86 std::swap(head, other.head);
87 std::swap(tail, other.tail);
88 std::swap(capacity, other.capacity);
89 std::swap(data, other.data);
90 }
91
92 constexpr bool IsNull() const {
93 return data == nullptr;
94 }
95
96 constexpr bool IsDefined() const {
97 return !IsNull();
98 }
99
100 T *GetBuffer() {
101 return data;
102 }
103
104 constexpr size_type GetCapacity() const {
105 return capacity;
106 }
107
108 void SetNull() {
109 head = tail = 0;
110 capacity = 0;
111 data = nullptr;
112 }
113
114 void SetBuffer(T *_data, size_type _capacity) {
115 assert(_data != nullptr);
116 assert(_capacity > 0);
117
118 head = tail = 0;
119 capacity = _capacity;
120 data = _data;
121 }
122
123 void MoveBuffer(T *new_data, size_type new_capacity) {
124 assert(new_capacity >= tail - head);
125
126 std::move(data + head, data + tail, new_data);
127 data = new_data;
128 capacity = new_capacity;
129 tail -= head;
130 head = 0;
131 }
132
133 void Clear() {
134 head = tail = 0;
135 }
136
137 constexpr bool IsEmpty() const {
138 return head == tail;
139 }
140
141 constexpr bool IsFull() const {
142 return head == 0 && tail == capacity;
143 }
144
149 Range Write() {
150 if (IsEmpty())
151 Clear();
152 else if (tail == capacity)
153 Shift();
154
155 return Range(data + tail, capacity - tail);
156 }
157
158 bool WantWrite(size_type n) {
159 if (tail + n <= capacity)
160 /* enough space after the tail */
161 return true;
162
163 const size_type in_use = tail - head;
164 const size_type required_capacity = in_use + n;
165 if (required_capacity > capacity)
166 return false;
167
168 Shift();
169 assert(tail + n <= capacity);
170 return true;
171 }
172
177 void Append(size_type n) {
178 assert(tail <= capacity);
179 assert(n <= capacity);
180 assert(tail + n <= capacity);
181
182 tail += n;
183 }
184
185 constexpr size_type GetAvailable() const {
186 return tail - head;
187 }
188
193 constexpr Range Read() const {
194 return Range(data + head, tail - head);
195 }
196
200 void Consume(size_type n) {
201 assert(tail <= capacity);
202 assert(head <= tail);
203 assert(n <= tail);
204 assert(head + n <= tail);
205
206 head += n;
207 }
208
209 size_type Read(pointer_type p, size_type n) {
210 auto range = Read();
211 if (n > range.size)
212 n = range.size;
213 std::copy_n(range.data, n, p);
214 Consume(n);
215 return n;
216 }
217
223 size_type MoveFrom(ForeignFifoBuffer<T> &src) {
224 auto r = src.Read();
225 auto w = Write();
226 size_t n = std::min(r.size, w.size);
227
228 std::move(r.data, r.data + n, w.data);
229 Append(n);
230 src.Consume(n);
231 return n;
232 }
233
234 protected:
235 void Shift() {
236 if (head == 0)
237 return;
238
239 assert(head <= capacity);
240 assert(tail <= capacity);
241 assert(tail >= head);
242
243 std::move(data + head, data + tail, data);
244
245 tail -= head;
246 head = 0;
247 }
248 };
249
250 #endif
ForeignFifoBuffer::Shift
void Shift()
Definition: ForeignFifoBuffer.hxx:235
ForeignFifoBuffer::Swap
void Swap(ForeignFifoBuffer< T > &other)
Definition: ForeignFifoBuffer.hxx:85
WritableBuffer.hxx
ForeignFifoBuffer::ForeignFifoBuffer
ForeignFifoBuffer(ForeignFifoBuffer &&src)
Definition: ForeignFifoBuffer.hxx:70
ForeignFifoBuffer::MoveBuffer
void MoveBuffer(T *new_data, size_type new_capacity)
Definition: ForeignFifoBuffer.hxx:123
ForeignFifoBuffer::Read
size_type Read(pointer_type p, size_type n)
Definition: ForeignFifoBuffer.hxx:209
ForeignFifoBuffer::ForeignFifoBuffer
constexpr ForeignFifoBuffer(std::nullptr_t n)
Definition: ForeignFifoBuffer.hxx:64
ForeignFifoBuffer::Read
constexpr Range Read() const
Return a buffer range which may be read.
Definition: ForeignFifoBuffer.hxx:193
ForeignFifoBuffer::Clear
void Clear()
Definition: ForeignFifoBuffer.hxx:133
ForeignFifoBuffer::pointer_type
Range::pointer_type pointer_type
Definition: ForeignFifoBuffer.hxx:56
WritableBuffer
A reference to a memory area that is writable.
Definition: Silence.hxx:27
ForeignFifoBuffer::IsNull
constexpr bool IsNull() const
Definition: ForeignFifoBuffer.hxx:92
ForeignFifoBuffer::capacity
size_type capacity
Definition: ForeignFifoBuffer.hxx:60
ForeignFifoBuffer::WantWrite
bool WantWrite(size_type n)
Definition: ForeignFifoBuffer.hxx:158
ForeignFifoBuffer::Consume
void Consume(size_type n)
Marks a chunk as consumed.
Definition: ForeignFifoBuffer.hxx:200
WritableBuffer::pointer_type
T * pointer_type
Definition: WritableBuffer.hxx:85
ForeignFifoBuffer::GetCapacity
constexpr size_type GetCapacity() const
Definition: ForeignFifoBuffer.hxx:104
ForeignFifoBuffer::operator=
ForeignFifoBuffer & operator=(ForeignFifoBuffer &&src)
Definition: ForeignFifoBuffer.hxx:76
ForeignFifoBuffer::const_pointer_type
Range::const_pointer_type const_pointer_type
Definition: ForeignFifoBuffer.hxx:57
ForeignFifoBuffer::Write
Range Write()
Prepares writing.
Definition: ForeignFifoBuffer.hxx:149
ForeignFifoBuffer::size_type
size_t size_type
Definition: ForeignFifoBuffer.hxx:54
ForeignFifoBuffer
A first-in-first-out buffer: you can append data at the end, and read data from the beginning...
Definition: ForeignFifoBuffer.hxx:52
ForeignFifoBuffer::SetBuffer
void SetBuffer(T *_data, size_type _capacity)
Definition: ForeignFifoBuffer.hxx:114
ForeignFifoBuffer::IsDefined
constexpr bool IsDefined() const
Definition: ForeignFifoBuffer.hxx:96
ForeignFifoBuffer::ForeignFifoBuffer
constexpr ForeignFifoBuffer(T *_data, size_type _capacity)
Definition: ForeignFifoBuffer.hxx:67
ForeignFifoBuffer::GetAvailable
constexpr size_type GetAvailable() const
Definition: ForeignFifoBuffer.hxx:185
ForeignFifoBuffer::data
T * data
Definition: ForeignFifoBuffer.hxx:61
ForeignFifoBuffer::Append
void Append(size_type n)
Expands the tail of the buffer, after data has been written to the buffer returned by write()...
Definition: ForeignFifoBuffer.hxx:177
ForeignFifoBuffer::head
size_type head
Definition: ForeignFifoBuffer.hxx:60
ForeignFifoBuffer::IsFull
constexpr bool IsFull() const
Definition: ForeignFifoBuffer.hxx:141
ForeignFifoBuffer::tail
size_type tail
Definition: ForeignFifoBuffer.hxx:60
ForeignFifoBuffer::IsEmpty
constexpr bool IsEmpty() const
Definition: ForeignFifoBuffer.hxx:137
ForeignFifoBuffer::MoveFrom
size_type MoveFrom(ForeignFifoBuffer< T > &src)
Move as much data as possible from the specified buffer.
Definition: ForeignFifoBuffer.hxx:223
WritableBuffer::const_pointer_type
const T * const_pointer_type
Definition: WritableBuffer.hxx:86
ForeignFifoBuffer::SetNull
void SetNull()
Definition: ForeignFifoBuffer.hxx:108
ForeignFifoBuffer::GetBuffer
T * GetBuffer()
Definition: ForeignFifoBuffer.hxx:100
ForeignFifoBuffer::Range
WritableBuffer< T > Range
Definition: ForeignFifoBuffer.hxx:55