bluetooth/btsdp/database/responsesizevisitor.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2000-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 #include <btsdp.h>
       
    17 #include "responsesizevisitor.h"
       
    18 #include "SDPDatabase.h"
       
    19 #include "mignorer.h"
       
    20 #include "DataEncoder.h"
       
    21 
       
    22 
       
    23 // Class CHandleItem
       
    24 EXPORT_C CHandleItem* CHandleItem::NewLC()
       
    25 	{
       
    26 	CHandleItem* self = new(ELeave)CHandleItem();
       
    27 	CleanupStack::PushL(self);
       
    28 	self->ConstructL();
       
    29 	return self;
       
    30 	}
       
    31 
       
    32 EXPORT_C CHandleItem* CHandleItem::NewL()
       
    33 	{
       
    34 	CHandleItem* self = CHandleItem::NewLC();
       
    35 	CleanupStack::Pop();
       
    36 	return self;
       
    37 	}
       
    38 
       
    39 void CHandleItem::ConstructL()
       
    40 	{
       
    41 	iAttrSizeList = new (ELeave) CArrayPtrFlat<CAttrSizeItem>(KSDPAttListGran);
       
    42 	}
       
    43 
       
    44 CHandleItem::~CHandleItem()
       
    45 	{
       
    46 	if (iAttrSizeList)
       
    47 		{
       
    48 		iAttrSizeList->ResetAndDestroy();
       
    49 		delete iAttrSizeList;
       
    50 		}
       
    51 	}
       
    52 
       
    53 EXPORT_C CHandleItem* CHandleItem::CHandleItemL(TSdpServRecordHandle aHandleID, CSdpServRecord* aRecord)
       
    54 	{
       
    55 	CHandleItem* self = NewL();
       
    56 	self->iHandleID = aHandleID;
       
    57 	self->iRecord = aRecord;
       
    58 	self->iRecordSize = 0;
       
    59 	return self;
       
    60 	}
       
    61 
       
    62 void CHandleItem::AddAttrItemL(CAttrSizeItem* aItem)
       
    63 	{
       
    64 	iAttrSizeList->AppendL(aItem);
       
    65 	iRecordSize += aItem->Size() + 3; // add the attrID header size;
       
    66 	}
       
    67 
       
    68 void CHandleItem::AddAttrItemL(const TSdpAttributeID aAttributeID, TUint aSize, CSdpAttr* aAttribute)
       
    69 	{
       
    70 	CAttrSizeItem* sizeItem = new (ELeave) CAttrSizeItem(aAttributeID, aSize, aAttribute);
       
    71 	AddAttrItemL(sizeItem);
       
    72 	}
       
    73 
       
    74 
       
    75 // Class CSizeAccumulator
       
    76 
       
    77 EXPORT_C CSizeAccumulator* CSizeAccumulator::NewLC()
       
    78 	{
       
    79 	CSizeAccumulator* self = new(ELeave)CSizeAccumulator();
       
    80 	CleanupStack::PushL(self);
       
    81 	self->ConstructL();
       
    82 	return self;
       
    83 	}
       
    84 
       
    85 EXPORT_C CSizeAccumulator* CSizeAccumulator::NewL()
       
    86 	{
       
    87 	CSizeAccumulator* self = CSizeAccumulator::NewLC();
       
    88 	CleanupStack::Pop();
       
    89 	return self;
       
    90 	}
       
    91 
       
    92 void CSizeAccumulator::ConstructL()
       
    93 	{
       
    94 	iHandleList = new (ELeave) CArrayPtrFlat<CHandleItem>(KSDPHandListGran);
       
    95 	}
       
    96 
       
    97 CSizeAccumulator::~CSizeAccumulator()
       
    98 	{
       
    99 	if ( iHandleList )
       
   100 		{
       
   101 		iHandleList->ResetAndDestroy();
       
   102 		delete iHandleList;
       
   103 		}
       
   104 	}
       
   105 
       
   106 void CSizeAccumulator::AddHandleL(CHandleItem* aHandleItem)
       
   107 	{
       
   108 	iHandleList->AppendL(aHandleItem);
       
   109 	}
       
   110 
       
   111 // do a crc across all the attributes
       
   112 EXPORT_C TUint16 CSizeAccumulator::CrcAttribs()
       
   113 	{
       
   114 	TUint16 totalCrc=0;
       
   115 	for (TInt i = 0; i<HandleCount(); i++)
       
   116 		{
       
   117 		for (TInt j = 0; j<AttrCount(i); j++)
       
   118 			{
       
   119 			CAttrSizeItem* attr = AttributeOf(i,j);
       
   120 			CSdpAttrValue& theVal = attr->Attr()->Value();
       
   121 			Mem::Crc(totalCrc, reinterpret_cast<const TAny*>(theVal.Des()[0]), attr->Size());
       
   122 			}
       
   123 		}
       
   124 	return totalCrc;
       
   125 
       
   126 	}
       
   127 
       
   128 /**
       
   129 	CSizeAccumulator::SizeLeft
       
   130 	calculate the size of the attribute list.
       
   131 
       
   132 	Foundation of the continuation handling. 
       
   133 	It is used together	with StartAt.
       
   134 	It walks through the list of records, each should contain
       
   135 	a list of attributes. There are internal start offsets for
       
   136 	both the record and attribute lists. These are set with StartAt.
       
   137 
       
   138 	The method returns the size (in bytes) of the attributes, together with
       
   139 	3 bytes for each attribute ID (1 byte header, 2 byte UInt) and the correct
       
   140 	number of bytes for each DES header for the attributes of each record.
       
   141 
       
   142 	It does NOT calculate the DES header for a list of records. So an extra
       
   143 	DES must be created for Searvice Search Attribute.
       
   144 
       
   145 	This allows the total length to be written before the rest of the response
       
   146 	packet. It also allows the request handler to decide if it can fit the whole
       
   147 	response in to the response packet with or without continuation.
       
   148 	Return format is
       
   149  @verbatim
       
   150 		Size left					TUint
       
   151  @endverbatim
       
   152 **/
       
   153 EXPORT_C TUint CSizeAccumulator::SizeLeft()
       
   154 	{
       
   155 	TUint totalSize=0;
       
   156 	TInt handleCount = HandleCount();	// for testing
       
   157 	for (TInt i = iFirstRec; i < handleCount; i++)
       
   158 		{
       
   159 		TUint recordSize = 0;
       
   160 		TInt attrCount = AttrCount(i); // for testing
       
   161 		for (TInt j = iFirstAtt; j < attrCount; j++)
       
   162 			{
       
   163 			CAttrSizeItem* attr = AttributeOf(i,j);
       
   164 			recordSize += attr->Size();
       
   165 			recordSize +=3;		// the size of a attribute ID in the list
       
   166 			}
       
   167 		if (iFirstAtt == 0)
       
   168 			{ // are we sizing the whole record ?
       
   169 			TUint recRecSize = iHandleList->At(i)->CHandleItem::iRecordSize; // for testing
       
   170 			if (recordSize != recRecSize) DbPanic(ESdpDbBadSearchPattern);
       
   171 			}
       
   172 		if (recordSize)
       
   173 			{ // only add the header if there is any data
       
   174 			TUint desSize;
       
   175 			desSize = (recordSize > 0xff) ? 3 : 2;
       
   176 			desSize = (recordSize > 0xffff) ? 5 : desSize;
       
   177 			totalSize += recordSize + desSize;	// size of the DES header for this record
       
   178 			}
       
   179 		}
       
   180 	return totalSize;
       
   181 
       
   182 	}
       
   183 
       
   184 	
       
   185 /**
       
   186 	CSizeAccumulator::StartAt
       
   187 	Supplied with the data sent so far.
       
   188 	This walks through the list of service search record handles
       
   189 	and the the list of attributes associated with each record.
       
   190 
       
   191 	Once it has found the location where the size is less than or
       
   192 	equal to the parameter supplied, it sets CSizeAccumulators
       
   193 	internal record and attribute offsets to the point it has
       
   194 	reached. It will not update the offsets if the data is greater
       
   195 	than the input offset.
       
   196 	
       
   197 	The method returns the two offsets and the data already sent
       
   198 	from the current attribute.
       
   199 
       
   200 	The method counts the DES header at the start of any record. It
       
   201 	does NOT count the overall DES header if there is more than one
       
   202 	record. To do this would require a count of all bytes to evaluate
       
   203 	the DES header size. This action is the same as that of SizeLeft.
       
   204 
       
   205 	******************************************************** 
       
   206 	IMPORTANT NOTE: If aOffset traverses the database and  
       
   207 	STOPS IN THE MIDDLE OF A NEW RECORD DES HEADER, it will return 
       
   208 	THE DES HEADER OFFSET in the ATTRIBUTE OFFSET PARAMETER.
       
   209 	This is ambiguous...
       
   210 	****A calling function should ensure aOffset cannot do this***
       
   211 
       
   212 	The method returns a bool to indicate the setting was OK. It will
       
   213 	be false if the two index parameters were used and they would
       
   214 	have set the lists beyond their end. Also it returns false if the
       
   215 	offset was beyond the end of the data. If the method returns EFalse,
       
   216 	the two index parameters are set to 0.
       
   217 
       
   218 	This method can reset the parameters by being called with offset 0.
       
   219 	However it will then return false.
       
   220 	Parameter format is
       
   221  @verbatim
       
   222 		Offset in bytes from start of attribute data		TUint
       
   223 		Record index (0...)									TInt
       
   224 		Attribute index (0...)								TInt
       
   225  @endverbatim
       
   226 	Return format is
       
   227  @verbatim
       
   228 		Were the offsets set OK								TBool
       
   229 		Record index is set									TInt
       
   230 		Attribute index is set								TInt
       
   231  @endverbatim
       
   232 
       
   233 **/
       
   234 EXPORT_C TBool CSizeAccumulator::StartAt(TUint aOffset, TUint& aPartSent, TInt& aRec, TInt& aAtt)
       
   235 	{
       
   236 	// calculates and sets the next record and attribute
       
   237 	if (aOffset == 0)
       
   238 		{
       
   239 		aRec = 0; iFirstRec = 0;
       
   240 		aAtt = 0; iFirstAtt = 0;
       
   241 		aPartSent = 0;
       
   242 		return EFalse;
       
   243 		}
       
   244 	TUint totalSize=0;
       
   245 	TBool more = ETrue;
       
   246 	TInt topRec = HandleCount();
       
   247 	if (aRec > topRec)
       
   248 		{
       
   249 		aRec = 0; iFirstRec = 0;
       
   250 		aAtt = 0; iFirstAtt = 0;
       
   251 		aPartSent = 0;
       
   252 		return EFalse;
       
   253 		}
       
   254 	else if (aRec == topRec)
       
   255 		{
       
   256 		TInt partAtt = AttrCount(topRec);
       
   257 		if (aAtt > partAtt)
       
   258 			{
       
   259 			aRec = 0; iFirstRec = 0;
       
   260 			aAtt = 0; iFirstAtt = 0;
       
   261 			aPartSent = 0;
       
   262 			return EFalse;
       
   263 			}
       
   264 		}
       
   265 	iFirstRec = aRec;
       
   266 	TInt firstAttForNextRecord = aAtt;
       
   267 	while (more && (iFirstRec < topRec))
       
   268 		{
       
   269 		TUint recordSize = iHandleList->At(iFirstRec)->CHandleItem::iRecordSize;
       
   270 		TInt topAtt = AttrCount(iFirstRec);
       
   271 		iFirstAtt = firstAttForNextRecord < topAtt ? firstAttForNextRecord : topAtt;
       
   272 // except for first record we always start with a record's first attribute
       
   273 		firstAttForNextRecord = 0; 
       
   274 // add in the DES header size for this record
       
   275 		TUint desSize;
       
   276 		desSize = (recordSize > 0xff) ? 3 : 2;
       
   277 		desSize = (recordSize > 0xffff) ? 5 : desSize;
       
   278 		if (totalSize + desSize > aOffset)
       
   279 			//see "IMPORTANT NOTE" above this method
       
   280 			{
       
   281 			more = EFalse;
       
   282 			break;
       
   283 			}
       
   284 		totalSize += desSize;
       
   285 		while (more && (iFirstAtt < topAtt))
       
   286 			{
       
   287 			CAttrSizeItem* attr = AttributeOf(iFirstRec, iFirstAtt);
       
   288 			TUint nextSize = attr->Size();
       
   289 			nextSize += 3;	// Attribute ID and its header
       
   290 			if (totalSize + nextSize > aOffset)
       
   291 				{
       
   292 				more = EFalse;
       
   293 				break;
       
   294 				}
       
   295 			totalSize += nextSize;
       
   296 			iFirstAtt++;
       
   297 			}
       
   298 		if (more) iFirstRec++;
       
   299 		}
       
   300 	if (totalSize == aOffset) more = EFalse;
       
   301 	if (more)
       
   302 		{
       
   303 		aRec = 0; iFirstRec = 0;
       
   304 		aAtt = 0; iFirstAtt = 0;
       
   305 		aPartSent = 0;
       
   306 		return EFalse;
       
   307 		}
       
   308 	aRec = iFirstRec;
       
   309 	aAtt = iFirstAtt;
       
   310 	aPartSent = aOffset - totalSize;
       
   311 	return ETrue;
       
   312 //	__ASSERT_DEBUG(totalSize != aOffset, DbPanic(ESdpDbBadSearchPattern));
       
   313 	}
       
   314 
       
   315 EXPORT_C TInt CSizeAccumulator::HandleCount()
       
   316 	{
       
   317 	return iHandleList->Count();
       
   318 	}
       
   319 
       
   320 EXPORT_C TSdpServRecordHandle CSizeAccumulator::HandleAt(TInt aOffset)
       
   321 	{
       
   322 	__ASSERT_DEBUG(aOffset <= iHandleList->Count(), DbPanic(ESdpDbBadSearchPattern)); // FIXME different panic code please
       
   323 	return iHandleList->At(aOffset)->CHandleItem::iHandleID;
       
   324 	}
       
   325 
       
   326 EXPORT_C TUint CSizeAccumulator::HandleSize(TInt aOffset)
       
   327 	{
       
   328 	return iHandleList->At(aOffset)->CHandleItem::iRecordSize;
       
   329 	}
       
   330 
       
   331 EXPORT_C TInt CSizeAccumulator::AttrCount(TInt aOffset)
       
   332 	{
       
   333 	if (iHandleList->Count() == 0) return 0;
       
   334 	__ASSERT_DEBUG(aOffset <= iHandleList->Count(), DbPanic(ESdpDbBadSearchPattern));
       
   335 	if (iHandleList->At(aOffset) == NULL) return 0;
       
   336 	return iHandleList->At(aOffset)->CHandleItem::iAttrSizeList->Count();
       
   337 	}
       
   338 
       
   339 EXPORT_C CAttrSizeItem* CSizeAccumulator::AttributeOf(TInt aHandleOffset, TInt aAttOffset)
       
   340 	{
       
   341 	if (iHandleList->Count() == 0) return (CAttrSizeItem*)0;
       
   342 	__ASSERT_DEBUG(aHandleOffset < iHandleList->Count(), DbPanic(ESdpDbBadSearchPattern));
       
   343 	CHandleItem* hnd = iHandleList->At(aHandleOffset);
       
   344 	if (hnd->iAttrSizeList->Count() == 0) return (CAttrSizeItem*)0;
       
   345 	__ASSERT_DEBUG(aAttOffset < hnd->iAttrSizeList->Count(), DbPanic(ESdpDbBadSearchPattern));
       
   346 //	return iHandleList->At(aHandleOffset)->CHandleItem::iAttrSizeList->At(aAttOffset);
       
   347 	return hnd->iAttrSizeList->At(aAttOffset);
       
   348 	}
       
   349 
       
   350 
       
   351 
       
   352 // need this because CResponseSizeVisitor already has start list method...
       
   353 class CSizeEncVisitorAdaptor : public MIgnorer
       
   354 	{
       
   355 public:
       
   356 	CSizeEncVisitorAdaptor(CResponseSizeVisitor& aVisitor)
       
   357 		:iVisitor(aVisitor)
       
   358 		{}
       
   359 	MSdpElementBuilder* BuildUUIDL(const TUUID& aUUID)
       
   360 		{
       
   361 		iVisitor.FoundUUIDL(aUUID);
       
   362 		return this;
       
   363 		}
       
   364 private:
       
   365 	CResponseSizeVisitor& iVisitor;
       
   366 	};
       
   367 
       
   368 
       
   369 
       
   370 
       
   371 // Class CResponseSizeVisitor 
       
   372 
       
   373 CResponseSizeVisitor::CResponseSizeVisitor()
       
   374 	{
       
   375 	}
       
   376 
       
   377 CResponseSizeVisitor::~CResponseSizeVisitor()
       
   378 	{
       
   379 	delete iFoundIndex;
       
   380 	delete iCurrentRec;
       
   381 	delete iAdapter;
       
   382 	delete iParser;
       
   383 	}
       
   384 
       
   385 CResponseSizeVisitor* CResponseSizeVisitor::NewLC()
       
   386 	{
       
   387 	CResponseSizeVisitor* self = new(ELeave)CResponseSizeVisitor();
       
   388 	CleanupStack::PushL(self);
       
   389 	self->ConstructL();
       
   390 	return self;
       
   391 	}
       
   392 
       
   393 CResponseSizeVisitor* CResponseSizeVisitor::NewL()
       
   394 	{
       
   395 	CResponseSizeVisitor* self = CResponseSizeVisitor::NewLC();
       
   396 	CleanupStack::Pop();
       
   397 	return self;
       
   398 	}
       
   399 
       
   400 void CResponseSizeVisitor::ConstructL()
       
   401 	{
       
   402 	iAdapter = new(ELeave) CSizeEncVisitorAdaptor(*this);
       
   403 	iParser = CElementParser::NewL(iAdapter);
       
   404 	}
       
   405 
       
   406 // Iterate thru attributes in record
       
   407 /* Search through all attributes in a record
       
   408    either to find if it matches the UUIDlist,
       
   409    or if the attributes match the AttrIdMatchList
       
   410    or both. If there is no UUIDList then the sizes
       
   411    of matched attributes is saved to the size collector
       
   412 */
       
   413 void CResponseSizeVisitor::SearchRecordL(CSdpServRecord& aRec)
       
   414 	{
       
   415 // could be in calling routine
       
   416 	if (iSearchPattern)
       
   417 	{
       
   418 		if (iFoundIndex)
       
   419 			{
       
   420 			delete iFoundIndex;
       
   421 			iFoundIndex = 0;
       
   422 			}
       
   423 		iFoundIndex = CBitMapAllocator::NewL(iSearchSize);
       
   424 		iUseThis = EFalse;
       
   425 	}
       
   426 	else
       
   427 		iUseThis = ETrue;
       
   428 //	if (iCurrentRec) delete iCurrentRec;	// I want a reset.
       
   429 	iCurrentRec = CHandleItem::CHandleItemL(aRec.Handle(), &aRec);
       
   430 	
       
   431 	for(TServAttrIter attrIter(aRec.AttributeIter()); attrIter; attrIter++)
       
   432 		{
       
   433 /* 
       
   434 	we are checking every attribute, searching for the UUIDs. We don't exit if
       
   435 	we find them all because we also want to get the sizes of any attributes which
       
   436 	match our list if we have one.
       
   437 	The array of sizes is built, then thrown away if it doesn't match.
       
   438  
       
   439 */
       
   440 		if (iAtMatList)
       
   441 			{
       
   442 			TSdpAttributeID theAttrID = (*attrIter).AttributeID();
       
   443 			if(iAtMatList->InMatchList(theAttrID))
       
   444 				{// create a new array entry
       
   445 				TUint size = (*attrIter).Value().DataSize();
       
   446 				TSdpElementType type = (*attrIter).Value().Type();
       
   447 				if (type != ETypeEncoded) 
       
   448 					{
       
   449 // some server records may be un-encoded
       
   450 					size += TElementEncoder::HeaderSize(type, size); // add the header size
       
   451 					}
       
   452 				if(!(type==ETypeNil)&&!(type==ETypeEncoded&&size<=1))
       
   453 				{ // only include attribute if not either null or encoded null ...
       
   454 				  // (size of encoded (which INCLUDES header) in all non-null cases is > 1
       
   455 				  //  because other attribute types either have
       
   456 				  //  to have a header plus at least one byte, or they have at least a two byte header.)
       
   457 					iCurrentRec->AddAttrItemL(theAttrID, size, attrIter);
       
   458 					}
       
   459 				}
       
   460 			}
       
   461 		// check if any UUIDs match only if we have a UUIDList.
       
   462 		if (iSearchPattern) (*attrIter).AcceptVisitorL(*this);
       
   463 		}
       
   464 	if (iUseThis)
       
   465 		{
       
   466 		// now we have to copy the array(s) we've built up.
       
   467 		iCollector->AddHandleL(iCurrentRec);
       
   468 		iCurrentRec = 0;
       
   469 		}
       
   470 	else
       
   471 		{
       
   472 		delete iCurrentRec;	// I don't want a heap fault.
       
   473 		iCurrentRec = 0;
       
   474 		}
       
   475 	}
       
   476 
       
   477 
       
   478 //	static void SizeRespSSL(CSdpDatabase& aDb, const CSdpSearchPattern &aPattern, const CSizeAccumulator& aCollector);
       
   479 //	static void SizeRespARL(CSdpServRecord& aRec, CSdpAttrIdMatchList &aList, const CSizeAccumulator& aCollector);
       
   480 //	static void SizeRespSAL(CSdpDatabase &aDb, const CSdpSearchPattern &aPattern, CSdpAttrIdMatchList &aList, const CSizeAccumulator& aCollector);
       
   481 // we need three of these calls, all slightly different
       
   482 	EXPORT_C void CResponseSizeVisitor::SizeRespSSL(CSdpDatabase& aDb, const CSdpSearchPattern& aPattern, CSizeAccumulator& aCollector)
       
   483    	{
       
   484 	if (aPattern.Count() == 0) User::Leave(KErrArgument); // this is part of spec.
       
   485 //	SDP_DEBUG(3, FPrint(_L("Sizing SDP DB for pattern with %d entries\n"), aPattern.Count()));
       
   486 	CResponseSizeVisitor* theVisitor = CResponseSizeVisitor::NewLC();
       
   487 	theVisitor->iCollector = &aCollector;
       
   488 	theVisitor->iAtMatList = NULL;		// using it as a flag...
       
   489 	theVisitor->iSearchPattern = &aPattern;
       
   490 	theVisitor->iSearchSize = theVisitor->iSearchPattern->Count();
       
   491 
       
   492 	for(TServRecordIter recIter(aDb.RecordIter()); recIter; recIter++)
       
   493 		{// Iterate thru records in Db
       
   494 		theVisitor->SearchRecordL(*recIter);
       
   495 		}
       
   496 	CleanupStack::PopAndDestroy();//theVisitor
       
   497 	}
       
   498 
       
   499 	EXPORT_C void CResponseSizeVisitor::SizeRespARL(CSdpServRecord& aRec, const CSdpAttrIdMatchList& aList, CSizeAccumulator& aCollector)
       
   500 	{
       
   501 //	SDP_DEBUG(3, FPrint(_L("Sizing SDP DB for single record\n")));
       
   502 	CResponseSizeVisitor* theVisitor = CResponseSizeVisitor::NewLC();
       
   503 	theVisitor->iCollector = &aCollector;
       
   504 	theVisitor->iAtMatList = &aList;		// using it as a flag...
       
   505 	theVisitor->iSearchPattern = NULL;
       
   506 	theVisitor->iSearchSize = 0;
       
   507 	theVisitor->SearchRecordL(aRec);
       
   508 	CleanupStack::PopAndDestroy();//theVisitor
       
   509 	}
       
   510 
       
   511 	EXPORT_C void CResponseSizeVisitor::SizeRespSAL(CSdpDatabase &aDb, const CSdpSearchPattern &aPattern, const CSdpAttrIdMatchList& aList, CSizeAccumulator& aCollector)
       
   512 	{
       
   513 	if (aPattern.Count() == 0) User::Leave(KErrArgument); // this is part of spec.
       
   514 //	SDP_DEBUG(3, FPrint(_L("Sizing SDP DB (and attribs) with %d UUIDs\n"), aPattern.Count()));
       
   515 	CResponseSizeVisitor* theVisitor = CResponseSizeVisitor::NewLC();
       
   516 	theVisitor->iCollector = &aCollector;
       
   517 	theVisitor->iAtMatList = &aList;		// using it as a flag...
       
   518 	theVisitor->iSearchPattern = &aPattern;
       
   519 	theVisitor->iSearchSize = theVisitor->iSearchPattern->Count();
       
   520 
       
   521 	for(TServRecordIter recIter(aDb.RecordIter()); recIter; recIter++)
       
   522 		{// Iterate thru records in Db
       
   523 		theVisitor->SearchRecordL(*recIter);
       
   524 		}
       
   525 	CleanupStack::PopAndDestroy();//theVisitor
       
   526 	}
       
   527 
       
   528 
       
   529 
       
   530 void CResponseSizeVisitor::VisitAttributeL(CSdpAttr& /*aAttribute*/)
       
   531 	{
       
   532 	}
       
   533 
       
   534 void CResponseSizeVisitor::VisitAttributeValueL(CSdpAttrValue &aValue, TSdpElementType aType)
       
   535 	{
       
   536 	switch (aType)
       
   537 		{
       
   538 	case ETypeUUID:
       
   539 		FoundUUIDL(aValue.UUID());
       
   540 		break;
       
   541 		case ETypeEncoded:
       
   542 // parse out any UUIDs in this encoded attribute
       
   543 		iParser->Reset();
       
   544 		/*rem = */iParser->ParseElementsL(aValue.Des());
       
   545 		break;
       
   546 	default:
       
   547 		return;
       
   548 		}
       
   549 	}
       
   550 
       
   551 void CResponseSizeVisitor::StartListL(CSdpAttrValueList &/*aList*/)
       
   552 	{
       
   553 	}
       
   554 
       
   555 void CResponseSizeVisitor::EndListL()
       
   556 	{
       
   557 	}
       
   558 
       
   559 void CResponseSizeVisitor::FoundUUIDL(const TUUID& aUUID)
       
   560 	{
       
   561 	TInt pos;
       
   562 	if (iSearchPattern->Find(aUUID, pos)==0 &&
       
   563 		iFoundIndex->IsFree(pos))
       
   564 		{
       
   565 		iFoundIndex->AllocAt(pos);
       
   566 		if (iFoundIndex->Avail() == 0)
       
   567 			{// We've found what we were searching for.
       
   568 			iUseThis = ETrue;
       
   569 			}
       
   570 		}
       
   571 	}