root/trunk/FFissionCodec/ringbuffer.cpp

Revision 420, 5.0 kB (checked in by dconrad, 2 years ago)

Fix stupid mistake in buffer reallocation

Line 
1 /*
2  *  ringbuffer.cpp
3  *
4  *    RingBuffer class implementation. Simple ring buffer functionality
5  *    expressed as a c++ class.
6  *
7  *
8  *  Copyright (c) 2005,2007  Arek Korbik
9  *
10  *  This file is part of XiphQT, the Xiph QuickTime Components.
11  *
12  *  XiphQT is free software; you can redistribute it and/or
13  *  modify it under the terms of the GNU Lesser General Public
14  *  License as published by the Free Software Foundation; either
15  *  version 2.1 of the License, or (at your option) any later version.
16  *
17  *  XiphQT is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  *  Lesser General Public License for more details.
21  *
22  *  You should have received a copy of the GNU Lesser General Public
23  *  License along with XiphQT; if not, write to the Free Software
24  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
25  *
26  *
27  *  Last modified: $Id: ringbuffer.cpp 12356 2007-01-20 00:18:04Z arek $
28  *
29  */
30
31 #include "ringbuffer.h"
32
33 RingBuffer::RingBuffer() :
34 mBuffer(NULL),
35 mBStart(0),
36 mBEnd(0),
37 mBSize(0),
38 mNeedsWrapping(false)
39 {
40 }
41
42 RingBuffer::~RingBuffer() {
43     delete[] mBuffer;
44 }
45
46
47 void RingBuffer::Initialize(UInt32 inBufferByteSize) {
48     mBSize = inBufferByteSize;
49
50     if (mBuffer)
51         delete[] mBuffer;
52
53     mBuffer = new Byte[mBSize * 2];
54
55     mBStart = 0;
56     mBEnd = 0;
57     mNeedsWrapping = false;
58         packetSizes.clear();
59 }
60
61 void RingBuffer::Uninitialize() {
62     mBSize = 0;
63
64     if (mBuffer) {
65         delete[] mBuffer;
66         mBuffer = NULL;
67     }
68
69     Reset();
70
71 }
72
73 void RingBuffer::Reset() {
74     mBStart = 0;
75     mBEnd = 0;
76     mNeedsWrapping = false;
77         packetSizes.clear();
78 }
79
80 UInt32 RingBuffer::Reallocate(UInt32 inBufferByteSize) {
81     Byte *bptr = NULL;
82     UInt32 data_size = 0;
83
84     // can't decrease the size at the moment
85     if (inBufferByteSize > mBSize) {
86         bptr = new Byte[inBufferByteSize * 2];
87         data_size = GetDataAvailable();
88         if (mNeedsWrapping) {
89             UInt32 headBytes = mBSize - mBStart;
90             BlockMoveData(mBuffer + mBStart, bptr, headBytes);
91             BlockMoveData(mBuffer, bptr + headBytes, mBEnd);
92             mNeedsWrapping = false;
93         } else {
94             BlockMoveData(mBuffer + mBStart, bptr, data_size);
95         }
96         mBEnd = data_size;
97         mBStart = 0;
98
99         delete[] mBuffer;
100         mBuffer = bptr;
101         mBSize = inBufferByteSize;
102     }
103
104     return mBSize;
105 }
106
107 UInt32 RingBuffer::GetBufferByteSize() const {
108     return mBSize;
109 }
110
111 UInt32 RingBuffer::GetDataAvailable() const {
112     UInt32 ret = 0;
113
114     if (mBStart < mBEnd)
115         ret = mBEnd - mBStart;
116     else if (mBEnd < mBStart)
117         ret = mBSize + mBEnd - mBStart;
118
119     return ret;
120 }
121
122 UInt32 RingBuffer::GetSpaceAvailable() const {
123     UInt32 ret = mBSize;
124
125     if (mBStart > mBEnd)
126         ret =  mBStart - mBEnd;
127     else if (mBEnd > mBStart)
128         ret = mBSize - mBEnd + mBStart;
129
130     return ret;
131
132 }
133
134
135 void RingBuffer::In(const void* data, UInt32& ioBytes) {
136         UInt32 copiedBytes = ioBytes;
137
138         UInt32 sizeNeeded = GetDataAvailable() + ioBytes;
139         if (sizeNeeded > GetBufferByteSize())
140                 if (Reallocate(sizeNeeded) < sizeNeeded)
141                         copiedBytes = GetSpaceAvailable();
142
143     if (mBEnd + copiedBytes <= mBSize) {
144         BlockMoveData(data, mBuffer + mBEnd, copiedBytes);
145         mBEnd += copiedBytes;
146         if (mBEnd < mBStart)
147             mNeedsWrapping = true;
148     } else {
149         UInt32 wrappedBytes = mBSize - mBEnd;
150         const Byte* dataSplit = static_cast<const Byte*>(data) + wrappedBytes;
151         BlockMoveData(data, mBuffer + mBEnd, wrappedBytes);
152
153         mBEnd = copiedBytes - wrappedBytes;
154         BlockMoveData(dataSplit, mBuffer, mBEnd);
155
156         mNeedsWrapping = true;
157     }
158
159     ioBytes -= copiedBytes;
160         packetSizes.push_back(copiedBytes);
161 }
162
163 void RingBuffer::Zap(UInt32 inBytes) {
164         UInt32 packetsZapped = 0;
165         while (packetsZapped < inBytes) {
166                 if (packetsZapped + packetSizes.front() > inBytes) {
167                         packetSizes.front() -= inBytes - packetsZapped;
168                         packetsZapped = inBytes;
169                 } else {
170                         packetsZapped += packetSizes.front();
171                         packetSizes.pop_front();
172                 }
173         }
174        
175     if (inBytes >= GetDataAvailable()) {
176         mBStart = 0;
177         mBEnd = 0;
178         mNeedsWrapping = false;
179     } else if (mBStart < mBEnd || mBStart + inBytes < mBSize) {
180         mBStart += inBytes;
181     } else {
182         mBStart += inBytes - mBSize;
183         mNeedsWrapping = false;
184     }
185 }
186
187 Byte* RingBuffer::GetData() {
188     if (GetDataAvailable() == 0)
189         return mBuffer;
190     else {
191         if (mNeedsWrapping) {
192             BlockMoveData(mBuffer, mBuffer + mBSize, mBEnd);
193             mNeedsWrapping = false;
194         }
195         return mBuffer + mBStart;
196     }
197 }
198
199 Byte* RingBuffer::GetDataEnd() {
200     UInt32 available = GetDataAvailable();
201     if (available == 0)
202         return mBuffer;
203     else {
204         if (mNeedsWrapping) {
205             BlockMoveData(mBuffer, mBuffer + mBSize, mBEnd);
206             mNeedsWrapping = false;
207         }
208         return mBuffer + mBStart + available;
209     }
210 }
Note: See TracBrowser for help on using the browser.