xref: /haiku/src/apps/cortex/addons/common/RawBuffer.cpp (revision 652df41ee51bcdae5d3d54563fe48baccf312a9d)
1 // RawBuffer.cpp
2 // e.moon 31mar99
3 
4 #include "RawBuffer.h"
5 
6 #include <RealtimeAlloc.h>
7 #include <Debug.h>
8 #include <cstring>
9 
10 // -------------------------------------------------------- //
11 // ctor/dtor/accessors
12 // -------------------------------------------------------- //
13 
14 // allocate buffer (if frames > 0)
15 RawBuffer::RawBuffer(
16 	uint32 frameSize,
17 	uint32 frames,
18 	bool bCircular,
19 	rtm_pool* pFromPool) :
20 
21 	m_pData(0),
22 	m_pPool(pFromPool),
23 	m_frameSize(frameSize),
24 	m_frames(frames),
25 	m_allocatedSize(0),
26 	m_bCircular(bCircular),
27 	m_bOwnData(true)
28 {
29 
30 	if(m_frames)
31 		resize(m_frames);
32 }
33 
34 // point to given data (does NOT take responsibility for
35 // deleting it; use adopt() for that.)
36 RawBuffer::RawBuffer(
37 	void* pData,
38 	uint32 frameSize,
39 	uint32 frames,
40 	bool bCircular,
41 	rtm_pool* pFromPool) :
42 
43 	m_pData(pData),
44 	m_pPool(pFromPool),
45 	m_frameSize(frameSize),
46 	m_frames(frames),
47 	m_allocatedSize(0),
48 	m_bCircular(bCircular),
49 	m_bOwnData(false)
50 {}
51 
52 RawBuffer::RawBuffer(const RawBuffer& clone) {
53 	operator=(clone);
54 }
55 
56 // generate a reference to the buffer
57 RawBuffer& RawBuffer::operator=(const RawBuffer& clone) {
58 	m_pData = clone.m_pData;
59 	m_allocatedSize = clone.m_allocatedSize;
60 	m_frameSize = clone.m_frameSize;
61 	m_frames = clone.m_frames;
62 	m_bCircular = clone.m_bCircular;
63 	m_pPool = clone.m_pPool;
64 	m_bOwnData = false;
65 
66 	return *this;
67 }
68 
69 // deallocate if I own the data
70 RawBuffer::~RawBuffer() {
71 	free();
72 }
73 
74 char* RawBuffer::data() const { return (char*)m_pData; }
75 // returns pointer to given frame
76 char* RawBuffer::frame(uint32 frame) const {
77 	return data() + (frame * frameSize());
78 }
79 uint32 RawBuffer::frameSize() const { return m_frameSize; }
80 uint32 RawBuffer::frames() const { return m_frames; }
81 uint32 RawBuffer::size() const { return m_frames * m_frameSize; }
82 
83 bool RawBuffer::isCircular() const { return m_bCircular; }
84 bool RawBuffer::ownsBuffer() const { return m_bOwnData; }
85 
86 rtm_pool* RawBuffer::pool() const { return m_pPool; }
87 
88 // resize buffer, re-allocating if necessary to contain
89 // designated number of frames.
90 // Does not preserve buffer contents.
91 
92 void RawBuffer::resize(uint32 frames) {
93 	uint32 sizeRequired = frames * m_frameSize;
94 
95 	// already have enough storage?
96 	if(sizeRequired 	< m_allocatedSize &&
97 		m_bOwnData) {
98 		m_frames = frames;
99 		return;
100 	}
101 
102 	// free existing storage
103 	free();
104 
105 	// allocate
106 	m_pData = (m_pPool) ?
107 		rtm_alloc(m_pPool, sizeRequired) :
108 		new int8[sizeRequired];
109 
110 	m_bOwnData = true;
111 	m_allocatedSize = sizeRequired;
112 	m_frames = frames;
113 
114 }
115 
116 // take ownership of buffer from target
117 // (deletes current buffer data, if any owned)
118 
119 void RawBuffer::adopt(
120 	void* pData,
121 	uint32 frameSize,
122 	uint32 frames,
123 	bool bCircular,
124 	rtm_pool* pPool) {
125 
126 	// clean up myself first
127 	free();
128 
129 	// reference
130 	operator=(RawBuffer(pData, frameSize, frames, bCircular, pPool));
131 
132 	// mark ownership
133 	m_bOwnData = true;
134 }
135 
136 // returns false if the target doesn't own the data, but references it
137 // one way or the other
138 
139 bool RawBuffer::adopt(RawBuffer& target) {
140 
141 	// reference
142 	operator=(target);
143 
144 	// take ownership if possible
145 
146 	if(!target.m_bOwnData) {
147 		m_bOwnData = false;
148 		return false;
149 	}
150 
151 	target.m_bOwnData = false;
152 	m_bOwnData = true;
153 	return true;
154 }
155 
156 // adopt currently ref'd data (if any; returns false if no buffer data or
157 // already owned)
158 
159 bool RawBuffer::adopt() {
160 	if(!m_pData || m_bOwnData)
161 		return false;
162 
163 	m_bOwnData = true;
164 	return true;
165 }
166 
167 // -------------------------------------------------------- //
168 // operations
169 // -------------------------------------------------------- //
170 
171 // fill the buffer with zeroes
172 
173 void RawBuffer::zero() {
174 	if(!m_pData || !m_frames)
175 		return;
176 
177 	memset(m_pData, 0, m_frames * m_frameSize);
178 }
179 
180 // raw copy to destination buffer, returning the number of
181 // frames written, and adjusting both offsets accordingly.
182 //
183 // no frames will be written if the buffers' frame sizes
184 // differ.
185 
186 uint32 RawBuffer::rawCopyTo(
187 	RawBuffer& target,
188 	uint32* pioFromFrame,
189 	uint32* pioTargetFrame,
190 	uint32 frames) const {
191 
192 	if(m_frameSize != target.m_frameSize)
193 		return 0;
194 
195 	ASSERT(m_pData);
196 	ASSERT(m_frames);
197 	ASSERT(target.m_pData);
198 
199 	// convert frame counts to byte offsets
200 	uint32 fromOffset = *pioFromFrame * m_frameSize;
201 	uint32 targetOffset = *pioTargetFrame * m_frameSize;
202 
203 	// figure buffer sizes in bytes
204 	uint32 size = m_frames * m_frameSize;
205 	uint32 targetSize = target.m_frames * target.m_frameSize;
206 
207 	// figure amount to write
208 	uint32 toCopy = frames * m_frameSize;
209 	if(target.m_bCircular) {
210 		if(toCopy > targetSize)
211 			toCopy = targetSize;
212 	} else {
213 		if(toCopy > (targetSize-targetOffset))
214 			toCopy = (targetSize-targetOffset);
215 	}
216 	uint32 remaining = toCopy;
217 
218 	// do it
219 	while(remaining) {
220 
221 		// figure a contiguous area to fill
222 		uint32 targetChunk = targetSize - targetOffset;
223 
224 		if(targetChunk > remaining)
225 			targetChunk = remaining;
226 
227 		// fill it (from one or more source areas)
228 		while(targetChunk > 0) {
229 
230 			// figure a contiguous source area
231 			uint32 sourceChunk = size - fromOffset;
232 			if(sourceChunk > targetChunk)
233 				sourceChunk = targetChunk;
234 
235 			// copy it
236 			memcpy(
237 				(int8*)target.m_pData + targetOffset,
238 				(int8*)m_pData + fromOffset,
239 				sourceChunk);
240 
241 			// advance offsets
242 			targetOffset += sourceChunk;
243 			if(targetOffset == targetSize)
244 				targetOffset = 0;
245 
246 			fromOffset += sourceChunk;
247 			if(fromOffset == size)
248 				fromOffset = 0;
249 
250 			// figure remaining portion of target area to fill
251 			targetChunk -= sourceChunk;
252 			remaining -= sourceChunk;
253 		}
254 	}
255 
256 	// write new offsets
257 	*pioFromFrame = fromOffset / m_frameSize;
258 	*pioTargetFrame = targetOffset / m_frameSize;
259 
260 	return toCopy;
261 }
262 
263 // more convenient version of above if you don't care
264 // how the offsets change.
265 
266 uint32 RawBuffer::rawCopyTo(
267 	RawBuffer& target,
268 	uint32 fromOffset,
269 	uint32 targetOffset,
270 	uint32 frames) const {
271 
272 	return rawCopyTo(target, &fromOffset, &targetOffset, frames);
273 }
274 
275 // -------------------------------------------------------- //
276 // internal operations
277 // -------------------------------------------------------- //
278 
279 // free owned data, if any
280 // [16jun99] uses proper rtm_free() call if needed
281 void RawBuffer::free() {
282 	if(!(m_bOwnData && m_pData))
283 		return;
284 
285 	if(m_pPool)
286 		rtm_free(m_pData);
287 	else
288 		delete [] (int8 *)m_pData;
289 
290 	m_pData = 0;
291 }
292 
293 
294 // END -- RawBuffer.cpp --
295