summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/RingBuffer.cpp
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2020-10-19 00:52:24 +0200
committermanuel <manuel@mausz.at>2020-10-19 00:52:24 +0200
commitbe933ef2241d79558f91796cc5b3a161f72ebf9c (patch)
treefe3ab2f130e20c99001f2d7a81d610c78c96a3f4 /xbmc/utils/RingBuffer.cpp
parent5f8335c1e49ce108ef3481863833c98efa00411b (diff)
downloadkodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.tar.gz
kodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.tar.bz2
kodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.zip
sync with upstream
Diffstat (limited to 'xbmc/utils/RingBuffer.cpp')
-rw-r--r--xbmc/utils/RingBuffer.cpp246
1 files changed, 246 insertions, 0 deletions
diff --git a/xbmc/utils/RingBuffer.cpp b/xbmc/utils/RingBuffer.cpp
new file mode 100644
index 0000000..f44ab57
--- /dev/null
+++ b/xbmc/utils/RingBuffer.cpp
@@ -0,0 +1,246 @@
1/*
2 * Copyright (C) 2010-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9#include "RingBuffer.h"
10
11#include "threads/SingleLock.h"
12
13#include <algorithm>
14#include <cstdlib>
15#include <cstring>
16
17/* Constructor */
18CRingBuffer::CRingBuffer()
19{
20 m_buffer = NULL;
21 m_size = 0;
22 m_readPtr = 0;
23 m_writePtr = 0;
24 m_fillCount = 0;
25}
26
27/* Destructor */
28CRingBuffer::~CRingBuffer()
29{
30 Destroy();
31}
32
33/* Create a ring buffer with the specified 'size' */
34bool CRingBuffer::Create(unsigned int size)
35{
36 CSingleLock lock(m_critSection);
37 m_buffer = (char*)malloc(size);
38 if (m_buffer != NULL)
39 {
40 m_size = size;
41 return true;
42 }
43 return false;
44}
45
46/* Free the ring buffer and set all values to NULL or 0 */
47void CRingBuffer::Destroy()
48{
49 CSingleLock lock(m_critSection);
50 if (m_buffer != NULL)
51 {
52 free(m_buffer);
53 m_buffer = NULL;
54 }
55 m_size = 0;
56 m_readPtr = 0;
57 m_writePtr = 0;
58 m_fillCount = 0;
59}
60
61/* Clear the ring buffer */
62void CRingBuffer::Clear()
63{
64 CSingleLock lock(m_critSection);
65 m_readPtr = 0;
66 m_writePtr = 0;
67 m_fillCount = 0;
68}
69
70/* Read in data from the ring buffer to the supplied buffer 'buf'. The amount
71 * read in is specified by 'size'.
72 */
73bool CRingBuffer::ReadData(char *buf, unsigned int size)
74{
75 CSingleLock lock(m_critSection);
76 if (size > m_fillCount)
77 {
78 return false;
79 }
80 if (size + m_readPtr > m_size)
81 {
82 unsigned int chunk = m_size - m_readPtr;
83 memcpy(buf, m_buffer + m_readPtr, chunk);
84 memcpy(buf + chunk, m_buffer, size - chunk);
85 m_readPtr = size - chunk;
86 }
87 else
88 {
89 memcpy(buf, m_buffer + m_readPtr, size);
90 m_readPtr += size;
91 }
92 if (m_readPtr == m_size)
93 m_readPtr = 0;
94 m_fillCount -= size;
95 return true;
96}
97
98/* Read in data from the ring buffer to another ring buffer object specified by
99 * 'rBuf'.
100 */
101bool CRingBuffer::ReadData(CRingBuffer &rBuf, unsigned int size)
102{
103 CSingleLock lock(m_critSection);
104 if (rBuf.getBuffer() == NULL)
105 rBuf.Create(size);
106
107 bool bOk = size <= rBuf.getMaxWriteSize() && size <= getMaxReadSize();
108 if (bOk)
109 {
110 unsigned int chunksize = std::min(size, m_size - m_readPtr);
111 bOk = rBuf.WriteData(&getBuffer()[m_readPtr], chunksize);
112 if (bOk && chunksize < size)
113 bOk = rBuf.WriteData(&getBuffer()[0], size - chunksize);
114 if (bOk)
115 SkipBytes(size);
116 }
117
118 return bOk;
119}
120
121/* Write data to ring buffer from buffer specified in 'buf'. Amount read in is
122 * specified by 'size'.
123 */
124bool CRingBuffer::WriteData(const char *buf, unsigned int size)
125{
126 CSingleLock lock(m_critSection);
127 if (size > m_size - m_fillCount)
128 {
129 return false;
130 }
131 if (size + m_writePtr > m_size)
132 {
133 unsigned int chunk = m_size - m_writePtr;
134 memcpy(m_buffer + m_writePtr, buf, chunk);
135 memcpy(m_buffer, buf + chunk, size - chunk);
136 m_writePtr = size - chunk;
137 }
138 else
139 {
140 memcpy(m_buffer + m_writePtr, buf, size);
141 m_writePtr += size;
142 }
143 if (m_writePtr == m_size)
144 m_writePtr = 0;
145 m_fillCount += size;
146 return true;
147}
148
149/* Write data to ring buffer from another ring buffer object specified by
150 * 'rBuf'.
151 */
152bool CRingBuffer::WriteData(CRingBuffer &rBuf, unsigned int size)
153{
154 CSingleLock lock(m_critSection);
155 if (m_buffer == NULL)
156 Create(size);
157
158 bool bOk = size <= rBuf.getMaxReadSize() && size <= getMaxWriteSize();
159 if (bOk)
160 {
161 unsigned int readpos = rBuf.getReadPtr();
162 unsigned int chunksize = std::min(size, rBuf.getSize() - readpos);
163 bOk = WriteData(&rBuf.getBuffer()[readpos], chunksize);
164 if (bOk && chunksize < size)
165 bOk = WriteData(&rBuf.getBuffer()[0], size - chunksize);
166 }
167
168 return bOk;
169}
170
171/* Skip bytes in buffer to be read */
172bool CRingBuffer::SkipBytes(int skipSize)
173{
174 CSingleLock lock(m_critSection);
175 if (skipSize < 0)
176 {
177 return false; // skipping backwards is not supported
178 }
179
180 unsigned int size = skipSize;
181 if (size > m_fillCount)
182 {
183 return false;
184 }
185 if (size + m_readPtr > m_size)
186 {
187 unsigned int chunk = m_size - m_readPtr;
188 m_readPtr = size - chunk;
189 }
190 else
191 {
192 m_readPtr += size;
193 }
194 if (m_readPtr == m_size)
195 m_readPtr = 0;
196 m_fillCount -= size;
197 return true;
198}
199
200/* Append all content from ring buffer 'rBuf' to this ring buffer */
201bool CRingBuffer::Append(CRingBuffer &rBuf)
202{
203 return WriteData(rBuf, rBuf.getMaxReadSize());
204}
205
206/* Copy all content from ring buffer 'rBuf' to this ring buffer overwriting any existing data */
207bool CRingBuffer::Copy(CRingBuffer &rBuf)
208{
209 Clear();
210 return Append(rBuf);
211}
212
213/* Our various 'get' methods */
214char *CRingBuffer::getBuffer()
215{
216 return m_buffer;
217}
218
219unsigned int CRingBuffer::getSize()
220{
221 CSingleLock lock(m_critSection);
222 return m_size;
223}
224
225unsigned int CRingBuffer::getReadPtr() const
226{
227 return m_readPtr;
228}
229
230unsigned int CRingBuffer::getWritePtr()
231{
232 CSingleLock lock(m_critSection);
233 return m_writePtr;
234}
235
236unsigned int CRingBuffer::getMaxReadSize()
237{
238 CSingleLock lock(m_critSection);
239 return m_fillCount;
240}
241
242unsigned int CRingBuffer::getMaxWriteSize()
243{
244 CSingleLock lock(m_critSection);
245 return m_size - m_fillCount;
246}