⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chunkres.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* ***** BEGIN LICENSE BLOCK ***** 
 * Version: RCSL 1.0/RPSL 1.0 
 *  
 * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
 *      
 * The contents of this file, and the files included with this file, are 
 * subject to the current version of the RealNetworks Public Source License 
 * Version 1.0 (the "RPSL") available at 
 * http://www.helixcommunity.org/content/rpsl unless you have licensed 
 * the file under the RealNetworks Community Source License Version 1.0 
 * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
 * in which case the RCSL will apply. You may also obtain the license terms 
 * directly from RealNetworks.  You may not use this file except in 
 * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
 * applicable to this file, the RCSL.  Please see the applicable RPSL or 
 * RCSL for the rights, obligations and limitations governing use of the 
 * contents of the file.  
 *  
 * This file is part of the Helix DNA Technology. RealNetworks is the 
 * developer of the Original Code and owns the copyrights in the portions 
 * it created. 
 *  
 * This file, and the files included with this file, is distributed and made 
 * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
 * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
 * 
 * Technology Compatibility Kit Test Suite(s) Location: 
 *    http://www.helixcommunity.org/content/tck 
 * 
 * Contributor(s): 
 *  
 * ***** END LICENSE BLOCK ***** */ 

#include "hxslist.h"
#include "chunkres.h"
#include "hlxclib/stdlib.h"		// needed for MAX_PATH
#include "hlxclib/stdio.h"		// for fopen(), etc.
#include "hlxclib/limits.h"		// for INT_MAX, etc.

#include "hlxclib/fcntl.h"	// for O_CREAT, etc.
#include "hlxclib/io.h"
#include "hlxclib/windows.h"

#include "chxdataf.h"	// cross platform file object

#ifdef _MACINTOSH
#ifdef _MAC_MACHO
#include <unistd.h> // for unlink call
#else
#include <unix.h>		// for unlink call
#undef _UNIX	//defined in unixmac.h
#endif
#endif

#ifdef _UNIX
#include <unistd.h> 	// for unlink
#ifndef _MAX_PATH
#define _MAX_PATH		256
#endif
#endif

#ifdef _SYMBIAN
#include <unistd.h> //for unlink
#endif

#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
//
//	Method:
//
//		CChunkyResMgr::OpenResource()
//
//	Purpose:
//
//		Opens an existing resource or creates a new resource.
//
//	Parameters:
//
//		CChunkyRes** ppChunkyRes
//		Memory location that will be filled in on output with the pointer
//		to the opened CChunkRes object.
//
//		const char* pResName
//		Unique name of the resource to open or create.
//
//	Return:
//
//		HX_RESULT
//		Possible errors include: TBD.
//
HX_RESULT CChunkyResMgr::OpenResource(CChunkyRes** ppChunkyRes, const char* pResName)
{
    HX_RESULT theErr = HXR_OK;

    HX_ASSERT(ppChunkyRes && pResName);
    
    void* pData;
    if (m_OpenResources.Lookup(pResName, pData))
    {
	*ppChunkyRes = (CChunkyRes*)pData;
    }
    else if (m_ClosedResources.Lookup(pResName, pData))
    {
	*ppChunkyRes = (CChunkyRes*)pData;
	HX_VERIFY(m_ClosedResources.RemoveKey(pResName));
	m_OpenResources.SetAt(pResName, pData);

	RemoveFromLRU(pResName);
    }
    else
    {
	*ppChunkyRes = new CChunkyRes;
	if (*ppChunkyRes)
	{
	    m_OpenResources.SetAt(pResName, (void*)*ppChunkyRes);
	}
	else
	{
	    theErr = HXR_OUTOFMEMORY;
	}
    }

    return theErr;
}

/////////////////////////////////////////////////////////////////////////////
//
//	Method:
//
//		CChunkyResMgr::CloseResource()
//
//	Purpose:
//
//		Closes an existing resource. Closed resources may be discarded.
//
//	Parameters:
//
//		CChunkyRes* pChunkyRes
//		Pointer to a previously opened CChunkRes object.
//
//	Return:
//
//		HX_RESULT
//		Possible errors include: TBD.
//
HX_RESULT CChunkyResMgr::CloseResource(CChunkyRes* pChunkyRes)
{
    HX_RESULT theErr = HXR_FAIL;

    POSITION pPos = m_OpenResources.GetStartPosition();
    while (pPos)
    {
	CHXString key;
	void* pData;
	m_OpenResources.GetNextAssoc(pPos, key, pData);

	if (pData == (void*)pChunkyRes)
	{
	    HX_VERIFY(m_OpenResources.RemoveKey(key));

	    m_ClosedResources.SetAt(key, pData);

	    HX_ASSERT(!m_LRUResources.FindString(key));
	    m_LRUResources.AddTailString(key);

	    theErr = HXR_OK;
	}
    }

    if (theErr == HXR_OK)
    {
	DiscardDiskData();
    }

    return theErr;
}


/////////////////////////////////////////////////////////////////////////////
//
//	Method:
//
//		CChunkyResMgr::CloseResource()
//
//	Purpose:
//
//		Closes an existing resource. Closed resources may be discarded.
//
//	Parameters:
//
//		const char* pResName
//		Unique name of a previously opened resource.
//
//	Return:
//
//		HX_RESULT
//		Possible errors include: TBD.
//
HX_RESULT CChunkyResMgr::CloseResource(const char* pResName)
{
    HX_RESULT theErr = HXR_FAIL;

    void* pData;
    if (m_OpenResources.Lookup(pResName, pData))
    {
	HX_VERIFY(m_OpenResources.RemoveKey(pResName));

	m_ClosedResources.SetAt(pResName, pData);

	HX_ASSERT(!m_LRUResources.FindString(pResName));
	m_LRUResources.AddTailString(pResName);

	theErr = HXR_OK;
    }

    if (theErr == HXR_OK)
    {
	DiscardDiskData();
    }

    return theErr;
}

/////////////////////////////////////////////////////////////////////////////
//
//	Method:
//
//		CChunkyResMgr::DiscardResource()
//
//	Purpose:
//
//		Discards a resource. Closed resources may be discarded.
//
//	Parameters:
//
//		const char* pResName
//		Unique name of a previously opened resource.
//
//	Return:
//
//		HX_RESULT
//		Possible errors include: TBD.
//
HX_RESULT CChunkyResMgr::DiscardResource(const char* pResName)
{
    HX_RESULT theErr = HXR_FAIL;

    void* pData;
    if (m_OpenResources.Lookup(pResName, pData))
    {
	HX_VERIFY(m_OpenResources.RemoveKey(pResName));

	CChunkyRes* pRes = (CChunkyRes*)pData;

	delete pRes;

	theErr = HXR_OK;
    }

    if (m_ClosedResources.Lookup(pResName, pData))
    {
	HX_VERIFY(m_ClosedResources.RemoveKey(pResName));

	RemoveFromLRU(pResName);

	CChunkyRes* pRes = (CChunkyRes*)pData;

	delete pRes;

	theErr = HXR_OK;
    }

    return theErr;
}


/////////////////////////////////////////////////////////////////////////////
//
//	Method:
//
//		CChunkyResMgr::FindResource()
//
//	Purpose:
//
//		Looks to see if the resource exists.
//
//	Parameters:
//
//		const char* pResName
//		Unique name of a previously opened resource.
//
//	Return:
//
//		HX_RESULT
HX_RESULT
CChunkyResMgr::FindResource(const char* pResName)
{
    void* pData;
    if (m_OpenResources.Lookup(pResName, pData) ||
	m_ClosedResources.Lookup(pResName, pData))
    {
	return HXR_OK;
    }

    return HXR_FAIL;
}


/////////////////////////////////////////////////////////////////////////////
//
//	Method:
//
//		CChunkyResMgr::SetDiskUsageThreshold()
//
//	Purpose:
//
//		Sets the Disk Usage threshold for the chunky resource manager.
//		If closed resources amount to more than the threshold, then they
//		will be discarded.
//
//	Parameters:
//
//		ULONG32 diskUsage
//		Disk usage in bytes which will be allowed for closed resources.
//
//	Return:
//
//		None.
//
void CChunkyResMgr::SetDiskUsageThreshold(ULONG32 diskUsage)
{
    m_ulDiskUsage = diskUsage;

    DiscardDiskData();
}


void CChunkyResMgr::DiscardDiskData()
{
    void* pData = NULL;
    CChunkyRes* pRes = NULL;
    ULONG32 ulTotal = 0;

    // Count the total disk usage
    POSITION pPos = m_ClosedResources.GetStartPosition();
    while (pPos)
    {
	CHXString key;
	m_ClosedResources.GetNextAssoc(pPos, key, pData);

	HX_ASSERT(pData);
	pRes = (CChunkyRes*)pData;

	ulTotal += pRes->GetDiskUsage();
    }

    // Trim as much as we need until we're under the disk usage threshold.
    pPos = m_LRUResources.GetHeadPosition();
    while (pPos && ulTotal > m_ulDiskUsage)
    {
	CHXString* pResName = m_LRUResources.GetNext(pPos);

	HX_ASSERT(pResName);
	if (m_ClosedResources.Lookup(*pResName, pData))
	{
	    HX_ASSERT(pData);
	    pRes = (CChunkyRes*)pData;

	    ULONG32 ulSize = pRes->GetDiskUsage();
	    if (ulSize)
	    {
		HX_ASSERT(ulSize <= ulTotal);
		ulTotal -= ulSize;

		m_ClosedResources.RemoveKey(*pResName);

		RemoveFromLRU(*pResName);

		delete pRes;
	    }
	}
    }
}


void CChunkyResMgr::RemoveFromLRU(const char* pResName)
{
    POSITION pPos = m_LRUResources.GetHeadPosition();
    POSITION pPrev; 
    while (pPos)
    {
	pPrev = pPos;
	CHXString* pStr = m_LRUResources.GetNext(pPos);
	if (!strcmp(*pStr, pResName))
	{
	    m_LRUResources.RemoveAt(pPrev);
	}
    }
}




/////////////////////////////////////////////////////////////////////////////
//
//	Method:
//
//		CChunkyResMgr::CChunkyResMgr()
//
//	Purpose:
//
//		Construtor for chunky resource manager.
//
//	Parameters:
//
//		None.
//
//	Return:
//
//		N/A
//
CChunkyResMgr::CChunkyResMgr()
    : m_ulDiskUsage(0)
{
}


/////////////////////////////////////////////////////////////////////////////
//
//	Method:
//
//		CChunkyResMgr::~CChunkyResMgr()
//
//	Purpose:
//
//		Destructor for chunky resource manager.
//
//	Parameters:
//
//		None.
//
//	Return:
//
//		N/A
//
CChunkyResMgr::~CChunkyResMgr()
{
    CHXString	key;
    CChunkyRes* pRes;
    POSITION	p;
    
    p = m_OpenResources.GetStartPosition();
    while (p)
    {
	m_OpenResources.GetNextAssoc(p, key, (void*&)pRes);
	HX_DELETE(pRes);
    }

    p = m_ClosedResources.GetStartPosition();
    while (p)
    {
	m_ClosedResources.GetNextAssoc(p, key, (void*&)pRes);
	HX_DELETE(pRes);
    }

}


/////////////////////////////////////////////////////////////////////////////
//
//	Method:
//
//		CChunkyRes::DiscardRange()
//
//	Purpose:
//
//		Discards the specified range of the file.
//
//	Parameters:
//
//		The location and length of the range to be discarded.
//
//	Return:
//
//		HX_RESULT
//		Possible errors include: TBD.
//
HX_RESULT CChunkyRes::DiscardRange( ULONG32 offset, ULONG32 count )
{
    HX_RESULT theErr = HXR_OK;
    
    // Big picture of this function is that it takes
    // care of the end cases, where part of a chunk may
    // be invalidated; then it totally removes all the
    // chunks wholly contained by the range.
    
    ULONG32 ulOffsetIntoChunk;
    
    ULONG32 ulFirstChunk = offset/DEF_CHUNKYRES_CHUNK_SIZE;
    
    ulOffsetIntoChunk = offset % DEF_CHUNKYRES_CHUNK_SIZE;
    
    ULONG32 ulLastChunk  = (offset+count)/DEF_CHUNKYRES_CHUNK_SIZE;
    
    if (ulFirstChunk == ulLastChunk)
    {
	// if the range is all in one chunk, deal with that simplest
	// case and ignore the more complicated scenarios.
	
	CChunkyResChunk* pChunk = (CChunkyResChunk*)m_Chunks[ulFirstChunk];
	
	HX_ASSERT(pChunk);
	
	pChunk->AddValidRange(ulOffsetIntoChunk, count, FALSE);
	
	return theErr;
    }
    
    if (ulOffsetIntoChunk)
    {
        // OK, we have a chunk that needs to be partially invalidated.
        
	CChunkyResChunk* pChunk = (CChunkyResChunk*)m_Chunks[ulFirstChunk];
	
	HX_ASSERT(pChunk);
	
	pChunk->AddValidRange(ulOffsetIntoChunk, DEF_CHUNKYRES_CHUNK_SIZE - ulOffsetIntoChunk, FALSE);
	
        ulFirstChunk++;
    }
    
    ulOffsetIntoChunk = (offset+count) % DEF_CHUNKYRES_CHUNK_SIZE;
    if (ulOffsetIntoChunk)
    {
        // OK, the final chunk needs to be partially invalidated.
        
	CChunkyResChunk* pChunk = (CChunkyResChunk*)m_Chunks[ulLastChunk];
	
	HX_ASSERT(pChunk);
	
	pChunk->AddValidRange(0, ulOffsetIntoChunk, FALSE);
    }
    
    for (ULONG32 ulWhichChunk = ulFirstChunk; ulWhichChunk < ulLastChunk; ulWhichChunk++)
    {
	CChunkyResChunk* pChunk = (CChunkyResChunk*)m_Chunks[ulWhichChunk];

	// if the chunk doesn't (yet?) exist, then it's considered invalid.
	
	if (pChunk)
	{
	    ULONG32 ulTempOffset = pChunk->GetTempFileOffset();
	    if (ulTempOffset)
	    {
		m_FreeDiskOffsets.AddHead((void*)ulTempOffset);
	    }
	    
	    delete pChunk;
	    m_Chunks[ulWhichChunk] = NULL;
	}
    }
    
    return theErr;
}


/////////////////////////////////////////////////////////////////////////////
//
//	Method:
//
//		CChunkyRes::GetDiskUsage()
//
//	Purpose:
//
//		Returns the entire disk usage of a resource.
//
//	Parameters:
//
//		None.
//
//	Return:
//
//		ULONG32
//		Total amount of diskspace the resource's chunks consume.
//
ULONG32 CChunkyRes::GetDiskUsage() const
{
	return (m_Chunks.GetSize() * DEF_CHUNKYRES_CHUNK_SIZE);
}

BOOL CChunkyRes::HasPartialData(ULONG32 length, ULONG32 offset /* = 0 */)
{
	return (GetContiguousLength(offset) >= length);
}

ULONG32 CChunkyRes::GetContiguousLength(ULONG32 offset /* = 0 */)
{
	ULONG32 contiguousLength = 0;
	int ndx;

	int startNdx = offset / DEF_CHUNKYRES_CHUNK_SIZE;
	if (startNdx < m_Chunks.GetSize())
	{
		CChunkyResChunk* pChunk = (CChunkyResChunk*)m_Chunks[startNdx];
		
		if (!pChunk) goto exit;
		
		contiguousLength = pChunk->GetValidLength(offset % DEF_CHUNKYRES_CHUNK_SIZE);
		
		if (contiguousLength != DEF_CHUNKYRES_CHUNK_SIZE - (offset % DEF_CHUNKYRES_CHUNK_SIZE))
		{
			goto exit;
		}
	}
	startNdx++;
	
	for (ndx = startNdx; ndx < m_Chunks.GetSize(); ndx++)
	{
		CChunkyResChunk* pChunk = (CChunkyResChunk*)m_Chunks[ndx];

		// if there is no chunk then we are no longer contiguous.
		if (!pChunk)
		{
			break;
		}

		ULONG32 chunkLength = pChunk->GetValidLength();

		contiguousLength += chunkLength;

		// if this chunk is not the max length then we are no longer contiguous
		if (chunkLength < DEF_CHUNKYRES_CHUNK_SIZE)
		{
			break;
		}
	}

exit:
	return contiguousLength;
}

/////////////////////////////////////////////////////////////////////////////
//
//	Method:
//
//		CChunkyRes::GetData()
//
//	Purpose:
//
//		Gets a block of data out of a resource.
//
//	Parameters:
//
//		ULONG32 offset
//		char* buf
//		ULONG32 count
//		ULONG32* actual
//
//	Return:
//

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -