--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/servicediscoveryandcontrol/pnp/test/upnp/upnpmessage/src/CHeaderField.cpp Tue Feb 02 01:12:20 2010 +0200
@@ -0,0 +1,676 @@
+// 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:
+//
+
+// System includes
+#include <e32std.h>
+#include <http/framework/cheadercodec.h>
+
+// Local includes
+#include "CHeaders.h"
+#include "CHeaderField.h"
+
+
+CHeaderField* CHeaderField::NewL(RStringF aHeaderFieldName, CHeaders& aOwner)
+ {
+ return new(ELeave)CHeaderField(aHeaderFieldName, aOwner);
+ }
+
+/*
+CHeaderField* CHeaderField::NewL(RStringF aHeaderFieldName, CHeaders& aOwner, THTTPHdrVal aVal)
+ {
+ CHeaderField* me = new(ELeave)CHeaderField(aHeaderFieldName, aOwner);
+ CleanupStack::PushL(me);
+ CHeaderFieldPart* part = CHeaderFieldPart::NewL(aVal);
+ CleanupStack::PushL(part);
+ me->AddPartL(part);
+ CleanupStack::Pop(2);
+ return me;
+ }
+*/
+
+CHeaderField* CHeaderField::NewL(RStringF aHeaderFieldName, CHeaders& aOwner, const TDesC8& aRawData)
+ {
+ CHeaderField* me = new(ELeave)CHeaderField(aHeaderFieldName, aOwner);
+ CleanupStack::PushL(me);
+ me->ConstructL(aRawData);
+ CleanupStack::Pop(me);
+ return me;
+ }
+
+
+/** D'tor
+*/
+
+CHeaderField::~CHeaderField()
+ {
+ iName.Close();
+ ClearParsedData();
+ ClearRawData();
+ }
+
+
+/** Getter's
+*/
+/*
+RStringF CHeaderField::Name() const
+ {
+ return iName;
+ }
+*/
+
+TInt CHeaderField::NumPartsL()
+ {
+ // Convert, if necessary, to the parsed format
+ ConvertToParsedFormatL();
+
+ // Check the array exists first
+ return iParts.Count();
+ }
+
+
+THeaderFieldPartIter CHeaderField::PartsL()
+ {
+ // Convert, if necessary, to the parsed format
+ ConvertToParsedFormatL();
+
+ // create an iterator initialised for this header
+ return THeaderFieldPartIter(this);
+ }
+
+
+CHeaderFieldPart* CHeaderField::PartL(TInt aIndex)
+ {
+ // Convert, if necessary, to the parsed format
+ ConvertToParsedFormatL();
+
+ // Check the part is in range, if so return it
+ if (aIndex < NumPartsL())
+ return iParts[aIndex];
+ else
+ return NULL;
+ }
+
+EXPORT_C
+void CHeaderField::RawDataL(TPtrC8& aRawData)
+ {
+ ConvertToRawFormatL();
+ aRawData.Set(*iRawData);
+ }
+
+
+/** Setters
+*/
+/*
+void CHeaderField::SetPartL(CHeaderFieldPart* aPart, TInt aIndex)
+ {
+ if (aIndex < iParts.Count())
+ {
+ CHeaderFieldPart* oldPart = iParts[aIndex];
+ iParts[aIndex] = aPart;
+ delete oldPart;
+ }
+ else
+ User::LeaveIfError(iParts.Append(aPart));
+ }
+*/
+void CHeaderField::BeginRawDataL(TInt aChunkSize)
+ {
+ iRawChunkSize = aChunkSize;
+
+ // clear out any existing Raw data, but don't reallocate if not needed
+ if (!iRawData)
+ iRawData = HBufC8::NewL(iRawChunkSize);
+ else
+ {
+ TPtr8 rawPtr = iRawData->Des();
+ rawPtr.Zero();
+ }
+ }
+
+
+void CHeaderField::WriteRawDataL(const TDesC8& aData)
+ {
+ // Check to see if the buffer needs to grow
+ TInt maxLength = iRawData->Des().MaxLength();
+ TInt reqdLength = iRawData->Length() + aData.Length();
+ if (reqdLength > maxLength)
+ {
+ // Yes - allocate a new buffer of a larger size, and copy the contents
+ // of the old one over. This may need more than one extra chunk. Check
+ // for partial chunks - add an extra one if necessary.
+ TInt numChunksReqd = (reqdLength - maxLength)/iRawChunkSize;
+ if ( (reqdLength - maxLength)%iRawChunkSize > 0)
+ ++numChunksReqd;
+ HBufC8* largerBuffer = iRawData->ReAllocL(maxLength + iRawChunkSize*numChunksReqd);
+
+ // Switch buffers. The old one was removed by ReAlloc.
+ iRawData = largerBuffer;
+ }
+
+ // Can now append confidently
+ iRawData->Des().Append(aData);
+ }
+
+/*
+void CHeaderField::WriteRawDataL(TChar aData)
+ {
+ // Check to see if the buffer descriptor needs to grow
+ TInt maxLength = iRawData->Des().MaxLength();
+ TInt reqdLength = iRawData->Length() + 1;
+ if (reqdLength > maxLength)
+ {
+ // Yes - allocate a new buffer of a larger size, and copy the contents
+ // of the old one over. Since a single character is being added, one
+ // chunk will be enough.
+ HBufC8* largerBuffer = iRawData->ReAllocL(maxLength + iRawChunkSize);
+
+ // Switch buffers. The old one was removed by ReAlloc.
+ iRawData = largerBuffer;
+ }
+
+ // Can now append confidently
+ iRawData->Des().Append(aData);
+ }
+*/
+
+void CHeaderField::CommitRawData()
+ {
+ // Change state and remove the parsed form of the header data
+ iDataParseState = EDataInRawForm;
+ ClearParsedData();
+ }
+
+
+void CHeaderField::AddPartL(CHeaderFieldPart* aPart)
+ {
+ // Convert, if necessary, to the parsed format
+ ConvertToParsedFormatL();
+
+ // Append the item
+ User::LeaveIfError(iParts.Append(aPart));
+ }
+
+/*
+void CHeaderField::InsertPartL(CHeaderFieldPart* aPart, TInt aIndex)
+ {
+ // Convert, if necessary, to the parsed format
+ ConvertToParsedFormatL();
+
+ // If the array isn't yet constructed, or is empty, then use 'AddPart'
+ if (!NumPartsL())
+ AddPartL(aPart);
+ else
+ User::LeaveIfError(iParts.Insert(aPart, aIndex));
+ }
+*/
+/*
+TInt CHeaderField::RemovePartL(CHeaderFieldPart* aPart)
+ {
+ // Convert, if necessary, to the parsed format
+ ConvertToParsedFormatL();
+
+ // Sanity check - if no parts, then the part can't be removed...
+ if (iParts.Count() == 0)
+ return KErrNotFound;
+
+ // Find the part.
+ TInt idx = iParts.Find(aPart);
+
+ // Now remove by index
+ iParts.Remove(idx);
+ iParts.Compress();
+ delete aPart;
+ return KErrNone;
+ }
+*/
+
+TInt CHeaderField::RemovePartL(TInt aIndex)
+ {
+ // Convert, if necessary, to the parsed format
+ ConvertToParsedFormatL();
+
+ // Sanity check - if no array exists or if the index supplied is out of the bounds
+ // of the array, then the part can't be removed...
+ if ((aIndex < 0) || (aIndex >= NumPartsL()))
+ return KErrNotFound;
+
+ // Note that the array doesn't actually delete the part itself. Also the array must be
+ // compressed to close the 'gap' left by the deleted part
+ CHeaderFieldPart* part = PartL(aIndex);
+ iParts.Remove(aIndex);
+ iParts.Compress();
+ delete part;
+ return KErrNone;
+ }
+
+
+/** Constructors and second-phase construction
+*/
+
+void CHeaderField::ConvertToRawFormatL()
+ {
+ if (iDataParseState != EDataParsedOK)
+ return;
+ RHeaderField rf(*this);
+ // State change and removal of parsed data is done when the Raw data is committed by the codec when it is encoded
+ iCodec.EncodeHeaderL(rf);
+ }
+
+void CHeaderField::ConvertToParsedFormatL()
+ {
+ if (iDataParseState != EDataInRawForm)
+ return;
+ RHeaderField rf(*this);
+ iCodec.DecodeHeaderL(rf);
+
+ // If we haven't left, then it must have succeeded. Change state and remove the Raw data
+ iDataParseState = EDataParsedOK;
+ ClearRawData();
+ }
+
+CHeaderField::CHeaderField(RStringF aHeaderFieldName, CHeaders& aOwner)
+ : iDataParseState(ENoDataSupplied), iOwner(&aOwner), iCodec(aOwner.Codec())
+ {
+ // Ensure that we maintain string references correctly with the header field name
+ iName = aHeaderFieldName.Copy();
+ iDataParseState = EDataParsedOK;
+ }
+
+void CHeaderField::ConstructL(const TDesC8& aRawData)
+ {
+ // Copy the data. Set the state.
+ iRawData = aRawData.AllocL();
+ iDataParseState = EDataInRawForm;
+ }
+
+void CHeaderField::ClearParsedData()
+ {
+ // Clear and destroy parts array and its contents
+ iParts.ResetAndDestroy();
+ }
+
+void CHeaderField::ClearRawData()
+ {
+ // Destroy any Raw data
+ delete iRawData;
+ iRawData = NULL;
+ }
+
+
+/** Implementation of CHeaderFieldPart class *************************************************
+*/
+
+/** Factory methods
+*/
+
+EXPORT_C
+CHeaderFieldPart* CHeaderFieldPart::NewL(THTTPHdrVal aVal)
+ {
+ return new(ELeave)CHeaderFieldPart(aVal);
+ }
+
+
+/** D'tor
+*/
+
+CHeaderFieldPart::~CHeaderFieldPart()
+ {
+ // Remove the parameter list. Parent class clears the part value.
+ iParams.ResetAndDestroy();
+
+ // If the part's value is a string, then it must be closed.
+ if (iValue.Type() == THTTPHdrVal::KStrFVal)
+ iValue.StrF().Close();
+ if (iValue.Type() == THTTPHdrVal::KStrVal)
+ iValue.Str().Close();
+ }
+
+
+/** Getter's
+*/
+
+EXPORT_C
+THTTPHdrVal CHeaderFieldPart::Value() const
+ {
+ return iValue;
+ }
+
+EXPORT_C
+TInt CHeaderFieldPart::NumParameters() const
+ {
+ // Check the array exists first
+ return iParams.Count();
+ }
+
+
+EXPORT_C
+THeaderFieldParamIter CHeaderFieldPart::Parameters() const
+ {
+ // create an iterator initialised for this part
+ return THeaderFieldParamIter(this);
+ }
+
+/*
+CHeaderFieldParam* CHeaderFieldPart::Parameter(TInt aIndex) const
+ {
+ // Check the parameter is in range, if so return it
+ if (aIndex < NumParameters())
+ return (CHeaderFieldParam*)iParams[aIndex];
+ else
+ return NULL;
+ }
+*/
+
+CHeaderFieldParam* CHeaderFieldPart::Parameter(RStringF aParamName) const
+ {
+ // Iterate the parameter list looking for a name match
+ THeaderFieldParamIter it(this);
+ CHeaderFieldParam* retVal = NULL;
+ const CHeaderFieldParam* nextParam = NULL;
+ TBool done = EFalse;
+ while (!done && !it.AtEnd())
+ {
+ nextParam = it();
+ if (nextParam->Name() == aParamName)
+ {
+ retVal = CONST_CAST(CHeaderFieldParam*, nextParam);
+ done = ETrue;
+ }
+ ++it;
+ }
+ return retVal;
+ }
+
+
+
+/** Setter's
+*/
+
+/*
+void CHeaderFieldPart::SetValue(THTTPHdrVal aVal)
+ {
+ // We must check for an existing string value since it will have to be closed
+ if (iValue.Type() == THTTPHdrVal::KStrFVal)
+ iValue.StrF().Close();
+ if (iValue.Type() == THTTPHdrVal::KStrVal)
+ iValue.Str().Close();
+ iValue = aVal.Copy();
+ }
+*/
+EXPORT_C
+void CHeaderFieldPart::AddParamL(CHeaderFieldParam* aParam)
+ {
+ // Append the item
+ User::LeaveIfError(iParams.Append(aParam));
+ }
+
+/*
+TInt CHeaderFieldPart::RemoveParam(CHeaderFieldParam* aParam)
+ {
+ // Sanity check - if no array exists, then the part can't be removed...
+ if (iParams.Count() == 0)
+ return KErrNotFound;
+
+ // Find the param.
+ TInt idx = iParams.Find(aParam);
+
+ // Now remove by index. Note that the array doesn't actually delete the param itself. Also
+ // the array must be compressed to close the 'gap' left by the deleted param
+ if (idx != KErrNotFound)
+ {
+ iParams.Remove(idx);
+ iParams.Compress();
+ delete aParam;
+ idx = KErrNone;
+ }
+ return idx;
+ }
+*/
+
+/** c'tor
+*/
+CHeaderFieldPart::CHeaderFieldPart(THTTPHdrVal aVal)
+ : iValue(aVal)
+ {
+ // Ensure that we've copied the HdrVal properly - strings must be Copy()d in order to
+ // correctly maintain string references
+ iValue = aVal.Copy();
+ }
+
+
+
+/** Implementation of CHeaderFieldParam class *************************************************
+*/
+
+/** Factory methods
+*/
+
+EXPORT_C
+CHeaderFieldParam* CHeaderFieldParam::NewL(RStringF aParamName, THTTPHdrVal aVal)
+ {
+ return new(ELeave)CHeaderFieldParam(aParamName, aVal);
+ }
+
+
+/** D'tor
+*/
+
+CHeaderFieldParam::~CHeaderFieldParam()
+ {
+ // Close the parameter name and value, if it is a string.
+ iName.Close();
+ if (iValue.Type() == THTTPHdrVal::KStrVal)
+ iValue.Str().Close();
+ if (iValue.Type() == THTTPHdrVal::KStrFVal)
+ iValue.StrF().Close();
+ }
+
+/** Getter's
+*/
+
+EXPORT_C
+RStringF CHeaderFieldParam::Name() const
+ {
+ return iName;
+ }
+
+EXPORT_C
+THTTPHdrVal CHeaderFieldParam::Value() const
+ {
+ return iValue;
+ }
+
+/** Setter's
+*/
+/*
+void CHeaderFieldParam::SetValue(THTTPHdrVal aVal)
+ {
+ // We must check for an existing string value since it will have to be closed
+ if (iValue.Type() == THTTPHdrVal::KStrFVal)
+ iValue.StrF().Close();
+ if (iValue.Type() == THTTPHdrVal::KStrVal)
+ iValue.Str().Close();
+ iValue = aVal.Copy();
+ }
+*/
+/** c'tor
+*/
+CHeaderFieldParam::CHeaderFieldParam(RStringF aName, THTTPHdrVal aVal)
+ : iValue(aVal)
+ {
+ // Ensure that we've copied the arguments properly - strings must be Copy()d in order to
+ // correctly maintain string references
+ iName = aName.Copy();
+ iValue = aVal.Copy();
+ }
+
+
+
+/** Implementation of THeaderFieldPartIter class **********************************************
+*/
+
+
+/** Normal c'tor
+*/
+
+THeaderFieldPartIter::THeaderFieldPartIter(const CHeaderField* aHeader)
+ : iHeader(aHeader)
+ {
+ // to begin at the beginning...
+ First();
+ }
+
+/** d'tor
+*/
+
+
+/** Reset the iterator to point at the first element
+*/
+
+EXPORT_C
+void THeaderFieldPartIter::First()
+ {
+ // Check existence of the array in CHeaderField. If it hasn't been created yet then
+ // we must start off 'at the end'. This is indicated by the position index set to KErrNotFound
+ iPosIdx = 0;
+ CheckInvalidation();
+ }
+
+/** Check if the iterator is at the end of the list it traverses
+*/
+
+EXPORT_C
+TBool THeaderFieldPartIter::AtEnd()
+ {
+ return (iPosIdx == KErrNotFound);
+ }
+
+/** Advance the iterator
+*/
+
+EXPORT_C
+void THeaderFieldPartIter::operator++()
+ {
+ // Do nothing if we're already at the end
+ if (iPosIdx >= 0)
+ {
+ ++iPosIdx;
+ CheckInvalidation();
+ }
+ }
+
+/** Obtain the element at the iterator's current position
+*/
+
+EXPORT_C
+const CHeaderFieldPart* THeaderFieldPartIter::operator()()
+ {
+ CheckInvalidation();
+ if (iPosIdx > KErrNotFound)
+ return iHeader->iParts.operator[](iPosIdx);
+ else
+ return NULL;
+ }
+
+void THeaderFieldPartIter::CheckInvalidation()
+ {
+ // iPosIdx may have been valid after the last use of operator() but
+ // if an item was subsequently removed from the collection the iterator
+ // may have gone off the end.
+ if (iPosIdx >= iHeader->iParts.Count())
+ iPosIdx = KErrNotFound; // Hit the end
+ }
+
+
+
+/** Implementation of THeaderFieldParamIter class *********************************************
+*/
+
+
+/** Normal c'tor
+*/
+
+THeaderFieldParamIter::THeaderFieldParamIter(const CHeaderFieldPart* aHeaderPart)
+ : iHeaderPart(aHeaderPart)
+ {
+ // to begin at the beginning...
+ First();
+ }
+
+/** d'tor
+*/
+
+EXPORT_C
+THeaderFieldParamIter::~THeaderFieldParamIter()
+ {
+ // does nothing
+ }
+
+/** Reset the iterator to point at the first element
+*/
+
+EXPORT_C
+void THeaderFieldParamIter::First()
+ {
+ // Check existence of the array in CHeaderFieldPart. If it hasn't been created yet then
+ // we must start off 'at the end'. This is indicated by the position index set to KErrNotFound
+ iPosIdx = 0;
+ CheckInvalidation();
+ }
+
+/** Check if the iterator is at the end of the list it traverses
+*/
+
+EXPORT_C
+TBool THeaderFieldParamIter::AtEnd()
+ {
+ return (iPosIdx == KErrNotFound);
+ }
+
+/** Advance the iterator
+*/
+
+EXPORT_C
+void THeaderFieldParamIter::operator++()
+ {
+ // Do nothing if we're already at the end
+ if (iPosIdx >= 0)
+ {
+ ++iPosIdx;
+ CheckInvalidation();
+ }
+ }
+
+/** Obtain the element at the iterator's current position
+*/
+EXPORT_C
+const CHeaderFieldParam* THeaderFieldParamIter::operator()()
+ {
+ CheckInvalidation();
+ if (iPosIdx > KErrNotFound)
+ return iHeaderPart->iParams.operator[](iPosIdx);
+ else
+ return NULL;
+ }
+
+void THeaderFieldParamIter::CheckInvalidation()
+ {
+ // iPosIdx may have been valid after the last use of operator() but
+ // if an item was subsequently removed from the collection the iterator
+ // may have gone off the end.
+ if (iPosIdx >= iHeaderPart->iParams.Count())
+ iPosIdx = KErrNotFound; // Hit the end
+ }
+