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