chxfgbuf.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:21k
源码类别:

Symbian

开发平台:

C/C++

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