servicediscoveryandcontrol/pnp/test/upnp/upnpmessage/src/CHeaderField.cpp
changeset 0 f5a58ecadc66
equal deleted inserted replaced
-1:000000000000 0:f5a58ecadc66
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 // System includes
       
    17 #include <e32std.h>
       
    18 #include <http/framework/cheadercodec.h>
       
    19 
       
    20 // Local includes
       
    21 #include "CHeaders.h"
       
    22 #include "CHeaderField.h"
       
    23 
       
    24 
       
    25 CHeaderField* CHeaderField::NewL(RStringF aHeaderFieldName, CHeaders& aOwner)
       
    26 	{
       
    27 	return new(ELeave)CHeaderField(aHeaderFieldName, aOwner);
       
    28 	}
       
    29 
       
    30 /*
       
    31 CHeaderField* CHeaderField::NewL(RStringF aHeaderFieldName, CHeaders& aOwner, THTTPHdrVal aVal)
       
    32 	{
       
    33 	CHeaderField* me = new(ELeave)CHeaderField(aHeaderFieldName, aOwner);
       
    34 	CleanupStack::PushL(me);
       
    35 	CHeaderFieldPart* part = CHeaderFieldPart::NewL(aVal);
       
    36 	CleanupStack::PushL(part);
       
    37 	me->AddPartL(part);
       
    38 	CleanupStack::Pop(2);
       
    39 	return me;
       
    40 	}
       
    41 */
       
    42 
       
    43 CHeaderField* CHeaderField::NewL(RStringF aHeaderFieldName, CHeaders& aOwner, const TDesC8& aRawData)
       
    44 	{
       
    45 	CHeaderField* me = new(ELeave)CHeaderField(aHeaderFieldName, aOwner);
       
    46 	CleanupStack::PushL(me);
       
    47 	me->ConstructL(aRawData);
       
    48 	CleanupStack::Pop(me);
       
    49 	return me;
       
    50 	}
       
    51 
       
    52 
       
    53 /** D'tor
       
    54 */
       
    55 
       
    56 CHeaderField::~CHeaderField()
       
    57 	{
       
    58 	iName.Close();
       
    59 	ClearParsedData();
       
    60 	ClearRawData();
       
    61 	}
       
    62 
       
    63 
       
    64 /** Getter's
       
    65 */
       
    66 /*
       
    67 RStringF CHeaderField::Name() const
       
    68 	{
       
    69 	return iName;
       
    70 	}
       
    71 */
       
    72 
       
    73 TInt CHeaderField::NumPartsL()
       
    74 	{
       
    75 	// Convert, if necessary, to the parsed format
       
    76 	ConvertToParsedFormatL();
       
    77 
       
    78 	// Check the array exists first
       
    79 	return iParts.Count();
       
    80 	}
       
    81 
       
    82 
       
    83 THeaderFieldPartIter CHeaderField::PartsL()
       
    84 	{
       
    85 	// Convert, if necessary, to the parsed format
       
    86 	ConvertToParsedFormatL();
       
    87 
       
    88 	// create an iterator initialised for this header
       
    89 	return THeaderFieldPartIter(this);
       
    90 	}
       
    91 
       
    92 
       
    93 CHeaderFieldPart* CHeaderField::PartL(TInt aIndex)
       
    94 	{
       
    95 	// Convert, if necessary, to the parsed format
       
    96 	ConvertToParsedFormatL();
       
    97 
       
    98 	// Check the part is in range, if so return it
       
    99 	if (aIndex < NumPartsL())
       
   100 		return iParts[aIndex];
       
   101 	else
       
   102 		return NULL;
       
   103 	}
       
   104 
       
   105 EXPORT_C
       
   106 void CHeaderField::RawDataL(TPtrC8& aRawData)
       
   107 	{
       
   108 	ConvertToRawFormatL();
       
   109 	aRawData.Set(*iRawData);
       
   110 	}
       
   111 
       
   112 
       
   113 /** Setters
       
   114 */
       
   115 /*
       
   116 void CHeaderField::SetPartL(CHeaderFieldPart* aPart, TInt aIndex)
       
   117 	{
       
   118 	if (aIndex < iParts.Count())
       
   119 		{
       
   120 		CHeaderFieldPart* oldPart = iParts[aIndex];
       
   121 		iParts[aIndex] = aPart;
       
   122 		delete oldPart;
       
   123 		}
       
   124 	else
       
   125 		User::LeaveIfError(iParts.Append(aPart));
       
   126 	}
       
   127 */
       
   128 void CHeaderField::BeginRawDataL(TInt aChunkSize)
       
   129 	{
       
   130 	iRawChunkSize = aChunkSize;
       
   131 
       
   132 	// clear out any existing Raw data, but don't reallocate if not needed
       
   133 	if (!iRawData)
       
   134 		iRawData = HBufC8::NewL(iRawChunkSize);
       
   135 	else
       
   136 		{
       
   137 		TPtr8 rawPtr = iRawData->Des();
       
   138 		rawPtr.Zero();
       
   139 		}
       
   140 	}
       
   141 
       
   142 
       
   143 void CHeaderField::WriteRawDataL(const TDesC8& aData)
       
   144 	{
       
   145     // Check to see if the buffer needs to grow
       
   146 	TInt maxLength  = iRawData->Des().MaxLength();
       
   147 	TInt reqdLength = iRawData->Length() + aData.Length();
       
   148 	if (reqdLength > maxLength)
       
   149 		{
       
   150 		// Yes - allocate a new buffer of a larger size, and copy the contents
       
   151 		// of the old one over. This may need more than one extra chunk. Check
       
   152 		// for partial chunks - add an extra one if necessary.
       
   153 		TInt numChunksReqd = (reqdLength - maxLength)/iRawChunkSize;
       
   154 		 if ( (reqdLength - maxLength)%iRawChunkSize > 0)
       
   155 			++numChunksReqd;
       
   156 		HBufC8* largerBuffer = iRawData->ReAllocL(maxLength + iRawChunkSize*numChunksReqd);
       
   157 
       
   158 		// Switch buffers. The old one was removed by ReAlloc.
       
   159 		iRawData = largerBuffer;
       
   160 		}
       
   161 
       
   162 	// Can now append confidently
       
   163 	iRawData->Des().Append(aData);
       
   164 	}
       
   165 
       
   166 /*
       
   167 void CHeaderField::WriteRawDataL(TChar aData)
       
   168 	{
       
   169 	// Check to see if the buffer descriptor needs to grow
       
   170 	TInt maxLength  = iRawData->Des().MaxLength();
       
   171 	TInt reqdLength = iRawData->Length() + 1;
       
   172 	if (reqdLength > maxLength)
       
   173 		{
       
   174 		// Yes - allocate a new buffer of a larger size, and copy the contents
       
   175 		// of the old one over. Since a single character is being added, one
       
   176 		// chunk will be enough.
       
   177 		HBufC8* largerBuffer = iRawData->ReAllocL(maxLength + iRawChunkSize);
       
   178 
       
   179 		// Switch buffers. The old one was removed by ReAlloc.
       
   180 		iRawData = largerBuffer;
       
   181 		}
       
   182 
       
   183 	// Can now append confidently
       
   184 	iRawData->Des().Append(aData);
       
   185 	}
       
   186 */
       
   187 
       
   188 void CHeaderField::CommitRawData()
       
   189 	{
       
   190 	// Change state and remove the parsed form of the header data
       
   191 	iDataParseState = EDataInRawForm;
       
   192 	ClearParsedData();
       
   193 	}
       
   194 
       
   195 
       
   196 void CHeaderField::AddPartL(CHeaderFieldPart* aPart)
       
   197 	{
       
   198 	// Convert, if necessary, to the parsed format
       
   199 	ConvertToParsedFormatL();
       
   200 
       
   201 	// Append the item
       
   202 	User::LeaveIfError(iParts.Append(aPart));
       
   203 	}
       
   204 
       
   205 /*
       
   206 void CHeaderField::InsertPartL(CHeaderFieldPart* aPart, TInt aIndex)
       
   207 	{
       
   208 	// Convert, if necessary, to the parsed format
       
   209 	ConvertToParsedFormatL();
       
   210 
       
   211 	// If the array isn't yet constructed, or is empty, then use 'AddPart'
       
   212 	if (!NumPartsL()) 
       
   213 		AddPartL(aPart);
       
   214 	else
       
   215 		User::LeaveIfError(iParts.Insert(aPart, aIndex));
       
   216 	}
       
   217 */
       
   218 /*
       
   219 TInt CHeaderField::RemovePartL(CHeaderFieldPart* aPart)
       
   220 	{
       
   221 	// Convert, if necessary, to the parsed format
       
   222 	ConvertToParsedFormatL();
       
   223 
       
   224 	// Sanity check - if no parts, then the part can't be removed...
       
   225 	if (iParts.Count() == 0)
       
   226 		return KErrNotFound;
       
   227 
       
   228 	// Find the part.  
       
   229 	TInt idx = iParts.Find(aPart);
       
   230 
       
   231 	// Now remove by index
       
   232 	iParts.Remove(idx);
       
   233 	iParts.Compress();
       
   234 	delete aPart;
       
   235 	return KErrNone;
       
   236 	}
       
   237 */
       
   238 
       
   239 TInt CHeaderField::RemovePartL(TInt aIndex)
       
   240 	{
       
   241 	// Convert, if necessary, to the parsed format
       
   242 	ConvertToParsedFormatL();
       
   243 
       
   244 	// Sanity check - if no array exists or if the index supplied is out of the bounds
       
   245 	// of the array, then the part can't be removed...
       
   246 	if ((aIndex < 0) || (aIndex >= NumPartsL()))
       
   247 		return KErrNotFound;
       
   248 
       
   249 	// Note that the array doesn't actually delete the part itself. Also the array must be
       
   250 	// compressed to close the 'gap' left by the deleted part
       
   251 	CHeaderFieldPart* part = PartL(aIndex);
       
   252 	iParts.Remove(aIndex);
       
   253 	iParts.Compress();
       
   254 	delete part;
       
   255 	return KErrNone;
       
   256 	}
       
   257 
       
   258 
       
   259 /** Constructors and second-phase construction
       
   260 */
       
   261 
       
   262 void CHeaderField::ConvertToRawFormatL()
       
   263 	{
       
   264 	if (iDataParseState != EDataParsedOK)
       
   265 		return;
       
   266 	RHeaderField rf(*this);
       
   267 	// State change and removal of parsed data  is done when the Raw data is committed by the codec when it is encoded
       
   268 	iCodec.EncodeHeaderL(rf);
       
   269 	}
       
   270 
       
   271 void CHeaderField::ConvertToParsedFormatL()
       
   272 	{
       
   273 	if (iDataParseState != EDataInRawForm)
       
   274 		return;
       
   275 	RHeaderField rf(*this);
       
   276 	iCodec.DecodeHeaderL(rf);
       
   277 
       
   278 	// If we haven't left, then it must have succeeded. Change state and remove the Raw data
       
   279 	iDataParseState = EDataParsedOK;
       
   280 	ClearRawData();
       
   281 	}
       
   282 
       
   283 CHeaderField::CHeaderField(RStringF aHeaderFieldName, CHeaders& aOwner)
       
   284 	: iDataParseState(ENoDataSupplied), iOwner(&aOwner), iCodec(aOwner.Codec())
       
   285 	{
       
   286 	// Ensure that we maintain string references correctly with the header field name
       
   287 	iName = aHeaderFieldName.Copy();
       
   288 	iDataParseState = EDataParsedOK;
       
   289 	}
       
   290 
       
   291 void CHeaderField::ConstructL(const TDesC8& aRawData)
       
   292 	{
       
   293 	// Copy the data.  Set the state.
       
   294 	iRawData = aRawData.AllocL();
       
   295 	iDataParseState = EDataInRawForm;
       
   296 	}
       
   297 
       
   298 void CHeaderField::ClearParsedData()
       
   299 	{
       
   300 	// Clear and destroy parts array and its contents
       
   301 	iParts.ResetAndDestroy();
       
   302 	}
       
   303 
       
   304 void CHeaderField::ClearRawData()
       
   305 	{
       
   306 	// Destroy any Raw data
       
   307 	delete iRawData;
       
   308 	iRawData = NULL;
       
   309 	}
       
   310 
       
   311 
       
   312 /** Implementation of CHeaderFieldPart class *************************************************
       
   313 */
       
   314 
       
   315 /** Factory methods
       
   316 */
       
   317 
       
   318 EXPORT_C
       
   319 CHeaderFieldPart* CHeaderFieldPart::NewL(THTTPHdrVal aVal)
       
   320 	{
       
   321 	return new(ELeave)CHeaderFieldPart(aVal);
       
   322 	}
       
   323 
       
   324 
       
   325 /** D'tor
       
   326 */
       
   327 
       
   328 CHeaderFieldPart::~CHeaderFieldPart()
       
   329 	{
       
   330 	// Remove the parameter list.  Parent class clears the part value.
       
   331 	iParams.ResetAndDestroy();
       
   332 
       
   333 	// If the part's value is a string, then it must be closed.
       
   334 	if (iValue.Type() == THTTPHdrVal::KStrFVal)
       
   335 		iValue.StrF().Close();
       
   336 	if (iValue.Type() == THTTPHdrVal::KStrVal)
       
   337 		iValue.Str().Close();
       
   338 	}
       
   339 
       
   340 
       
   341 /** Getter's
       
   342 */
       
   343 
       
   344 EXPORT_C
       
   345 THTTPHdrVal CHeaderFieldPart::Value() const
       
   346 	{
       
   347 	return iValue;
       
   348 	}
       
   349 
       
   350 EXPORT_C
       
   351 TInt CHeaderFieldPart::NumParameters() const
       
   352 	{
       
   353 	// Check the array exists first
       
   354 	return iParams.Count();
       
   355 	}
       
   356 
       
   357 
       
   358 EXPORT_C
       
   359 THeaderFieldParamIter CHeaderFieldPart::Parameters() const
       
   360 	{
       
   361 	// create an iterator initialised for this part
       
   362 	return THeaderFieldParamIter(this);
       
   363 	}
       
   364 
       
   365 /*
       
   366 CHeaderFieldParam* CHeaderFieldPart::Parameter(TInt aIndex) const
       
   367 	{
       
   368 	// Check the parameter is in range, if so return it
       
   369 	if (aIndex < NumParameters())
       
   370 		return (CHeaderFieldParam*)iParams[aIndex];
       
   371 	else
       
   372 		return NULL;
       
   373 	}
       
   374 */
       
   375 
       
   376 CHeaderFieldParam* CHeaderFieldPart::Parameter(RStringF aParamName) const
       
   377 	{
       
   378 	// Iterate the parameter list looking for a name match
       
   379 	THeaderFieldParamIter it(this);
       
   380 	CHeaderFieldParam* retVal = NULL;
       
   381 	const CHeaderFieldParam* nextParam = NULL;
       
   382 	TBool done = EFalse;
       
   383 	while (!done && !it.AtEnd())
       
   384 		{
       
   385 		nextParam = it();
       
   386 		if (nextParam->Name() == aParamName)
       
   387 			{
       
   388 			retVal = CONST_CAST(CHeaderFieldParam*, nextParam);
       
   389 			done = ETrue;
       
   390 			}
       
   391 		++it;
       
   392 		}
       
   393 	return retVal;
       
   394 	}
       
   395 
       
   396 
       
   397 
       
   398 /** Setter's
       
   399 */
       
   400 
       
   401 /*
       
   402 void CHeaderFieldPart::SetValue(THTTPHdrVal aVal)
       
   403 	{
       
   404 	// We must check for an existing string value since it will have to be closed
       
   405 	if (iValue.Type() == THTTPHdrVal::KStrFVal)
       
   406 		iValue.StrF().Close();
       
   407 	if (iValue.Type() == THTTPHdrVal::KStrVal)
       
   408 		iValue.Str().Close();
       
   409 	iValue = aVal.Copy();
       
   410 	}
       
   411 */
       
   412 EXPORT_C
       
   413 void CHeaderFieldPart::AddParamL(CHeaderFieldParam* aParam)
       
   414 	{
       
   415 	// Append the item
       
   416 	User::LeaveIfError(iParams.Append(aParam));
       
   417 	}
       
   418 
       
   419 /*
       
   420 TInt CHeaderFieldPart::RemoveParam(CHeaderFieldParam* aParam)
       
   421 	{
       
   422 	// Sanity check - if no array exists, then the part can't be removed...
       
   423 	if (iParams.Count() == 0)
       
   424 		return KErrNotFound;
       
   425 
       
   426 	// Find the param. 
       
   427 	TInt idx = iParams.Find(aParam);
       
   428 
       
   429 	// Now remove by index. Note that the array doesn't actually delete the param itself. Also
       
   430 	// the array must be compressed to close the 'gap' left by the deleted param
       
   431 	if (idx != KErrNotFound)
       
   432 		{
       
   433 		iParams.Remove(idx);
       
   434 		iParams.Compress();
       
   435 		delete aParam;
       
   436 		idx = KErrNone;
       
   437 		}
       
   438 	return idx;
       
   439 	}
       
   440 */
       
   441 
       
   442 /** c'tor
       
   443 */
       
   444 CHeaderFieldPart::CHeaderFieldPart(THTTPHdrVal aVal)
       
   445 	: iValue(aVal)
       
   446 	{
       
   447 	// Ensure that we've copied the HdrVal properly - strings must be Copy()d in order to
       
   448 	// correctly maintain string references
       
   449 	iValue = aVal.Copy();
       
   450 	}
       
   451 
       
   452 
       
   453 	
       
   454 /** Implementation of CHeaderFieldParam class *************************************************
       
   455 */
       
   456 
       
   457 /** Factory methods
       
   458 */
       
   459 
       
   460 EXPORT_C
       
   461 CHeaderFieldParam* CHeaderFieldParam::NewL(RStringF aParamName, THTTPHdrVal aVal)
       
   462 	{
       
   463 	return new(ELeave)CHeaderFieldParam(aParamName, aVal);
       
   464 	}
       
   465 
       
   466 
       
   467 /** D'tor
       
   468 */
       
   469 
       
   470 CHeaderFieldParam::~CHeaderFieldParam()
       
   471 	{
       
   472 	// Close the parameter name and value, if it is a string.
       
   473 	iName.Close();
       
   474 	if (iValue.Type() == THTTPHdrVal::KStrVal)
       
   475 		iValue.Str().Close();
       
   476 	if (iValue.Type() == THTTPHdrVal::KStrFVal)
       
   477 		iValue.StrF().Close();
       
   478 	}
       
   479 
       
   480 /** Getter's
       
   481 */
       
   482 
       
   483 EXPORT_C
       
   484 RStringF CHeaderFieldParam::Name() const
       
   485 	{
       
   486 	return iName;
       
   487 	}
       
   488 
       
   489 EXPORT_C
       
   490 THTTPHdrVal CHeaderFieldParam::Value() const
       
   491 	{
       
   492 	return iValue;
       
   493 	}
       
   494 
       
   495 /** Setter's
       
   496 */
       
   497 /*
       
   498 void CHeaderFieldParam::SetValue(THTTPHdrVal aVal)
       
   499 	{
       
   500 	// We must check for an existing string value since it will have to be closed
       
   501 	if (iValue.Type() == THTTPHdrVal::KStrFVal)
       
   502 		iValue.StrF().Close();
       
   503 	if (iValue.Type() == THTTPHdrVal::KStrVal)
       
   504 		iValue.Str().Close();
       
   505 	iValue = aVal.Copy();
       
   506 	}
       
   507 */
       
   508 /** c'tor
       
   509 */
       
   510 CHeaderFieldParam::CHeaderFieldParam(RStringF aName, THTTPHdrVal aVal)
       
   511 	: iValue(aVal)
       
   512 	{
       
   513 	// Ensure that we've copied the arguments properly - strings must be Copy()d in order to
       
   514 	// correctly maintain string references
       
   515 	iName = aName.Copy();
       
   516 	iValue = aVal.Copy();
       
   517 	}
       
   518 
       
   519 
       
   520 	
       
   521 /** Implementation of THeaderFieldPartIter class **********************************************
       
   522 */
       
   523 
       
   524 
       
   525 /** Normal c'tor
       
   526 */
       
   527 
       
   528 THeaderFieldPartIter::THeaderFieldPartIter(const CHeaderField* aHeader)
       
   529 	: iHeader(aHeader)
       
   530 	{
       
   531 	// to begin at the beginning...
       
   532 	First();
       
   533 	}
       
   534 
       
   535 /** d'tor
       
   536 */
       
   537 
       
   538 
       
   539 /** Reset the iterator to point at the first element
       
   540 */
       
   541 
       
   542 EXPORT_C
       
   543 void THeaderFieldPartIter::First()
       
   544 	{
       
   545 	// Check existence of the array in CHeaderField. If it hasn't been created yet then
       
   546 	// we must start off 'at the end'.  This is indicated by the position index set to KErrNotFound
       
   547 	iPosIdx = 0;
       
   548 	CheckInvalidation();
       
   549 	}
       
   550 
       
   551 /** Check if the iterator is at the end of the list it traverses
       
   552 */
       
   553 
       
   554 EXPORT_C
       
   555 TBool THeaderFieldPartIter::AtEnd()
       
   556 	{
       
   557 	return (iPosIdx == KErrNotFound);
       
   558 	}
       
   559 
       
   560 /** Advance the iterator
       
   561 */
       
   562 
       
   563 EXPORT_C
       
   564 void THeaderFieldPartIter::operator++()
       
   565 	{
       
   566 	// Do nothing if we're already at the end
       
   567 	if (iPosIdx >= 0)
       
   568 		{
       
   569 		++iPosIdx;
       
   570 		CheckInvalidation();
       
   571 		}
       
   572 	}
       
   573 
       
   574 /** Obtain the element at the iterator's current position
       
   575 */
       
   576 
       
   577 EXPORT_C
       
   578 const CHeaderFieldPart* THeaderFieldPartIter::operator()()
       
   579 	{
       
   580 	CheckInvalidation();
       
   581 	if (iPosIdx > KErrNotFound)
       
   582 		return iHeader->iParts.operator[](iPosIdx);
       
   583 	else
       
   584 		return NULL;
       
   585 	}
       
   586 
       
   587 void THeaderFieldPartIter::CheckInvalidation()
       
   588 	{
       
   589 	// iPosIdx may have been valid after the last use of operator() but
       
   590 	// if an item was subsequently removed from the collection the iterator
       
   591 	// may have gone off the end.
       
   592 	if (iPosIdx >= iHeader->iParts.Count())
       
   593 		iPosIdx = KErrNotFound; // Hit the end
       
   594 	}
       
   595 
       
   596 
       
   597 
       
   598 /** Implementation of THeaderFieldParamIter class *********************************************
       
   599 */
       
   600 
       
   601 
       
   602 /** Normal c'tor
       
   603 */
       
   604 
       
   605 THeaderFieldParamIter::THeaderFieldParamIter(const CHeaderFieldPart* aHeaderPart)
       
   606 	: iHeaderPart(aHeaderPart)
       
   607 	{
       
   608 	// to begin at the beginning...
       
   609 	First();
       
   610 	}
       
   611 
       
   612 /** d'tor
       
   613 */
       
   614 
       
   615 EXPORT_C
       
   616 THeaderFieldParamIter::~THeaderFieldParamIter()
       
   617 	{
       
   618 	// does nothing
       
   619 	}
       
   620 
       
   621 /** Reset the iterator to point at the first element
       
   622 */
       
   623 
       
   624 EXPORT_C
       
   625 void THeaderFieldParamIter::First()
       
   626 	{
       
   627 	// Check existence of the array in CHeaderFieldPart. If it hasn't been created yet then
       
   628 	// we must start off 'at the end'.  This is indicated by the position index set to KErrNotFound
       
   629 	iPosIdx = 0;
       
   630 	CheckInvalidation();
       
   631 	}
       
   632 
       
   633 /** Check if the iterator is at the end of the list it traverses
       
   634 */
       
   635 
       
   636 EXPORT_C
       
   637 TBool THeaderFieldParamIter::AtEnd()
       
   638 	{
       
   639 	return (iPosIdx == KErrNotFound);
       
   640 	}
       
   641 
       
   642 /** Advance the iterator
       
   643 */
       
   644 
       
   645 EXPORT_C
       
   646 void THeaderFieldParamIter::operator++()
       
   647 	{
       
   648 	// Do nothing if we're already at the end
       
   649 	if (iPosIdx >= 0)
       
   650 		{
       
   651 		++iPosIdx;
       
   652 		CheckInvalidation();
       
   653 		}
       
   654 	}
       
   655 
       
   656 /** Obtain the element at the iterator's current position
       
   657 */
       
   658 EXPORT_C
       
   659 const CHeaderFieldParam* THeaderFieldParamIter::operator()()
       
   660 	{
       
   661 	CheckInvalidation();
       
   662 	if (iPosIdx > KErrNotFound)
       
   663 		return iHeaderPart->iParams.operator[](iPosIdx);
       
   664 	else
       
   665 		return NULL;
       
   666 	}
       
   667 
       
   668 void THeaderFieldParamIter::CheckInvalidation()
       
   669 	{
       
   670 	// iPosIdx may have been valid after the last use of operator() but
       
   671 	// if an item was subsequently removed from the collection the iterator
       
   672 	// may have gone off the end.
       
   673 	if (iPosIdx >= iHeaderPart->iParams.Count())
       
   674 		iPosIdx = KErrNotFound; // Hit the end
       
   675 	}
       
   676