commsfwutils/commsbufs/src/commsbufq.cpp
changeset 0 dfb7c4ff071f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commsfwutils/commsbufs/src/commsbufq.cpp	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,276 @@
+// Copyright (c) 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:
+//
+
+#include "es_commsbuf_internal.h"
+
+__IMPLEMENT_CLEANUP(RCommsBufQ, Free)
+
+
+EXPORT_C RCommsBufQ::RCommsBufQ(RCommsBuf* aChain)
+ 	{
+	iNext = aChain;
+	iLast = RCommsBufChain(aChain).Last(); // Safe even if aChain==NULL
+	}
+
+
+EXPORT_C void RCommsBufQ::Init()
+/**
+initializes the members
+*/
+	{
+	iNext = NULL;
+	iLast = NULL;
+	}
+
+
+EXPORT_C void RCommsBufQ::Assign(RCommsBufQ& aQueue)
+/**
+Assign this queue to a RCommsBuf queue
+@param aQueue to queue
+*/
+	{
+	*this = aQueue;
+	aQueue.Init();
+	}
+
+
+EXPORT_C void RCommsBufQ::Assign(RCommsBufChain& aChain)
+/**
+Assign this a RCommsBuf chain to this queue
+@param aChain the chain
+*/
+ 	{
+	iNext = aChain.First();
+	iLast = aChain.Last();
+	aChain.iNext = NULL;
+	}
+
+
+EXPORT_C void RCommsBufQ::Free()
+/**
+Frees the queue making it empty
+*/
+	{
+	if(iNext)
+		iNext->Free();
+	Init();
+	}
+
+
+EXPORT_C void RCommsBufQ::Append(RCommsBuf* aBuf)
+/**
+Appends a RCommsBuf to the queue
+@param aBuf the buffer to be prepended
+*/
+ 	{
+	if (IsEmpty())
+		iNext = iLast = aBuf;
+	else
+		{
+		iLast->SetNext(aBuf);
+		iLast = aBuf;
+		}
+	}
+
+
+EXPORT_C void RCommsBufQ::Prepend(RCommsBuf* aBuf)
+/**
+Prepends one RCommsBuf to this queue. aBuf must not point to any further CommsBufs.
+@param aBuf the buffer to be appended
+*/
+	{
+
+    __ASSERT_DEBUG(aBuf->Next()==NULL, CommsBuf::Panic(EMBuf_CannotPrependChainedMBuf));
+	if (IsEmpty())
+		{
+		iNext = aBuf;
+		iLast = aBuf;
+		aBuf->SetNext(NULL);	// break the mbuf chain (if any)
+		}
+	else
+		{
+		aBuf->SetNext(iNext);	// alter the mbuf chain (if any)
+		iNext = aBuf;
+		}
+	}
+
+
+EXPORT_C void RCommsBufQ::Append(RCommsBufQ& aQueue)
+/**
+Appends a RCommsBuf queue to this queue
+@param aQueue the queue to be appended
+*/
+ 	{
+	if (aQueue.IsEmpty())
+		return;
+
+	if (IsEmpty())
+		{
+		// src queue is reset, thus this operation is an append & move
+		*this = aQueue;
+		aQueue.Init();      // trs; why zero the src queue? implies a move instead of just append.  ideally this should be fixed, but kept as is to avoid a functional break
+		}
+	else
+		{
+		// src queue is not altered, thus this operation is only an append (ie. no move)
+		iLast->SetNext(aQueue.iNext);
+		iLast = aQueue.iLast;
+		}
+	}
+
+
+EXPORT_C void RCommsBufQ::Append(RCommsBufChain& aChain)
+/**
+Appends a RCommsBuf chain to this queue
+@param aChain the chain to be appended
+*/
+ 	{
+	if (aChain.IsEmpty())
+		return;
+
+	if (IsEmpty())
+		iNext = aChain.First();
+	else
+		iLast->SetNext(aChain.First());
+	iLast = aChain.Last();
+	aChain.iNext = NULL;
+	}
+
+
+EXPORT_C void RCommsBufQ::Prepend(RCommsBufChain& aChain)
+/**
+Prepends a RCommsBuf chain to this queue
+@param aChain the chain to be prepended
+*/
+ 	{
+	if (aChain.IsEmpty())
+		return;
+
+	if (IsEmpty())
+		iLast = aChain.Last();
+	else
+		aChain.Last()->SetNext(iNext);
+	iNext = aChain.First();
+	aChain.iNext = NULL;
+	}
+
+
+EXPORT_C void RCommsBufQ::Prepend(RCommsBufQ& aQueue)
+/**
+Prepends a RCommsBuf queue to this queue
+@param aQueue the queue to be prepended
+*/
+ 	{
+	if (aQueue.IsEmpty())
+		return;
+
+	if (IsEmpty())
+		Assign(aQueue);
+	else
+		{
+		aQueue.iLast->SetNext(iNext);
+		iNext = aQueue.iNext;
+		}
+	}
+
+
+EXPORT_C RCommsBuf* RCommsBufQ::Remove()
+/**
+Removes the first RCommsBuf from the queue
+@return the MBuf
+*/
+	{
+	RCommsBuf* m;
+
+	if (IsEmpty())
+		return NULL;
+
+	m = iNext;
+
+	if (iNext = m->Next(), iNext==NULL)
+		iLast = NULL;
+
+	m->SetNext(NULL);
+
+	return m;
+	}
+
+EXPORT_C TInt RCommsBufQ::Transfer(RCommsBufQ& aQueue, TInt aSize, TInt aBufSize, TInt& aCount)
+    {
+    __ASSERT_DEBUG(aSize >= 0, CommsBuf::Panic(EMBuf_BadBufferSize));
+
+    TInt transfered = 0;
+    aCount = 0;
+    
+    if (!IsEmpty())
+        {
+        RCommsBuf* first;
+        RCommsBuf* next;
+        RCommsBuf* last;
+    
+        first = iNext;
+        next = first;
+        last = first;
+    
+        do 
+            {
+            ++aCount;
+            transfered += aBufSize;
+            aSize -= aBufSize;
+            last = next;
+            next = next->Next();
+            } while (aSize > 0 && next != NULL);
+            
+        if (next)
+            {
+            last->SetNext(NULL);
+            iNext = next;
+            }
+        else
+            {
+            iNext = NULL;
+            iLast = NULL;
+            }
+
+        RCommsBufQ q(first, last);
+        
+        if (aSize < 0)
+            {
+            q.Last()->AdjustDataEnd(aSize);
+            }
+        aQueue.Append(q);
+        }
+    return transfered;
+    }
+
+EXPORT_C RCommsBuf* RCommsBufQ::RemoveLast()
+    {
+    RCommsBuf* current = iNext;
+    if(iNext == iLast)
+        {
+        iNext = iLast = NULL;
+        return current;
+        }
+
+    while(current->Next() != iLast)
+        {
+        current = current->Next();
+        }
+    RCommsBuf* last = iLast;
+    current->SetNext(NULL);
+    iLast = current;
+    return last;
+    }
+