--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/servicediscoveryandcontrol/pnp/test/upnp/chunkmgr/src/cmemchunk.cpp Tue Feb 02 01:12:20 2010 +0200
@@ -0,0 +1,179 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// @file
+// @internalComponent
+//
+//
+
+#include <e32base.h>
+#include "cchunkallocator.h"
+#include "rmemcell.h"
+#include "cmemchunk.h"
+
+#define MASK 0x03
+#define WORD_ALIGN(x) ( ( ( (x) + (MASK) )& ~MASK ) ) // aligns 'x' to the nearest word size
+#define IS_WORD_ALIGNED(x) ( ( (TUint32)(x) & MASK ) == 0 )
+
+
+CMemChunk* CMemChunk::New ( CChunkAllocator& aAllocator, RChunkPool& aChunkPool, TInt aNumBlocks , TInt aBlockSize )
+ {
+ // allocates chunk on shared Heap using ::new operator
+
+ // round of RMemCell & aBlockSize to the nearest word size.
+ TInt memCellSize = WORD_ALIGN ( sizeof ( RMemCell ) );
+ TInt blockSize = WORD_ALIGN ( aBlockSize );
+
+ CMemChunk* chunk = new ( aNumBlocks * ( memCellSize + blockSize ), aAllocator ) CMemChunk ( aAllocator, aNumBlocks );
+
+ // In the complete memory allocated on shared heap; first bytes are of CMemChunk,
+ // then start the memory required for RMemCell * NumBlocks and at the end contains
+ // the actual data buffer.
+
+ if ( chunk != NULL )
+ {
+ // memory required for CMemChunk and for its parameters storage
+ TUint8* chunkSize = ( ( TUint8* ) chunk ) + sizeof ( CMemChunk );
+ __ASSERT_DEBUG ( IS_WORD_ALIGNED ( chunkSize ), User::Invariant () ); // TODO Proper panic code
+
+ // memory required for RMemCell and its parameters storage
+ TUint8* dataBufStart = chunkSize + ( aNumBlocks * memCellSize );
+
+ // now place each RMemCell and its databuffer in the address specified
+ for ( TInt i = 0; i < aNumBlocks ; i++ )
+ {
+ // address assigned for RMemCell 'i'
+ RMemCell* hdr = ( RMemCell* ) ( chunkSize + i * memCellSize );
+
+ // overloaded ::new, that makes in-place allocation of MemCell at specified address
+ ( void ) new ( hdr ) RMemCell ( &aChunkPool, dataBufStart + ( i * aBlockSize ), aBlockSize );
+
+ // completed construction of a RMemCell.
+ chunk->iQueue.Append ( hdr );
+ }
+ }
+
+ return chunk;
+ }
+
+CMemChunk::CMemChunk ( CChunkAllocator& aAllocator, TInt aNumBlocks )
+ : iChunkAllocator ( aAllocator ), iNumBlocks ( aNumBlocks )
+ {
+ }
+
+CMemChunk::~CMemChunk ()
+ {
+ }
+
+TAny* CMemChunk::operator new ( TUint aSize, TInt aExtra, CChunkAllocator& aAllocator )
+ {
+ return aAllocator.Alloc ( aSize + aExtra );
+ }
+
+void CMemChunk::operator delete ( TAny* aPtr, TInt /*aExtra*/, CChunkAllocator& /*aAllocator*/ )
+ {
+ CMemChunk::operator delete ( aPtr );
+ }
+
+void CMemChunk::operator delete ( TAny* aPtr )
+ {
+ if ( aPtr )
+ {
+ ( ( CMemChunk* ) aPtr )->iChunkAllocator.Free ( aPtr );
+ }
+ }
+
+void RMemCellList::Append ( RMemCell* aPtr )
+ {
+ if ( IsEmpty () )
+ {
+ iNext = iLast = aPtr;
+ }
+ else
+ {
+ iLast->Link ( aPtr );
+ iLast = aPtr;
+ }
+ }
+
+void RMemCellList::Append ( RMemCellList& aList )
+ {
+ if ( aList.IsEmpty () )
+ {
+ return;
+ }
+
+ if ( this->IsEmpty () )
+ {
+ iNext = aList.First ();
+ iLast = aList.Last ();
+ }
+ else
+ {
+ iLast->Link ( aList.First () );
+ iLast = aList.Last ();
+ }
+ aList.Init ();
+ }
+
+TInt RMemCellList::Transfer ( RMemCellList& aList, TInt aSize )
+ {
+ __ASSERT_DEBUG ( aSize >= 0, User::Invariant () ); //TODO
+ TInt transferedBytes = 0;
+
+ if ( !IsEmpty () )
+ {
+ RMemCell* first;
+ RMemCell* next;
+ RMemCell* last;
+
+ // catch hold of first link
+ first = iNext;
+ next = first;
+ last = first;
+
+ while ( aSize >= 0 && next != NULL )
+ {
+ transferedBytes += next->Size ();
+ aSize -= next->Size ();
+
+ last = next;
+
+ next = next->Next ();
+
+ if ( aSize == 0 )
+ {
+ break;
+ }
+ }
+ last->SetLength(aSize + last->Size());
+
+ if ( next == NULL ) // all the blocks are transfferred
+ {
+ Init ();
+ }
+ else // still left with more blocks, so adjust the start & End links
+ {
+ last->Link ( NULL );
+ iNext = next;
+ }
+
+ // now the last link is ready to use
+ RMemCellList newList ( first, last );
+ aList.Append ( newList );
+ }
+
+ return transferedBytes;
+ }
+
+