chxfgbuf.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:21k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: chxfgbuf.cpp,v 1.3.36.3 2004/07/09 01:45:59 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "hxtypes.h"
  50. #include "hxresult.h"
  51. #include "hxcom.h"
  52. #include "chxfgbuf.h"
  53. #include "hxheap.h"
  54. #ifdef _DEBUG
  55. #undef HX_THIS_FILE
  56. static const char HX_THIS_FILE[] = __FILE__;
  57. #endif
  58. IMPLEMENT_INTERFACE_ARRAY_ENUMERATOR(IHXEnumFragmentedBuffer)
  59. BEGIN_INTERFACE_LIST(_CBufferFragment)
  60.     INTERFACE_LIST_ENTRY(IID_IHXBuffer, IHXBuffer)
  61. END_INTERFACE_LIST
  62. BEGIN_INTERFACE_LIST(CHXFragmentedBuffer)
  63.     INTERFACE_LIST_ENTRY(IID_IHXFragmentedBuffer, IHXFragmentedBuffer)
  64.     INTERFACE_LIST_ENTRY(IID_IHXBuffer, IHXBuffer)
  65. END_INTERFACE_LIST
  66. /* IHXFragmentedBuffer Methods
  67.  */
  68. STDMETHODIMP 
  69. CHXFragmentedBuffer::_FindFragment(UINT32 ulFindIndex, REF(_CFragment*) pfrgCurrent, REF(UINT32) ulCurrentSize, REF(UINT32) ulCurrentStart)
  70. {
  71.     pfrgCurrent = m_frglstThis.First();
  72.     ulCurrentStart = 0;
  73.     while(pfrgCurrent)
  74.     {
  75. ulCurrentSize = pfrgCurrent->GetData()->GetSize();
  76. if(ulCurrentStart+ulCurrentSize > ulFindIndex)
  77. {
  78.     break;
  79. }
  80. ulCurrentStart += ulCurrentSize;
  81. pfrgCurrent = pfrgCurrent->Next();
  82.     }
  83.     return HXR_OK;
  84. }
  85. STDMETHODIMP
  86. CHXFragmentedBuffer::GetEnumerator(IHXEnumFragmentedBuffer** ppefbNewEnum)
  87. {
  88.     if(!ppefbNewEnum)
  89.         return HXR_POINTER;
  90.     *ppefbNewEnum = NULL;
  91.     IHXBuffer** arrpbufData = NULL;
  92.     if(m_frglstThis.GetTotal())
  93.     {
  94.         _CFragment* pfrgCurrent;
  95.         UINT32 ulIndex;
  96.         arrpbufData = (IHXBuffer**)new IHXBuffer*[m_frglstThis.GetTotal()];
  97.         for 
  98.         (
  99.             pfrgCurrent = m_frglstThis.First(), ulIndex = 0;
  100.             pfrgCurrent;
  101.             pfrgCurrent = pfrgCurrent->Next(), ++ulIndex
  102.         )
  103.         {
  104.             arrpbufData[ulIndex] = pfrgCurrent->GetData();
  105.             (arrpbufData[ulIndex])->AddRef();
  106.         }
  107.     }
  108.     CREATE_INTERFACE_ARRAY_ENUMERATOR
  109.     (
  110.         IHXEnumFragmentedBuffer, 
  111.         arrpbufData,
  112.         m_frglstThis.GetTotal(),
  113.         ppefbNewEnum
  114.     )
  115.     
  116.     
  117.     return HXR_OK;
  118. }
  119. /* Use these to scatter the buffers
  120.  */
  121. STDMETHODIMP 
  122. CHXFragmentedBuffer::Prepend(IHXBuffer* pBufferFrom, UINT32 ulStartFrom, UINT32 ulLengthFrom)
  123. {
  124.     if(!pBufferFrom)
  125.     {
  126. return HXR_UNEXPECTED;
  127.     }
  128.     m_frglstThis.Insert
  129.     (
  130. (new _CFragment())->SetData
  131. (
  132.     pBufferFrom, 
  133.     ulStartFrom, 
  134.     ulLengthFrom
  135. )
  136.     );
  137.     return HXR_OK;
  138. }
  139. STDMETHODIMP 
  140. CHXFragmentedBuffer::Append(IHXBuffer* pBufferFrom, UINT32 ulStartFrom, UINT32 ulLengthFrom)
  141. {
  142.     if(!pBufferFrom)
  143.     {
  144. return HXR_UNEXPECTED;
  145.     }
  146.     m_frglstThis.Append
  147.     (
  148. (new _CFragment())->SetData
  149. (
  150.     pBufferFrom, 
  151.     ulStartFrom, 
  152.     ulLengthFrom
  153. )
  154.     );
  155.     return HXR_OK;
  156. }
  157. STDMETHODIMP 
  158. CHXFragmentedBuffer::Insert(IHXBuffer* pBufferFrom, UINT32 ulStartFrom, UINT32 ulLengthFrom, UINT32 ulStartTo)
  159. {
  160.     if(!pBufferFrom)
  161.     {
  162. return HXR_UNEXPECTED;
  163.     }
  164.     _CFragment* pfrgFirst;
  165.     UINT32 ulTotalFirst=0, ulSizeFirst=0;
  166.     UINT32 ulFirstIndx;
  167.     /* Find First affected fragment
  168.      */
  169.     _FindFragment(ulStartTo, pfrgFirst, ulSizeFirst, ulTotalFirst);
  170.     ulFirstIndx = ulStartTo - ulTotalFirst;
  171.     if(pfrgFirst)
  172.     {
  173. IHXBuffer* phxbufBuffy;
  174. phxbufBuffy = pfrgFirst->GetData();
  175. phxbufBuffy->AddRef();
  176. /* Reset existing fragment to contain first part of phxbufBuffy
  177.  */
  178. pfrgFirst->SetData(phxbufBuffy, 0, ulFirstIndx);
  179. /* Append new fragment to contain last part of phxbufBuffy (if any)
  180.  */
  181. if((ulSizeFirst-ulFirstIndx) > 0)
  182. {
  183.     m_frglstThis.Append
  184.     (
  185. (
  186.     (_CFragment*) new _CFragment()
  187. )
  188. ->SetData
  189. (
  190.     phxbufBuffy, 
  191.     ulFirstIndx, 
  192.     UINT32(-1)
  193. )
  194. , pfrgFirst
  195.     );
  196. }
  197. HX_RELEASE(phxbufBuffy);
  198.     }
  199.     else
  200.     {
  201. /* The existing buffers are not big enough
  202.  * Need to make an empty Buffer sizeof ulFirstIndx-1
  203.  */
  204. IHXBuffer* phxbufTemp = (IHXBuffer*)(new CHXBuffer());
  205. phxbufTemp->AddRef();
  206. phxbufTemp->SetSize(ulFirstIndx-1);
  207. pfrgFirst = new _CFragment();
  208. pfrgFirst->SetData(phxbufTemp);
  209. m_frglstThis.Append(pfrgFirst);
  210. HX_RELEASE(phxbufTemp);
  211.     }
  212.     _CFragment* pfrgNew;
  213.     /* Make new fragment to hold the new data
  214.      */
  215.     pfrgNew = new _CFragment();
  216.     /* Set the new data into the fragment
  217.      */
  218.     pfrgNew->SetData(pBufferFrom, ulStartFrom, ulLengthFrom);
  219.     /* Append the New fragment
  220.      */
  221.     m_frglstThis.Append(pfrgNew, pfrgFirst);
  222.     return HXR_OK;
  223. }
  224. STDMETHODIMP 
  225. CHXFragmentedBuffer::Replace(IHXBuffer* pBufferFrom, UINT32 ulStartFrom, UINT32 ulLengthFrom, UINT32 ulStartTo)
  226. {
  227.     if(!pBufferFrom)
  228.     {
  229. return HXR_UNEXPECTED;
  230.     }
  231.     _CFragment* pfrgFirst;
  232.     _CFragment* pfrgLast;
  233.     _CFragment* pfrgTmp;
  234.     UINT32 ulTotalFirst=0, ulSizeFirst=0, ulTotalLast=0, ulSizeLast=0;
  235.     UINT32 ulFirstIndx, ulLastIndx;
  236.     /* Find First affected fragment
  237.      */
  238.     _FindFragment(ulStartTo, pfrgFirst, ulSizeFirst, ulTotalFirst);
  239.     ulFirstIndx = ulStartTo - ulTotalFirst;
  240.     /* Find Last affected fragment
  241.      * search for ulStartTo+ulLengthFrom
  242.      * Release any buffers contained in that byte range.
  243.      */
  244.     pfrgLast = pfrgFirst;
  245.     ulTotalLast = 0;
  246.     while (pfrgLast)
  247.     {
  248. ulSizeLast = pfrgLast->GetData()->GetSize();
  249. if(ulLengthFrom <= ulTotalLast+ulSizeLast)
  250. {
  251.     break;
  252. }
  253. ulTotalLast += ulSizeLast;
  254. pfrgTmp = pfrgLast;
  255. pfrgLast = pfrgLast->Next();
  256. if (pfrgTmp != pfrgFirst)
  257. {
  258.     m_frglstThis.Remove(pfrgTmp);
  259. }
  260.     }
  261.     if(pfrgFirst == pfrgLast)
  262. ulLastIndx = ulFirstIndx + ulLengthFrom - 1;
  263.     else
  264. ulLastIndx = ulLengthFrom - ulTotalLast;
  265.     if(pfrgFirst)
  266.     {
  267. IHXBuffer* phxbufBuffy;
  268. phxbufBuffy = pfrgFirst->GetData();
  269. phxbufBuffy->AddRef();
  270. /* Reset existing fragment to contain first part of phxbufBuffy
  271.  */
  272. if(ulFirstIndx)
  273. {
  274.     pfrgFirst->SetData(phxbufBuffy, 0, ulFirstIndx);
  275. }
  276. else
  277. {
  278.     if(pfrgFirst == pfrgLast)
  279.     {
  280. pfrgFirst = NULL;
  281.     }
  282.     else
  283.     {
  284. /* Remove pfrgFirst..
  285.  */
  286. pfrgTmp = pfrgFirst->Prev();
  287. m_frglstThis.Remove(pfrgFirst);
  288. pfrgFirst = pfrgTmp;
  289.     }
  290. }
  291. if(pfrgLast)
  292. {
  293.     if (pfrgLast == pfrgFirst)
  294.     {
  295. /* Need to create new fragment. 
  296.  */
  297. pfrgLast = new _CFragment();
  298. m_frglstThis.Append(pfrgLast, pfrgFirst);
  299.     }
  300.     else
  301.     {
  302. HX_RELEASE(phxbufBuffy);
  303. /* Reuse existing fragment.
  304.  */
  305. (phxbufBuffy = pfrgLast->GetData())->AddRef();
  306.     }
  307.     if(ulLastIndx < phxbufBuffy->GetSize())
  308.     {
  309. /* Need to fragment the Last Fragment. :)
  310.  */
  311. pfrgLast->SetData(phxbufBuffy, ulLastIndx+1, UINT32(-1));
  312.     }
  313.     else
  314.     {
  315. /* Need to discard the Last Fragment.
  316.  */
  317. pfrgTmp = pfrgLast->Prev();
  318. m_frglstThis.Remove(pfrgLast);
  319. pfrgLast = pfrgTmp;
  320.     }
  321. }
  322. HX_RELEASE(phxbufBuffy);
  323.     }
  324.     else if (ulFirstIndx)
  325.     {
  326. /* The existing buffers are not big enough
  327.  * Need to make an empty Buffer sizeof ulFirstIndx-1
  328.  */
  329. IHXBuffer *phxbufTemp = (IHXBuffer*)(new CHXBuffer());
  330. phxbufTemp->AddRef();
  331. phxbufTemp->SetSize(ulFirstIndx-1);
  332. pfrgFirst = new _CFragment();
  333. pfrgFirst->SetData(phxbufTemp);
  334. m_frglstThis.Append(pfrgFirst);
  335. HX_RELEASE(phxbufTemp);
  336.     }
  337.     _CFragment* pfrgNew;
  338.     /* Make new fragment to hold the new data
  339.      */
  340.     pfrgNew = new _CFragment();
  341.     /* Set the new data into the fragment
  342.      */
  343.     pfrgNew->SetData(pBufferFrom, ulStartFrom, ulLengthFrom);
  344.     /* Append the New fragment
  345.      */
  346.     if (pfrgFirst)
  347.     {
  348. m_frglstThis.Append(pfrgNew, pfrgFirst);
  349.     }
  350.     else
  351.     {
  352. m_frglstThis.Insert(pfrgNew, pfrgLast);
  353.     }
  354.     return HXR_OK;
  355. }
  356. /* These will gather and return the specified area
  357.  */
  358. STDMETHODIMP 
  359. CHXFragmentedBuffer::Get(UINT32 ulStartFrom, UINT32 ulLengthFrom, REF(UCHAR*) pData, REF(UINT32) ulLength)
  360. {
  361.     /* Gather from start to start+length
  362.      */
  363.     
  364.     pData = NULL;
  365.     ulLength = 0;
  366.     
  367.     _CFragment* pfrgFirst=NULL;
  368.     _CFragment* pfrgCurrent=NULL;
  369.     IHXBuffer* phxbufBuffy=NULL;
  370.     UINT32 ulTotalFirst=0, ulSizeFirst=0;
  371.     UINT32 ulFirstStartIndex;
  372.     if (ulLengthFrom == (UINT32)(-1))
  373.     {
  374. ulLengthFrom = GetSize() - ulStartFrom;
  375.     }
  376.     /* Find First fragment
  377.      */
  378.     _FindFragment(ulStartFrom, pfrgFirst, ulSizeFirst, ulTotalFirst);
  379.     ulFirstStartIndex = ulStartFrom-ulTotalFirst;
  380.     
  381.     if (pfrgFirst)
  382.     {
  383. /* If the range is in one fragment, then just return that fragment.
  384.  */
  385. if(pfrgFirst->GetData()->GetSize() >= ulFirstStartIndex+ulLengthFrom)
  386. {
  387.     (phxbufBuffy = pfrgFirst->GetData())->AddRef();
  388. }
  389. else
  390. {
  391.     UCHAR* pucBuffy;
  392.     UINT32 ulStartIndex;
  393.     UINT32 ulSize;
  394.     UINT32 ulRemainingLength;
  395.     phxbufBuffy = (IHXBuffer*)(new CHXBuffer());
  396.     phxbufBuffy->AddRef();
  397.     phxbufBuffy->SetSize(ulLengthFrom);
  398.     pucBuffy = phxbufBuffy->GetBuffer();
  399.     ulStartIndex = ulFirstStartIndex;
  400.     ulSize = ulSizeFirst;
  401.     ulRemainingLength = ulLengthFrom;
  402.     pfrgCurrent = pfrgFirst;
  403.     while(pfrgCurrent && ulRemainingLength > 0)
  404.     {
  405. _RecursiveBufferCopy
  406. (
  407.     pucBuffy+(ulLengthFrom-ulRemainingLength),
  408.     pfrgCurrent->GetData(),
  409.     ulStartIndex,
  410.     ulSize
  411. );
  412. ulRemainingLength -= ulSize-ulStartIndex;
  413. pfrgCurrent = pfrgCurrent->Next();
  414. if (pfrgCurrent)
  415. {
  416.     ulSize = pfrgCurrent->GetData()->GetSize();
  417.     if (ulRemainingLength < ulSize)
  418.     {
  419. ulSize = ulRemainingLength;
  420.     }
  421. }
  422. ulStartIndex = 0;
  423.     }
  424.     
  425.     Replace(phxbufBuffy, 0, ulLengthFrom, ulStartFrom);
  426.     /* This forces the correct offset below..
  427.      */
  428.     ulFirstStartIndex = 0;
  429. }
  430.     }
  431.     if(phxbufBuffy)
  432.     {
  433. phxbufBuffy->Get(pData, ulLength);
  434.     
  435. pData = pData+ulFirstStartIndex;
  436. ulLength = ulLengthFrom;
  437.     }
  438.     HX_RELEASE(phxbufBuffy);
  439.     return HXR_OK;
  440. }
  441. void 
  442. CHXFragmentedBuffer::_RecursiveBufferCopy
  443. (
  444.     UCHAR* pucDestBuffer,
  445.     IHXBuffer* pbufSource,
  446.     UINT32 ulStartIndex,
  447.     UINT32 ulSize
  448. )
  449. {
  450.     IHXFragmentedBuffer* pfgbufCurrent = NULL;
  451.     /* Optimized by directly enumerating nested 
  452.      * fragmented buffers.
  453.      * (instead of "pfrgCurrent->GetData()->GetBuffer()")
  454.      */
  455.     if (!(pbufSource->QueryInterface(IID_IHXFragmentedBuffer, (void**)&pfgbufCurrent)) || pfgbufCurrent)
  456.     {
  457. IHXEnumFragmentedBuffer* pefbCurrent = NULL;
  458. IHXBuffer* pbufCurrent = NULL;
  459. UINT32 ulSizeCurrent=0;
  460. UINT32 ulCopied=0;
  461. UINT32 ulTotal=0;
  462. pfgbufCurrent->GetEnumerator(&pefbCurrent);
  463. pefbCurrent->Reset();
  464. while(!(pefbCurrent->Next(1, &pbufCurrent, NULL)) && ulSize>0)
  465. {
  466.     ulSizeCurrent =  pbufCurrent->GetSize();
  467.     
  468.     if ((ulTotal+ulSizeCurrent) < ulStartIndex)
  469.     {
  470. ulTotal += ulSizeCurrent;
  471.     }
  472.     else
  473.     {
  474. _RecursiveBufferCopy
  475. (
  476.     pucDestBuffer+ulCopied,
  477.     pbufCurrent,
  478.     ulStartIndex-ulTotal,
  479.     min(ulSize, ulSizeCurrent)
  480. );
  481. ulSize -= ulSizeCurrent;
  482. ulCopied += ulSizeCurrent;
  483. ulStartIndex = 0;
  484. ulTotal=0;
  485.     }
  486.     HX_RELEASE(pbufCurrent);
  487. }
  488. HX_RELEASE(pefbCurrent);
  489. HX_RELEASE(pfgbufCurrent);
  490.     }
  491.     else
  492.     {
  493. memcpy /* Flawfinder: ignore */
  494. (
  495.     pucDestBuffer, 
  496.     pbufSource->GetBuffer()+ulStartIndex, 
  497.     HX_SAFESIZE_T(ulSize-ulStartIndex)
  498. );
  499.     }
  500. }
  501. STDMETHODIMP_(UCHAR*) 
  502. CHXFragmentedBuffer::GetBuffer(UINT32 ulStartFrom, UINT32 ulLengthFrom)
  503. {
  504.     UCHAR* pData;
  505.     UINT32 ulLength;
  506.     /* Gather from start to start+length
  507.      */
  508.     Get(ulStartFrom, ulLengthFrom, pData, ulLength);
  509.     return pData;
  510. }
  511. /* IHXBuffer Methods
  512.  */ 
  513. /* XXX I am not doing memcopies into existing space as I cannot guarantee write access.
  514.  * An acceptable Optimization is to try to memcopy, and fragment only if that fails.
  515.  */
  516. STDMETHODIMP 
  517. CHXFragmentedBuffer::Set(const UCHAR* pData, ULONG32 ulLength)
  518. {
  519.     /* Need to make an empty Buffer sizeof ulLength
  520.      */
  521.     IHXBuffer* phxbufTemp = (IHXBuffer*)(new CHXBuffer());
  522.     phxbufTemp->AddRef();
  523.     phxbufTemp->SetSize(ulLength);
  524.     phxbufTemp->Set(pData, ulLength);
  525.     
  526.     Replace(phxbufTemp, 0, ulLength, 0);
  527.     HX_RELEASE(phxbufTemp);
  528.     return HXR_OK;
  529. }
  530. STDMETHODIMP 
  531. CHXFragmentedBuffer::Get(REF(UCHAR*) pData, REF(ULONG32) ulLength)
  532. {
  533.     return Get(0,UINT32(-1), pData, ulLength);
  534. }
  535. /* adds/removes fragment(s) to the end to set the size to the requested length
  536.  */
  537. STDMETHODIMP 
  538. CHXFragmentedBuffer::SetSize(ULONG32 ulLength)
  539. {
  540.     UINT32 ulSize;
  541.     ulSize = GetSize();
  542.     
  543.     if (ulLength > ulSize)
  544.     {
  545. /* The existing buffers are not big enough
  546.  * Need to make an empty Buffer sizeof ulLength-GetSize()
  547.  */
  548. IHXBuffer* phxbufTemp = (IHXBuffer*)(new CHXBuffer());
  549. _CFragment* pfrgNew;
  550. phxbufTemp->AddRef();
  551. phxbufTemp->SetSize(ulLength-ulSize);
  552. pfrgNew = new _CFragment();
  553. pfrgNew->SetData(phxbufTemp);
  554. m_frglstThis.Append(pfrgNew);
  555. HX_RELEASE(phxbufTemp);
  556.     }
  557.     else if (ulLength < ulSize)
  558.     {
  559. _CFragment* pfrgFirst;
  560. _CFragment* pfrgCurrent;
  561. _CFragment* pfrgTmp;
  562. UINT32 ulTotalFirst=0, ulSizeFirst=0;
  563. /* Find First affected fragment
  564.  */
  565. _FindFragment(ulLength, pfrgFirst, ulSizeFirst, ulTotalFirst);
  566. if(pfrgFirst)
  567. {
  568.     IHXBuffer* phxbufBuffy;
  569.     pfrgCurrent = pfrgFirst->Next();
  570.     phxbufBuffy = pfrgFirst->GetData();
  571.     phxbufBuffy->AddRef();
  572.     if(ulLength-ulTotalFirst > 0)
  573.     {
  574. /* Reset existing fragment to contain first part of phxbufBuffy
  575.  */
  576. pfrgFirst->SetData(phxbufBuffy, 0, ulLength-ulTotalFirst);
  577.     }
  578.     else
  579.     {
  580. m_frglstThis.Remove(pfrgFirst);
  581.     }
  582.     HX_RELEASE(phxbufBuffy);
  583.     /* Remove the truncated items.
  584.      */
  585.     while(pfrgCurrent)
  586.     {
  587. pfrgTmp = pfrgCurrent;
  588. pfrgCurrent = pfrgCurrent->Next();
  589. m_frglstThis.Remove(pfrgTmp);
  590.     }
  591. }
  592.     }
  593.     return HXR_OK;
  594. }
  595. /* returns the sum of all the fragments sizes
  596.  */
  597. STDMETHODIMP_(ULONG32) 
  598. CHXFragmentedBuffer::GetSize()
  599. {
  600.     _CFragment* pfrgCurrent;
  601.     UINT32 ulTotal = 0;
  602.     pfrgCurrent = m_frglstThis.First();
  603.     while (pfrgCurrent)
  604.     {
  605. ulTotal += pfrgCurrent->GetData()->GetSize();
  606. pfrgCurrent = pfrgCurrent->Next();
  607.     }
  608.     return ulTotal;
  609. }
  610. STDMETHODIMP_(UCHAR*) 
  611. CHXFragmentedBuffer::GetBuffer()
  612. {
  613.     return GetBuffer(0,UINT32(-1));
  614. }
  615. CHXFragmentedBuffer::_CFragment* 
  616. CHXFragmentedBuffer::_CFragment::SetData(IHXBuffer* pData)
  617. {
  618.     HX_RELEASE(m_pData); 
  619.     m_pData=pData; 
  620.     m_pData->AddRef(); 
  621.     return this;
  622. }
  623. CHXFragmentedBuffer::_CFragment* 
  624. CHXFragmentedBuffer::_CFragment::SetData(IHXBuffer* pData, UINT32 ulStartFrom, UINT32 ulLengthFrom)
  625. {
  626.     HX_RELEASE(m_pData); 
  627.     
  628.     if(!ulStartFrom && ulLengthFrom >= pData->GetSize())
  629.     {
  630. /* Use whole Buffer
  631.  */
  632. m_pData=pData;
  633.         m_pData->AddRef();
  634.     }
  635.     else
  636.     {
  637. /* Use Part of Buffer
  638.  */
  639. (
  640.     _CBufferFragment::CreateObject()
  641. )
  642. ->_SetBuffer
  643. (
  644.     pData, 
  645.     ulStartFrom, 
  646.     ulLengthFrom
  647. )
  648. ->QueryInterface
  649. (
  650.     IID_IHXBuffer,
  651.     (void**)&m_pData
  652. );
  653.     }
  654.     return this;
  655. }
  656. CHXFragmentedBuffer::_CFragment* 
  657. CHXFragmentedBuffer::_CFragment::Insert(_CFragment* pNewPrev)
  658. {
  659.     if(pNewPrev == m_pPrev)
  660.     {
  661. return this;
  662.     }
  663.     if(m_pPrev)
  664.     {
  665. m_pPrev->_SetNext(pNewPrev);
  666.     }
  667.     if(pNewPrev)
  668.     {
  669. pNewPrev->_SetNext(this);
  670. pNewPrev->_SetPrev(m_pPrev);
  671.     }
  672.     _SetPrev(pNewPrev);
  673.     return pNewPrev;
  674. }
  675. CHXFragmentedBuffer::_CFragment* 
  676. CHXFragmentedBuffer::_CFragment::Append(_CFragment* pNewNext)
  677. {
  678.     if(pNewNext == m_pNext)
  679.     {
  680. return this;
  681.     }
  682.     if(m_pNext)
  683.     {
  684. m_pNext->_SetPrev(pNewNext);
  685.     }
  686.     if(pNewNext)
  687.     {
  688. pNewNext->_SetPrev(this);
  689. pNewNext->_SetNext(m_pNext);
  690.     }
  691.     _SetNext(pNewNext);
  692.     
  693.     return pNewNext;
  694. }
  695. CHXFragmentedBuffer::_CFragment* 
  696. CHXFragmentedBuffer::_CFragment::Remove()
  697. {
  698.     _CFragment* pfrgRet;
  699.     
  700.     if(m_pNext)
  701.     {
  702. pfrgRet = m_pNext;
  703.     }
  704.     else 
  705.     {
  706. pfrgRet = m_pPrev;
  707.     }
  708.     
  709.     delete this;
  710.     return pfrgRet;
  711. }
  712. void 
  713. CHXFragmentedBuffer::_CFragmentList::Remove(_CFragment* pfrgObsolete)
  714. {
  715.     if(pfrgObsolete)
  716.     {
  717. if (pfrgObsolete == m_pfrgListEnd)
  718. {
  719.     m_pfrgListEnd = pfrgObsolete->Prev();
  720. }
  721. if (pfrgObsolete == m_pfrgListStart)
  722. {
  723.     m_pfrgListStart = pfrgObsolete->Next();
  724. }
  725. pfrgObsolete->Remove();
  726.         --m_ulTotal;
  727.     }
  728. }
  729. void 
  730. CHXFragmentedBuffer::_CFragmentList::Insert(_CFragment* pfrgNew, _CFragment* pfrgRelative)
  731. {
  732.     if (!pfrgNew)
  733.     {
  734. return;
  735.     }
  736.     if(pfrgRelative)
  737.     {
  738. pfrgRelative->Insert(pfrgNew);
  739. if (pfrgRelative == m_pfrgListStart)
  740. {
  741.     m_pfrgListStart = pfrgNew;
  742. }
  743.     }
  744.     else if (m_pfrgListStart)
  745.     {
  746. m_pfrgListStart->Insert(pfrgNew);
  747. m_pfrgListStart = pfrgNew;
  748.     }
  749.     else
  750.     {
  751. m_pfrgListStart = m_pfrgListEnd = pfrgNew;
  752.     }
  753.     ++m_ulTotal;
  754. }
  755. void 
  756. CHXFragmentedBuffer::_CFragmentList::Append(_CFragment* pfrgNew, _CFragment* pfrgRelative)
  757. {
  758.     if (!pfrgNew)
  759.     {
  760. return;
  761.     }
  762.     if(pfrgRelative)
  763.     {
  764. pfrgRelative->Append(pfrgNew);
  765. if (pfrgRelative == m_pfrgListEnd)
  766. {
  767.     m_pfrgListEnd = pfrgNew;
  768. }
  769.     }
  770.     else if (m_pfrgListEnd)
  771.     {
  772. m_pfrgListEnd->Append(pfrgNew);
  773. m_pfrgListEnd = pfrgNew;
  774.     }
  775.     else
  776.     {
  777. m_pfrgListStart = m_pfrgListEnd = pfrgNew;
  778.     }
  779.     ++m_ulTotal;
  780. }
  781. _CBufferFragment* 
  782. _CBufferFragment::_SetBuffer(IHXBuffer* pData, UINT32 ulStart, UINT32 ulLength)
  783. {
  784.     HX_RELEASE(m_pData); 
  785.     m_pData = pData; 
  786.     
  787.     if(m_pData)
  788.     {
  789. m_pData->AddRef();
  790. m_ulStart=ulStart;
  791. if(m_pData->GetSize()-ulStart < ulLength)
  792. {
  793.     m_ulLength=m_pData->GetSize()-ulStart;
  794. }
  795. else
  796. {
  797.     m_ulLength=ulLength;
  798. }
  799.     }
  800.     else
  801.     {
  802. m_ulStart=0;
  803. m_ulLength=0;
  804.     }
  805.     return this;
  806. }
  807. STDMETHODIMP 
  808. _CBufferFragment::Set(const UCHAR* pData, UINT32 ulLength)
  809. {
  810.     if(!m_pData)
  811.     {
  812. return HXR_UNEXPECTED;
  813.     }
  814.     return m_pData->Set(pData+m_ulStart, ulLength);
  815. }
  816. STDMETHODIMP
  817. _CBufferFragment::Get(REF(UCHAR*) pData, REF(UINT32) ulLength)
  818. {
  819.     if(!m_pData)
  820.     {
  821. return HXR_UNEXPECTED;
  822.     }
  823.     if(ulLength > m_ulLength)
  824.     {
  825. return HXR_INVALID_PARAMETER;
  826.     }
  827.     pData = GetBuffer();
  828.     ulLength = GetSize();
  829.     
  830.     return HXR_OK;
  831. }
  832. STDMETHODIMP
  833. _CBufferFragment::SetSize(UINT32 ulLength)
  834. {
  835.     HX_RESULT hxrRet = HXR_FAIL;
  836.     if(!m_pData)
  837.     {
  838. /* Make New Buffer
  839.  */
  840. m_pData = (IHXBuffer*)(new CHXBuffer());
  841. m_pData->AddRef();
  842. m_ulStart = 0;
  843.     }
  844.     
  845.     hxrRet = m_pData->SetSize(ulLength+m_ulStart);
  846.     m_ulLength = ulLength;
  847.     
  848.     return hxrRet;
  849. }
  850. STDMETHODIMP_(UINT32)
  851. _CBufferFragment::GetSize()
  852. {
  853.     if(!m_pData)
  854.     {
  855. return 0;
  856.     }
  857.     return min(m_pData->GetSize()-m_ulStart, m_ulLength);
  858. }
  859. STDMETHODIMP_(UCHAR*)
  860. _CBufferFragment::GetBuffer()
  861. {
  862.     if(!m_pData)
  863.     {
  864. return NULL;
  865.     }
  866.     return m_pData->GetBuffer()?m_pData->GetBuffer()+m_ulStart:NULL;
  867. }