--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btsdp/database/ServiceSearchVisitor.cpp Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,312 @@
+// Copyright (c) 2000-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:
+// cservicesearchvisitor.cpp
+//
+//
+
+#include <btsdp.h>
+#include "SDPDatabase.h"
+#include "ServiceSearchVisitor.h"
+#include "mignorer.h"
+
+EXPORT_C CSdpSearchPattern* CSdpSearchPattern::NewL()
+/** Allocates and constructs a new CSdpSearchPattern object.
+
+@return New CSdpSearchPattern object */
+ {
+ CSdpSearchPattern* self = new(ELeave) CSdpSearchPattern();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C void CSdpSearchPattern::ConstructL()
+/** Allocates a new UUID array. */
+ {
+ iUUIDArray = new(ELeave) CArrayFixFlat<TUUID>(1);
+ }
+
+EXPORT_C CSdpSearchPattern::~CSdpSearchPattern()
+/** Destructor
+
+Destroys the UUID array. */
+ {
+ delete iUUIDArray;
+ }
+
+CSdpSearchPattern::CSdpSearchPattern()
+ {
+ }
+
+EXPORT_C TInt CSdpSearchPattern::AddL(const TUUID& aUUID)
+/** Adds a UID to the list.
+
+@param aUUID UUID to add
+@return Position in the list that the UUID is inserted at, or KErrAlreadyExists
+if it's already in the list */
+ {
+ TInt pos;
+ if(Find(aUUID, pos) != 0)
+ {
+ // The UUID is not currently in the pattern. Try to add it.
+ iUUIDArray->InsertL(pos, aUUID);
+ }
+ else
+ {
+ pos = KErrAlreadyExists;
+ }
+
+ return pos;
+ }
+
+EXPORT_C TInt CSdpSearchPattern::Count() const
+/** Gets the number of UUIDs in the list.
+
+@return Number of UUIDs in the list */
+ {
+ return iUUIDArray->Count();
+ }
+
+EXPORT_C const TUUID CSdpSearchPattern::At(TInt anIndex) const
+/** Gets the UUID at the specified position in the list.
+
+@param anIndex Position of the UUID to get
+@return UUID at specified position */
+ {
+ return iUUIDArray->At(anIndex);
+ }
+
+EXPORT_C void CSdpSearchPattern::Reset()
+/** Removes all UUIDs from the list. */
+ {
+ iUUIDArray->Reset();
+ }
+
+EXPORT_C TInt CSdpSearchPattern::Remove(const TUUID& aUUID)
+/** Removes a UUID from the list.
+
+@param aUUID UUID to remove
+@return Position in the list of the UUID, or KErrNotFound if it's not in the
+list */
+ {
+ TInt pos;
+ if (Find(aUUID, pos)==0)
+ {
+ iUUIDArray->Delete(pos);
+ return pos;
+ }
+ return KErrNotFound;
+ }
+
+EXPORT_C TInt CSdpSearchPattern::Find(const TUUID& aUUID, TInt &aPos) const
+/** Gets the position of the specified UUID in the list.
+
+@param aUUID UUID to find
+@param aPos Position of the UUID if it is in the list, otherwise the position
+where it would be inserted
+@return 0 if aUUID is found, otherwise non-zero */
+ { // first parameter is Offset of data in UUID
+ TInt result;
+ for(TInt i=0;i<iUUIDArray->Count();i++)
+ {
+ result = aUUID.LongForm().Compare(iUUIDArray->At(i).LongForm());
+
+ if(result == 0)
+ {
+ aPos = i;
+ return 0; // Inicates that the UUID was found.
+ }
+ else
+ {
+ // The UUID being search for is less than the UUID at the
+ // current array index (i). The search is over. Set the
+ // position reference (aPos) to reflect that the current
+ // index is where the UUID should be inserted if required.
+ if(result < 0)
+ {
+ aPos = i;
+ return KErrNotFound;
+ }
+ }
+ }
+
+ // Either the UUID array is empty, or the search UUID is greater than
+ // all the UUIDs in the array.
+ aPos = iUUIDArray->Count();
+ return KErrNotFound;
+ }
+
+EXPORT_C TBool CSdpSearchPattern::IsEmpty()
+ {
+ return Count()==0;
+ }
+
+MSdpElementBuilder* CSdpSearchPattern::BuildUUIDL(const TUUID& aUUID)
+ {
+ AddL(aUUID);
+ // Could error on repeated UUIDs (we ignore them anyway though)
+ return this;
+ }
+
+MSdpElementBuilder* CSdpSearchPattern::BuildDESL()
+ {
+ return this;
+ }
+
+MSdpElementBuilder* CSdpSearchPattern::StartListL()
+ {
+ return this;
+ }
+
+MSdpElementBuilder* CSdpSearchPattern::EndListL()
+ {//Service search pattern is complete, so terminate this parse
+ return 0;
+ }
+
+class CEncodedVisitorAdapter : public CBase, public MIgnorer
+ {
+public:
+ CEncodedVisitorAdapter(CServiceSearchVisitor& aVisitor)
+ :iVisitor(aVisitor)
+ {}
+ virtual MSdpElementBuilder* BuildUUIDL(const TUUID& aUUID)
+ {
+ iVisitor.FoundUUIDL(aUUID);
+ return this;
+ }
+private:
+ CServiceSearchVisitor& iVisitor;
+ };
+
+
+// Class CServiceSearchVisitor
+
+CServiceSearchVisitor::CServiceSearchVisitor()
+ {
+ }
+
+CServiceSearchVisitor::~CServiceSearchVisitor()
+ {
+// delete iSearchPattern;
+ delete iFoundIndexs;
+ delete iAdapter;
+ delete iParser;
+ }
+
+EXPORT_C CServiceSearchVisitor* CServiceSearchVisitor::NewLC(const CSdpSearchPattern& aPattern)
+ {
+ CServiceSearchVisitor* self = new(ELeave)CServiceSearchVisitor();
+ CleanupStack::PushL(self);
+ self->ConstructL(aPattern);
+ return self;
+ }
+
+EXPORT_C CServiceSearchVisitor* CServiceSearchVisitor::NewL(const CSdpSearchPattern& aPattern)
+ {
+ CServiceSearchVisitor* self = CServiceSearchVisitor::NewLC(aPattern);
+ CleanupStack::Pop();
+ return self;
+ }
+
+void CServiceSearchVisitor::ConstructL(const CSdpSearchPattern& aPattern)
+/** 2nd phase constructor. */
+ {
+ iSearchPattern = &aPattern;
+ iAdapter = new(ELeave) CEncodedVisitorAdapter(*this);
+ iParser = CElementParser::NewL(iAdapter);
+ }
+
+void CServiceSearchVisitor::SearchRecordL(CSdpServRecord& aRec)
+ {
+ if (iFoundIndexs)
+ {
+ delete iFoundIndexs;
+ iFoundIndexs = 0;
+ }
+ iFoundIndexs = CBitMapAllocator::NewL(iSearchPattern->Count());
+ for(TServAttrIter attrIter(aRec.AttributeIter()); attrIter; attrIter++)
+ {// Iterate thru attributes in record
+ (*attrIter).AcceptVisitorL(*this);
+ }
+ }
+
+EXPORT_C void CServiceSearchVisitor::SearchDbL(CSdpDatabase &aDb, const CSdpSearchPattern &aPattern, MServiceSearchHandler& aObserver)
+ {
+ __ASSERT_DEBUG(aPattern.Count() > 0, DbPanic(ESdpDbBadSearchPattern));
+// SDP_DEBUG(3, FPrint(_L("Searching SDP DB for pattern with %d entries\n"), aPattern.Count()));
+ CServiceSearchVisitor* theVisitor = CServiceSearchVisitor::NewLC(aPattern);
+
+ for(TServRecordIter recIter(aDb.RecordIter()); recIter; recIter++)
+ {// Iterate thru records in Db
+ TRAPD(err, theVisitor->SearchRecordL(*recIter));
+ if (err == KErrCompletion)
+ {// Found!
+// SDP_DEBUG(3, FPrint(_L("Match found in record 0x%x\n"), (*recIter).Handle()));
+ aObserver.RecordFoundL(*recIter);
+ }
+ else if(err != KErrNone)
+ {
+ User::Leave(err);
+ }
+ }
+ CleanupStack::PopAndDestroy();//theVisitor
+ }
+
+void CServiceSearchVisitor::VisitAttributeL(CSdpAttr &/*aAttribute*/)
+ {
+ }
+
+void CServiceSearchVisitor::VisitAttributeValueL(CSdpAttrValue &aValue, TSdpElementType aType)
+ {
+ switch (aType)
+ {
+ case ETypeUUID:
+ FoundUUIDL(aValue.UUID());
+ break;
+ case ETypeEncoded:
+ {
+// parse out any UUIDs in this encoded attribute
+// TInt rem;
+ iParser->Reset();
+ /*rem = */iParser->ParseElementsL(aValue.Des());
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+void CServiceSearchVisitor::StartListL(CSdpAttrValueList &/*aList*/)
+ {
+ }
+
+void CServiceSearchVisitor::EndListL()
+ {
+ }
+
+
+void CServiceSearchVisitor::FoundUUIDL(const TUUID& aUUID)
+ {
+ TInt pos;
+ if (iSearchPattern->Find(aUUID, pos)==0 &&
+ iFoundIndexs->IsFree(pos))
+ {
+ iFoundIndexs->AllocAt(pos);
+ if (iFoundIndexs->Avail() == 0)
+ {// We've found what we were searching for. Quick complete with a leave
+ User::Leave(KErrCompletion); //Hmmmm!!!
+ }
+ }
+ }