📄 chxfgbuf.cpp
字号:
/* ***** 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 "hxtypes.h"
#include "hxresult.h"
#include "hxcom.h"
#include "chxfgbuf.h"
#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_INTERFACE_ARRAY_ENUMERATOR(IHXEnumFragmentedBuffer)
BEGIN_INTERFACE_LIST(_CBufferFragment)
INTERFACE_LIST_ENTRY(IID_IHXBuffer, IHXBuffer)
END_INTERFACE_LIST
BEGIN_INTERFACE_LIST(CHXFragmentedBuffer)
INTERFACE_LIST_ENTRY(IID_IHXFragmentedBuffer, IHXFragmentedBuffer)
INTERFACE_LIST_ENTRY(IID_IHXBuffer, IHXBuffer)
END_INTERFACE_LIST
/* IHXFragmentedBuffer Methods
*/
STDMETHODIMP
CHXFragmentedBuffer::_FindFragment(UINT32 ulFindIndex, REF(_CFragment*) pfrgCurrent, REF(UINT32) ulCurrentSize, REF(UINT32) ulCurrentStart)
{
pfrgCurrent = m_frglstThis.First();
ulCurrentStart = 0;
while(pfrgCurrent)
{
ulCurrentSize = pfrgCurrent->GetData()->GetSize();
if(ulCurrentStart+ulCurrentSize > ulFindIndex)
{
break;
}
ulCurrentStart += ulCurrentSize;
pfrgCurrent = pfrgCurrent->Next();
}
return HXR_OK;
}
STDMETHODIMP
CHXFragmentedBuffer::GetEnumerator(IHXEnumFragmentedBuffer** ppefbNewEnum)
{
if(!ppefbNewEnum)
return HXR_POINTER;
*ppefbNewEnum = NULL;
IHXBuffer** arrpbufData = NULL;
if(m_frglstThis.GetTotal())
{
_CFragment* pfrgCurrent;
UINT32 ulIndex;
arrpbufData = (IHXBuffer**)new IHXBuffer*[m_frglstThis.GetTotal()];
for
(
pfrgCurrent = m_frglstThis.First(), ulIndex = 0;
pfrgCurrent;
pfrgCurrent = pfrgCurrent->Next(), ++ulIndex
)
{
arrpbufData[ulIndex] = pfrgCurrent->GetData();
(arrpbufData[ulIndex])->AddRef();
}
}
CREATE_INTERFACE_ARRAY_ENUMERATOR
(
IHXEnumFragmentedBuffer,
arrpbufData,
m_frglstThis.GetTotal(),
ppefbNewEnum
)
return HXR_OK;
}
/* Use these to scatter the buffers
*/
STDMETHODIMP
CHXFragmentedBuffer::Prepend(IHXBuffer* pBufferFrom, UINT32 ulStartFrom, UINT32 ulLengthFrom)
{
if(!pBufferFrom)
{
return HXR_UNEXPECTED;
}
m_frglstThis.Insert
(
(new _CFragment())->SetData
(
pBufferFrom,
ulStartFrom,
ulLengthFrom
)
);
return HXR_OK;
}
STDMETHODIMP
CHXFragmentedBuffer::Append(IHXBuffer* pBufferFrom, UINT32 ulStartFrom, UINT32 ulLengthFrom)
{
if(!pBufferFrom)
{
return HXR_UNEXPECTED;
}
m_frglstThis.Append
(
(new _CFragment())->SetData
(
pBufferFrom,
ulStartFrom,
ulLengthFrom
)
);
return HXR_OK;
}
STDMETHODIMP
CHXFragmentedBuffer::Insert(IHXBuffer* pBufferFrom, UINT32 ulStartFrom, UINT32 ulLengthFrom, UINT32 ulStartTo)
{
if(!pBufferFrom)
{
return HXR_UNEXPECTED;
}
_CFragment* pfrgFirst;
UINT32 ulTotalFirst=0, ulSizeFirst=0;
UINT32 ulFirstIndx;
/* Find First affected fragment
*/
_FindFragment(ulStartTo, pfrgFirst, ulSizeFirst, ulTotalFirst);
ulFirstIndx = ulStartTo - ulTotalFirst;
if(pfrgFirst)
{
IHXBuffer* phxbufBuffy;
phxbufBuffy = pfrgFirst->GetData();
phxbufBuffy->AddRef();
/* Reset existing fragment to contain first part of phxbufBuffy
*/
pfrgFirst->SetData(phxbufBuffy, 0, ulFirstIndx);
/* Append new fragment to contain last part of phxbufBuffy (if any)
*/
if((ulSizeFirst-ulFirstIndx) > 0)
{
m_frglstThis.Append
(
(
(_CFragment*) new _CFragment()
)
->SetData
(
phxbufBuffy,
ulFirstIndx,
UINT32(-1)
)
, pfrgFirst
);
}
HX_RELEASE(phxbufBuffy);
}
else
{
/* The existing buffers are not big enough
* Need to make an empty Buffer sizeof ulFirstIndx-1
*/
IHXBuffer* phxbufTemp = (IHXBuffer*)(new CHXBuffer());
phxbufTemp->AddRef();
phxbufTemp->SetSize(ulFirstIndx-1);
pfrgFirst = new _CFragment();
pfrgFirst->SetData(phxbufTemp);
m_frglstThis.Append(pfrgFirst);
HX_RELEASE(phxbufTemp);
}
_CFragment* pfrgNew;
/* Make new fragment to hold the new data
*/
pfrgNew = new _CFragment();
/* Set the new data into the fragment
*/
pfrgNew->SetData(pBufferFrom, ulStartFrom, ulLengthFrom);
/* Append the New fragment
*/
m_frglstThis.Append(pfrgNew, pfrgFirst);
return HXR_OK;
}
STDMETHODIMP
CHXFragmentedBuffer::Replace(IHXBuffer* pBufferFrom, UINT32 ulStartFrom, UINT32 ulLengthFrom, UINT32 ulStartTo)
{
if(!pBufferFrom)
{
return HXR_UNEXPECTED;
}
_CFragment* pfrgFirst;
_CFragment* pfrgLast;
_CFragment* pfrgTmp;
UINT32 ulTotalFirst=0, ulSizeFirst=0, ulTotalLast=0, ulSizeLast=0;
UINT32 ulFirstIndx, ulLastIndx;
/* Find First affected fragment
*/
_FindFragment(ulStartTo, pfrgFirst, ulSizeFirst, ulTotalFirst);
ulFirstIndx = ulStartTo - ulTotalFirst;
/* Find Last affected fragment
* search for ulStartTo+ulLengthFrom
* Release any buffers contained in that byte range.
*/
pfrgLast = pfrgFirst;
ulTotalLast = 0;
while (pfrgLast)
{
ulSizeLast = pfrgLast->GetData()->GetSize();
if(ulLengthFrom <= ulTotalLast+ulSizeLast)
{
break;
}
ulTotalLast += ulSizeLast;
pfrgTmp = pfrgLast;
pfrgLast = pfrgLast->Next();
if (pfrgTmp != pfrgFirst)
{
m_frglstThis.Remove(pfrgTmp);
}
}
if(pfrgFirst == pfrgLast)
ulLastIndx = ulFirstIndx + ulLengthFrom - 1;
else
ulLastIndx = ulLengthFrom - ulTotalLast;
if(pfrgFirst)
{
IHXBuffer* phxbufBuffy;
phxbufBuffy = pfrgFirst->GetData();
phxbufBuffy->AddRef();
/* Reset existing fragment to contain first part of phxbufBuffy
*/
if(ulFirstIndx)
{
pfrgFirst->SetData(phxbufBuffy, 0, ulFirstIndx);
}
else
{
if(pfrgFirst == pfrgLast)
{
pfrgFirst = NULL;
}
else
{
/* Remove pfrgFirst..
*/
pfrgTmp = pfrgFirst->Prev();
m_frglstThis.Remove(pfrgFirst);
pfrgFirst = pfrgTmp;
}
}
if(pfrgLast)
{
if (pfrgLast == pfrgFirst)
{
/* Need to create new fragment.
*/
pfrgLast = new _CFragment();
m_frglstThis.Append(pfrgLast, pfrgFirst);
}
else
{
HX_RELEASE(phxbufBuffy);
/* Reuse existing fragment.
*/
(phxbufBuffy = pfrgLast->GetData())->AddRef();
}
if(ulLastIndx < phxbufBuffy->GetSize())
{
/* Need to fragment the Last Fragment. :)
*/
pfrgLast->SetData(phxbufBuffy, ulLastIndx+1, UINT32(-1));
}
else
{
/* Need to discard the Last Fragment.
*/
pfrgTmp = pfrgLast->Prev();
m_frglstThis.Remove(pfrgLast);
pfrgLast = pfrgTmp;
}
}
HX_RELEASE(phxbufBuffy);
}
else if (ulFirstIndx)
{
/* The existing buffers are not big enough
* Need to make an empty Buffer sizeof ulFirstIndx-1
*/
IHXBuffer *phxbufTemp = (IHXBuffer*)(new CHXBuffer());
phxbufTemp->AddRef();
phxbufTemp->SetSize(ulFirstIndx-1);
pfrgFirst = new _CFragment();
pfrgFirst->SetData(phxbufTemp);
m_frglstThis.Append(pfrgFirst);
HX_RELEASE(phxbufTemp);
}
_CFragment* pfrgNew;
/* Make new fragment to hold the new data
*/
pfrgNew = new _CFragment();
/* Set the new data into the fragment
*/
pfrgNew->SetData(pBufferFrom, ulStartFrom, ulLengthFrom);
/* Append the New fragment
*/
if (pfrgFirst)
{
m_frglstThis.Append(pfrgNew, pfrgFirst);
}
else
{
m_frglstThis.Insert(pfrgNew, pfrgLast);
}
return HXR_OK;
}
/* These will gather and return the specified area
*/
STDMETHODIMP
CHXFragmentedBuffer::Get(UINT32 ulStartFrom, UINT32 ulLengthFrom, REF(UCHAR*) pData, REF(UINT32) ulLength)
{
/* Gather from start to start+length
*/
pData = NULL;
ulLength = 0;
_CFragment* pfrgFirst=NULL;
_CFragment* pfrgCurrent=NULL;
IHXBuffer* phxbufBuffy=NULL;
UINT32 ulTotalFirst=0, ulSizeFirst=0;
UINT32 ulFirstStartIndex;
if (ulLengthFrom == (UINT32)(-1))
{
ulLengthFrom = GetSize() - ulStartFrom;
}
/* Find First fragment
*/
_FindFragment(ulStartFrom, pfrgFirst, ulSizeFirst, ulTotalFirst);
ulFirstStartIndex = ulStartFrom-ulTotalFirst;
if (pfrgFirst)
{
/* If the range is in one fragment, then just return that fragment.
*/
if(pfrgFirst->GetData()->GetSize() >= ulFirstStartIndex+ulLengthFrom)
{
(phxbufBuffy = pfrgFirst->GetData())->AddRef();
}
else
{
UCHAR* pucBuffy;
UINT32 ulStartIndex;
UINT32 ulSize;
UINT32 ulRemainingLength;
phxbufBuffy = (IHXBuffer*)(new CHXBuffer());
phxbufBuffy->AddRef();
phxbufBuffy->SetSize(ulLengthFrom);
pucBuffy = phxbufBuffy->GetBuffer();
ulStartIndex = ulFirstStartIndex;
ulSize = ulSizeFirst;
ulRemainingLength = ulLengthFrom;
pfrgCurrent = pfrgFirst;
while(pfrgCurrent && ulRemainingLength > 0)
{
_RecursiveBufferCopy
(
pucBuffy+(ulLengthFrom-ulRemainingLength),
pfrgCurrent->GetData(),
ulStartIndex,
ulSize
);
ulRemainingLength -= ulSize-ulStartIndex;
pfrgCurrent = pfrgCurrent->Next();
if (pfrgCurrent)
{
ulSize = pfrgCurrent->GetData()->GetSize();
if (ulRemainingLength < ulSize)
{
ulSize = ulRemainingLength;
}
}
ulStartIndex = 0;
}
Replace(phxbufBuffy, 0, ulLengthFrom, ulStartFrom);
/* This forces the correct offset below..
*/
ulFirstStartIndex = 0;
}
}
if(phxbufBuffy)
{
phxbufBuffy->Get(pData, ulLength);
pData = pData+ulFirstStartIndex;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -