xref: /haiku/src/apps/cortex/addons/common/RawBuffer.cpp (revision 19ae20e67e91fc09cc9fc5c0e60e21e24e7a53eb)
1 /*
2  * Copyright (c) 1999-2000, Eric Moon.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions, and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions, and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 
32 // RawBuffer.cpp
33 // e.moon 31mar99
34 
35 #include "RawBuffer.h"
36 
37 #include <RealtimeAlloc.h>
38 #include <Debug.h>
39 #include <cstring>
40 
41 // -------------------------------------------------------- //
42 // ctor/dtor/accessors
43 // -------------------------------------------------------- //
44 
45 // allocate buffer (if frames > 0)
RawBuffer(uint32 frameSize,uint32 frames,bool bCircular,rtm_pool * pFromPool)46 RawBuffer::RawBuffer(
47 	uint32 frameSize,
48 	uint32 frames,
49 	bool bCircular,
50 	rtm_pool* pFromPool) :
51 
52 	m_pData(0),
53 	m_pPool(pFromPool),
54 	m_frameSize(frameSize),
55 	m_frames(frames),
56 	m_allocatedSize(0),
57 	m_bCircular(bCircular),
58 	m_bOwnData(true)
59 {
60 
61 	if(m_frames)
62 		resize(m_frames);
63 }
64 
65 // point to given data (does NOT take responsibility for
66 // deleting it; use adopt() for that.)
RawBuffer(void * pData,uint32 frameSize,uint32 frames,bool bCircular,rtm_pool * pFromPool)67 RawBuffer::RawBuffer(
68 	void* pData,
69 	uint32 frameSize,
70 	uint32 frames,
71 	bool bCircular,
72 	rtm_pool* pFromPool) :
73 
74 	m_pData(pData),
75 	m_pPool(pFromPool),
76 	m_frameSize(frameSize),
77 	m_frames(frames),
78 	m_allocatedSize(0),
79 	m_bCircular(bCircular),
80 	m_bOwnData(false)
81 {}
82 
RawBuffer(const RawBuffer & clone)83 RawBuffer::RawBuffer(const RawBuffer& clone) {
84 	operator=(clone);
85 }
86 
87 // generate a reference to the buffer
operator =(const RawBuffer & clone)88 RawBuffer& RawBuffer::operator=(const RawBuffer& clone) {
89 	m_pData = clone.m_pData;
90 	m_allocatedSize = clone.m_allocatedSize;
91 	m_frameSize = clone.m_frameSize;
92 	m_frames = clone.m_frames;
93 	m_bCircular = clone.m_bCircular;
94 	m_pPool = clone.m_pPool;
95 	m_bOwnData = false;
96 
97 	return *this;
98 }
99 
100 // deallocate if I own the data
~RawBuffer()101 RawBuffer::~RawBuffer() {
102 	free();
103 }
104 
data() const105 char* RawBuffer::data() const { return (char*)m_pData; }
106 // returns pointer to given frame
frame(uint32 frame) const107 char* RawBuffer::frame(uint32 frame) const {
108 	return data() + (frame * frameSize());
109 }
frameSize() const110 uint32 RawBuffer::frameSize() const { return m_frameSize; }
frames() const111 uint32 RawBuffer::frames() const { return m_frames; }
size() const112 uint32 RawBuffer::size() const { return m_frames * m_frameSize; }
113 
isCircular() const114 bool RawBuffer::isCircular() const { return m_bCircular; }
ownsBuffer() const115 bool RawBuffer::ownsBuffer() const { return m_bOwnData; }
116 
pool() const117 rtm_pool* RawBuffer::pool() const { return m_pPool; }
118 
119 // resize buffer, re-allocating if necessary to contain
120 // designated number of frames.
121 // Does not preserve buffer contents.
122 
resize(uint32 frames)123 void RawBuffer::resize(uint32 frames) {
124 	uint32 sizeRequired = frames * m_frameSize;
125 
126 	// already have enough storage?
127 	if(sizeRequired 	< m_allocatedSize &&
128 		m_bOwnData) {
129 		m_frames = frames;
130 		return;
131 	}
132 
133 	// free existing storage
134 	free();
135 
136 	// allocate
137 	m_pData = (m_pPool) ?
138 		rtm_alloc(m_pPool, sizeRequired) :
139 		new int8[sizeRequired];
140 
141 	m_bOwnData = true;
142 	m_allocatedSize = sizeRequired;
143 	m_frames = frames;
144 
145 }
146 
147 // take ownership of buffer from target
148 // (deletes current buffer data, if any owned)
149 
adopt(void * pData,uint32 frameSize,uint32 frames,bool bCircular,rtm_pool * pPool)150 void RawBuffer::adopt(
151 	void* pData,
152 	uint32 frameSize,
153 	uint32 frames,
154 	bool bCircular,
155 	rtm_pool* pPool) {
156 
157 	// clean up myself first
158 	free();
159 
160 	// reference
161 	operator=(RawBuffer(pData, frameSize, frames, bCircular, pPool));
162 
163 	// mark ownership
164 	m_bOwnData = true;
165 }
166 
167 // returns false if the target doesn't own the data, but references it
168 // one way or the other
169 
adopt(RawBuffer & target)170 bool RawBuffer::adopt(RawBuffer& target) {
171 
172 	// reference
173 	operator=(target);
174 
175 	// take ownership if possible
176 
177 	if(!target.m_bOwnData) {
178 		m_bOwnData = false;
179 		return false;
180 	}
181 
182 	target.m_bOwnData = false;
183 	m_bOwnData = true;
184 	return true;
185 }
186 
187 // adopt currently ref'd data (if any; returns false if no buffer data or
188 // already owned)
189 
adopt()190 bool RawBuffer::adopt() {
191 	if(!m_pData || m_bOwnData)
192 		return false;
193 
194 	m_bOwnData = true;
195 	return true;
196 }
197 
198 // -------------------------------------------------------- //
199 // operations
200 // -------------------------------------------------------- //
201 
202 // fill the buffer with zeroes
203 
zero()204 void RawBuffer::zero() {
205 	if(!m_pData || !m_frames)
206 		return;
207 
208 	memset(m_pData, 0, m_frames * m_frameSize);
209 }
210 
211 // raw copy to destination buffer, returning the number of
212 // frames written, and adjusting both offsets accordingly.
213 //
214 // no frames will be written if the buffers' frame sizes
215 // differ.
216 
rawCopyTo(RawBuffer & target,uint32 * pioFromFrame,uint32 * pioTargetFrame,uint32 frames) const217 uint32 RawBuffer::rawCopyTo(
218 	RawBuffer& target,
219 	uint32* pioFromFrame,
220 	uint32* pioTargetFrame,
221 	uint32 frames) const {
222 
223 	if(m_frameSize != target.m_frameSize)
224 		return 0;
225 
226 	ASSERT(m_pData);
227 	ASSERT(m_frames);
228 	ASSERT(target.m_pData);
229 
230 	// convert frame counts to byte offsets
231 	uint32 fromOffset = *pioFromFrame * m_frameSize;
232 	uint32 targetOffset = *pioTargetFrame * m_frameSize;
233 
234 	// figure buffer sizes in bytes
235 	uint32 size = m_frames * m_frameSize;
236 	uint32 targetSize = target.m_frames * target.m_frameSize;
237 
238 	// figure amount to write
239 	uint32 toCopy = frames * m_frameSize;
240 	if(target.m_bCircular) {
241 		if(toCopy > targetSize)
242 			toCopy = targetSize;
243 	} else {
244 		if(toCopy > (targetSize-targetOffset))
245 			toCopy = (targetSize-targetOffset);
246 	}
247 	uint32 remaining = toCopy;
248 
249 	// do it
250 	while(remaining) {
251 
252 		// figure a contiguous area to fill
253 		uint32 targetChunk = targetSize - targetOffset;
254 
255 		if(targetChunk > remaining)
256 			targetChunk = remaining;
257 
258 		// fill it (from one or more source areas)
259 		while(targetChunk > 0) {
260 
261 			// figure a contiguous source area
262 			uint32 sourceChunk = size - fromOffset;
263 			if(sourceChunk > targetChunk)
264 				sourceChunk = targetChunk;
265 
266 			// copy it
267 			memcpy(
268 				(int8*)target.m_pData + targetOffset,
269 				(int8*)m_pData + fromOffset,
270 				sourceChunk);
271 
272 			// advance offsets
273 			targetOffset += sourceChunk;
274 			if(targetOffset == targetSize)
275 				targetOffset = 0;
276 
277 			fromOffset += sourceChunk;
278 			if(fromOffset == size)
279 				fromOffset = 0;
280 
281 			// figure remaining portion of target area to fill
282 			targetChunk -= sourceChunk;
283 			remaining -= sourceChunk;
284 		}
285 	}
286 
287 	// write new offsets
288 	*pioFromFrame = fromOffset / m_frameSize;
289 	*pioTargetFrame = targetOffset / m_frameSize;
290 
291 	return toCopy;
292 }
293 
294 // more convenient version of above if you don't care
295 // how the offsets change.
296 
rawCopyTo(RawBuffer & target,uint32 fromOffset,uint32 targetOffset,uint32 frames) const297 uint32 RawBuffer::rawCopyTo(
298 	RawBuffer& target,
299 	uint32 fromOffset,
300 	uint32 targetOffset,
301 	uint32 frames) const {
302 
303 	return rawCopyTo(target, &fromOffset, &targetOffset, frames);
304 }
305 
306 // -------------------------------------------------------- //
307 // internal operations
308 // -------------------------------------------------------- //
309 
310 // free owned data, if any
311 // [16jun99] uses proper rtm_free() call if needed
free()312 void RawBuffer::free() {
313 	if(!(m_bOwnData && m_pData))
314 		return;
315 
316 	if(m_pPool)
317 		rtm_free(m_pData);
318 	else
319 		delete [] (int8 *)m_pData;
320 
321 	m_pData = 0;
322 }
323 
324 
325 // END -- RawBuffer.cpp --
326