* Copyright (c) 1999-2000, Eric Moon.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions, and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "RawBuffer.h"
#include <RealtimeAlloc.h>
#include <Debug.h>
#include <cstring>
RawBuffer::RawBuffer(
uint32 frameSize,
uint32 frames,
bool bCircular,
rtm_pool* pFromPool) :
m_pData(0),
m_pPool(pFromPool),
m_frameSize(frameSize),
m_frames(frames),
m_allocatedSize(0),
m_bCircular(bCircular),
m_bOwnData(true)
{
if(m_frames)
resize(m_frames);
}
RawBuffer::RawBuffer(
void* pData,
uint32 frameSize,
uint32 frames,
bool bCircular,
rtm_pool* pFromPool) :
m_pData(pData),
m_pPool(pFromPool),
m_frameSize(frameSize),
m_frames(frames),
m_allocatedSize(0),
m_bCircular(bCircular),
m_bOwnData(false)
{}
RawBuffer::RawBuffer(const RawBuffer& clone) {
operator=(clone);
}
RawBuffer& RawBuffer::operator=(const RawBuffer& clone) {
m_pData = clone.m_pData;
m_allocatedSize = clone.m_allocatedSize;
m_frameSize = clone.m_frameSize;
m_frames = clone.m_frames;
m_bCircular = clone.m_bCircular;
m_pPool = clone.m_pPool;
m_bOwnData = false;
return *this;
}
RawBuffer::~RawBuffer() {
free();
}
char* RawBuffer::data() const { return (char*)m_pData; }
char* RawBuffer::frame(uint32 frame) const {
return data() + (frame * frameSize());
}
uint32 RawBuffer::frameSize() const { return m_frameSize; }
uint32 RawBuffer::frames() const { return m_frames; }
uint32 RawBuffer::size() const { return m_frames * m_frameSize; }
bool RawBuffer::isCircular() const { return m_bCircular; }
bool RawBuffer::ownsBuffer() const { return m_bOwnData; }
rtm_pool* RawBuffer::pool() const { return m_pPool; }
void RawBuffer::resize(uint32 frames) {
uint32 sizeRequired = frames * m_frameSize;
if(sizeRequired < m_allocatedSize &&
m_bOwnData) {
m_frames = frames;
return;
}
free();
m_pData = (m_pPool) ?
rtm_alloc(m_pPool, sizeRequired) :
new int8[sizeRequired];
m_bOwnData = true;
m_allocatedSize = sizeRequired;
m_frames = frames;
}
void RawBuffer::adopt(
void* pData,
uint32 frameSize,
uint32 frames,
bool bCircular,
rtm_pool* pPool) {
free();
operator=(RawBuffer(pData, frameSize, frames, bCircular, pPool));
m_bOwnData = true;
}
bool RawBuffer::adopt(RawBuffer& target) {
operator=(target);
if(!target.m_bOwnData) {
m_bOwnData = false;
return false;
}
target.m_bOwnData = false;
m_bOwnData = true;
return true;
}
bool RawBuffer::adopt() {
if(!m_pData || m_bOwnData)
return false;
m_bOwnData = true;
return true;
}
void RawBuffer::zero() {
if(!m_pData || !m_frames)
return;
memset(m_pData, 0, m_frames * m_frameSize);
}
uint32 RawBuffer::rawCopyTo(
RawBuffer& target,
uint32* pioFromFrame,
uint32* pioTargetFrame,
uint32 frames) const {
if(m_frameSize != target.m_frameSize)
return 0;
ASSERT(m_pData);
ASSERT(m_frames);
ASSERT(target.m_pData);
uint32 fromOffset = *pioFromFrame * m_frameSize;
uint32 targetOffset = *pioTargetFrame * m_frameSize;
uint32 size = m_frames * m_frameSize;
uint32 targetSize = target.m_frames * target.m_frameSize;
uint32 toCopy = frames * m_frameSize;
if(target.m_bCircular) {
if(toCopy > targetSize)
toCopy = targetSize;
} else {
if(toCopy > (targetSize-targetOffset))
toCopy = (targetSize-targetOffset);
}
uint32 remaining = toCopy;
while(remaining) {
uint32 targetChunk = targetSize - targetOffset;
if(targetChunk > remaining)
targetChunk = remaining;
while(targetChunk > 0) {
uint32 sourceChunk = size - fromOffset;
if(sourceChunk > targetChunk)
sourceChunk = targetChunk;
memcpy(
(int8*)target.m_pData + targetOffset,
(int8*)m_pData + fromOffset,
sourceChunk);
targetOffset += sourceChunk;
if(targetOffset == targetSize)
targetOffset = 0;
fromOffset += sourceChunk;
if(fromOffset == size)
fromOffset = 0;
targetChunk -= sourceChunk;
remaining -= sourceChunk;
}
}
*pioFromFrame = fromOffset / m_frameSize;
*pioTargetFrame = targetOffset / m_frameSize;
return toCopy;
}
uint32 RawBuffer::rawCopyTo(
RawBuffer& target,
uint32 fromOffset,
uint32 targetOffset,
uint32 frames) const {
return rawCopyTo(target, &fromOffset, &targetOffset, frames);
}
void RawBuffer::free() {
if(!(m_bOwnData && m_pData))
return;
if(m_pPool)
rtm_free(m_pData);
else
delete [] (int8 *)m_pData;
m_pData = 0;
}