chunkres.cpp
来自「symbian 下的helix player源代码」· C++ 代码 · 共 2,018 行 · 第 1/4 页
CPP
2,018 行
// CChunkyRes::~CChunkyRes()
//
// Purpose:
//
// Destructor for a chunky resource.
//
// Parameters:
//
// None.
//
// Return:
//
// N/A
//
CChunkyRes::~CChunkyRes()
{
// If we are getting rid of the resource, then
// we should discard all of the chunks...
for (int ndx = 0; ndx < m_Chunks.GetSize(); ndx++)
{
CChunkyResChunk* pChunk = (CChunkyResChunk*)m_Chunks[ndx];
if (pChunk)
{
delete pChunk;
}
}
HX_RESULT theErr = DiscardDiskData();
HX_ASSERT(theErr == HXR_OK);
if(m_ChunksMemoryMRU)
{
HX_ASSERT(m_ChunksMemoryMRU->GetCount() == 0);
delete m_ChunksMemoryMRU;
m_ChunksMemoryMRU = NULL;
}
if(m_ChunksDiskMRU)
{
HX_ASSERT(m_ChunksDiskMRU->GetCount() == 0);
delete m_ChunksDiskMRU;
m_ChunksDiskMRU = NULL;
}
HX_DELETE(m_pMutex);
}
/////////////////////////////////////////////////////////////////////////////
//
// Method:
//
// CChunkyResChunk::MakeSureChunkIsInMemory()
//
// Purpose:
//
// Get a portion of the data for a chunk.
//
// Parameters:
//
// ULONG32 offset
// char* buf
// ULONG32 count
// ULONG32* actual
//
// Return:
//
// HX_RESULT
// Possible errors include: TBD.
//
HX_RESULT CChunkyResChunk::MakeSureChunkIsInMemory()
{
HX_RESULT theErr = HXR_OK;
// If we don't have a chunk pointer, then we aren't in
// memory...
if (!m_pChunkData)
{
// Find ourselves in the MRU list for Disk chunks...
LISTPOSITION pos = m_pChunkRes->m_ChunksDiskMRU->Find(this);
// If were found in the disk MRU list, then we have
// some work to do...
if (pos)
{
// First, remove ourselves from the disk list...
m_pChunkRes->m_ChunksDiskMRU->RemoveAt(pos);
// Load from disk...
theErr = LoadFromDisk();
if (theErr != HXR_OK)
{
goto exit;
}
}
else
{
#ifdef _DEBUG
{
// We shouldn't find ourselves in the MRU list
// for memory chunks... but we want to check!
LISTPOSITION pos = m_pChunkRes->m_ChunksMemoryMRU->Find(this);
// We shouldn't be in this list!!!!
HX_ASSERT(pos == NULL);
}
#endif // end _DEBUG section
m_pChunkData = new UCHAR[m_pChunkRes->m_ChunkSize];
if (!m_pChunkData) theErr = HXR_OUTOFMEMORY;
if (theErr != HXR_OK)
{
goto exit;
}
HX_ASSERT(GetValidLength() == 0);
}
// Add to the front of the Memory list...
m_pChunkRes->m_ChunksMemoryMRU->AddHead(this);
m_pChunkRes->m_CurMemUsage += GetSize();
// Make sure we don't have to much info in memory...
if (!m_bDisableDiskIO)
{
m_pChunkRes->TrimDownMemoryMRU();
HX_ASSERT(m_pChunkData);
}
}
// If we are already in memory, then make sure we are at the
// top of the Memory MRU list!!!
else
{
// We should find ourselves in the MRU list
// for memory chunks... but we want to check!
LISTPOSITION pos = m_pChunkRes->m_ChunksMemoryMRU->Find(this);
// XXXNH: If we aren't in this list it means we were paged out,
// so we only need to put ourselves at the top of the MRU list
if (pos)
{
// First, remove ourselves from wherever we are in the
// Memory MRU list...
m_pChunkRes->m_ChunksMemoryMRU->RemoveAt(pos);
}
// And add ourselves to the top of the list!
m_pChunkRes->m_ChunksMemoryMRU->AddHead(this);
}
exit:
return theErr;
}
/////////////////////////////////////////////////////////////////////////////
//
// Method:
//
// CChunkyResChunk::GetValidLength()
//
// Purpose:
//
// Determines how much of a chunk is valid
//
// Parameters:
//
// ULONG32 offset
//
// Return:
//
// HX_RESULT
// Possible errors include: TBD.
//
ULONG32 CChunkyResChunk::GetValidLength(ULONG32 offset /* = 0 */) const
{
HX_ASSERT(offset < GetSize());
ULONG32 ulValidLength = 0;
LISTPOSITION rangePos = m_ValidRanges.GetHeadPosition();
if (rangePos)
{
do
{
ValidRange* pRange = (ValidRange*)m_ValidRanges.GetNext(rangePos);
HX_ASSERT(pRange);
// see if the offset points into this particular range
if (offset >= pRange->offset
&& offset <= pRange->offset + pRange->length)
{
ulValidLength = pRange->offset + pRange->length - offset;
}
}
while (rangePos);
}
return ulValidLength;
}
/////////////////////////////////////////////////////////////////////////////
//
// Method:
//
// CChunkyResChunk::GetData()
//
// Purpose:
//
// Get a portion of the data for a chunk.
//
// Parameters:
//
// ULONG32 offset
// char* buf
// ULONG32 count
// ULONG32* actual
//
// Return:
//
// HX_RESULT
// Possible errors include: TBD.
//
HX_RESULT CChunkyResChunk::GetData(ULONG32 offset, char* buf, ULONG32 count, ULONG32* actual)
{
HX_RESULT theErr;
if(!count)
{
*actual = count;
return HXR_OK;
}
// We should have a non-zero valid size
if (!GetValidLength(offset))
{
// This chunk must have been discarded
theErr = HXR_CHUNK_MISSING;
goto exit;
}
// Make sure this chunk is in memory!
theErr = MakeSureChunkIsInMemory();
if (theErr != HXR_OK)
{
goto exit;
}
// You can't read more than there is room in this chunk.
// CChunkyRes should prevent this case...
HX_ASSERT(offset+count <= GetSize());
// The call to MakeSureChunkIsInMemory() should have handled this!
HX_ASSERT_VALID_PTR(m_pChunkData);
*actual = min(count,GetValidLength(offset));
HX_ASSERT(*actual < UINT_MAX);
memcpy(buf,m_pChunkData+offset,(int)(*actual)); /* Flawfinder: ignore */
exit:
return theErr;
}
HX_RESULT
CChunkyResChunk::GetContiguousDataPointer(ULONG32 offset, char*& buf, ULONG32 count)
{
HX_RESULT theErr = HXR_OK;
if(!count)
{
theErr = HXR_FAIL;
goto exit;
}
// First, make sure this chunk is in memory!
theErr = MakeSureChunkIsInMemory();
if (theErr != HXR_OK)
{
goto exit;
}
// You can't write more than there is room in this chunk.
// CChunkyRes should prevent this case...
HX_ASSERT(offset+count <= GetSize());
// Currently, you must write to chunks in order from the
// start of the chunk first. Random access may come in the
// future...
HX_ASSERT(GetValidLength(offset) > 0); // needed still at all?
// The call to MakeSureChunkIsInMemory() should have handled this!
HX_ASSERT_VALID_PTR(m_pChunkData);
AddValidRange(offset, count);
HX_ASSERT(count < UINT_MAX);
buf = (char*) (m_pChunkData+offset);
m_bModified = TRUE;
exit:
return theErr;
}
/////////////////////////////////////////////////////////////////////////////
//
// Method:
//
// CChunkyResChunk::AddValidRange()
//
// Purpose:
//
// Mark a part of this CChunkyResChunk as valid
// Called from SetData.
//
// Parameters:
//
// ULONG32 offset
// ULONG32 length
// BOOL bValid
//
// Return:
//
// HX_RESULT
// Possible errors include: TBD.
//
HX_RESULT CChunkyResChunk::AddValidRange(ULONG32 offset, ULONG32 length, BOOL bValid /* = TRUE */)
{
HX_RESULT theErr = HXR_OK;
int nCount = m_ValidRanges.GetCount();
LISTPOSITION pos = m_ValidRanges.GetHeadPosition();
if (bValid)
{
// I don't think we need to ensure that the chunk is in
// memory, although it always probably will be if this is
// called from SetData.
// Ensure that it's saying that a legal range is valid.
HX_ASSERT(offset+length <= GetSize());
// Create a new range element.
ValidRange* pNewRange = new ValidRange;
pNewRange->offset = offset;
pNewRange->length = length;
// Iterate through the valid ranges to ensure that
// none of them overlap the range we're adding now.
for (int i=0; i<nCount; i++)
{
ValidRange* pRange = (ValidRange*)m_ValidRanges.GetAt(pos);
BOOL bNeedToMerge = FALSE;
// See if this range element overlaps the front end of the
// new range element.
if (pRange->offset <= pNewRange->offset
&& pRange->offset + pRange->length >= pNewRange->offset)
{
bNeedToMerge = TRUE;
}
// see if this range element overlaps the back end of the
// new range element.
if (pRange->offset <= pNewRange->offset + pNewRange->length
&& pRange->offset + pRange->length >= pNewRange->offset + pNewRange->length)
{
bNeedToMerge = TRUE;
}
// if an overlap happened, make the new range element hold
// the union of both ranges.
if (bNeedToMerge)
{
ULONG32 ulStartOfRange = min(pNewRange->offset, pRange->offset);
ULONG32 ulEndOfRange = max(pNewRange->offset+pNewRange->length,
pRange->offset+pRange->length);
HX_ASSERT(ulEndOfRange >= ulStartOfRange);
pNewRange->offset = ulStartOfRange;
pNewRange->length = ulEndOfRange-ulStartOfRange;
// delete the one we overlap with since we've ensured
// that pNewRange's range covers both.
pos = m_ValidRanges.RemoveAt(pos);
delete pRange;
}
else
m_ValidRanges.GetAtNext(pos);
}
// Now that we're sure that nobody overlaps us, we can
// add this range.
m_ValidRanges.AddTail((void*)pNewRange);
}
else
{
// bValid is false, so we're INVALIDATING a range.
// iterate through the list of valid ranges, and for each of them
// that overlaps the incoming range, either trim it appropriately
// or delete it entirely.
for (int i=0; i<nCount; i++)
{
ValidRange* pRange = (ValidRange*)m_ValidRanges.GetAt(pos);
HX_ASSERT(pRange);
// see if it's totally covered by the incoming range
if (offset <= pRange->offset && offset+length >= pRange->offset + pRange->length)
{
pos = m_ValidRanges.RemoveAt(pos);
delete pRange;
}
else
{
// see if it needs to be trimmed
ULONG32 ulCurrentRangeEnd = pRange->offset + pRange->length;
ULONG32 ulRangeEnd = offset + length;
BOOL bNeedToTrimOffBackEnd = pRange->offset < offset && ulCurrentRangeEnd >= offset;
BOOL bNeedToTrimOffFrontEnd = pRange->offset < ulRangeEnd
&& ulCurrentRangeEnd > ulRangeEnd;
if (bNeedToTrimOffBackEnd)
{
pRange->length = offset - pRange->offset;
}
if (bNeedToTrimOffFrontEnd)
{
// if we've also trimmed off the back end
// then we need to create a new range element
// to hold this sans-front-end element.
if (bNeedToTrimOffBackEnd)
{
pRange = new ValidRange;
m_ValidRanges.AddHead(pRange);
}
pRange->offset = ulRangeEnd;
pRange->length = ulCurrentRangeEnd - pRange->offset;
}
m_ValidRanges.GetAtNext(pos);
}
}
}
return theErr;
}
/////////////////////////////////////////////////////////////////////////////
//
// Method:
//
// CChunkyResChunk::SetData()
//
// Purpose:
//
// Set a portion of the data for a chunk.
//
// Parameters:
//
// ULONG32 offset
// const char* buf
// ULONG32 count
//
// Return:
//
// HX_RESULT
// Possible errors include: TBD.
//
HX_RESULT CChunkyResChunk::SetData(ULONG32 offset, const char* buf, ULONG32 count)
{
// First, make sure this chunk is in memory!
HX_RESULT theErr = MakeSureChunkIsInMemory();
if (theErr != HXR_OK)
{
goto exit;
}
// You can't write more than there is room in this chunk.
// CChunkyRes should prevent this case...
HX_ASSERT(offset+count <= GetSize());
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?