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