diff -r 000000000000 -r 29b1cd4cb562 bluetooth/btsdp/database/SDPDatabase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btsdp/database/SDPDatabase.cpp Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,302 @@ +// 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: +// + +#include +#include +#include +#include + +#include "SDPDatabase.h" +#include "DataEncoder.h" +#include "EncoderVisitor.h" + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, LOG_COMPONENT_SDPDATABASE); +#endif + +void Panic(TSdpDatabasePanics aCode) + { + User::Panic(KSdpDatabasePanicName, aCode); + } + +// Class CSdpDatabase + +EXPORT_C CSdpDatabase* CSdpDatabase::NewLC() +/** +Creates a CSdpDatabase object, but leaves on the cleanup stack. + +@return Pointer to the created CSdpDatabase object +*/ + { + LOG_STATIC_FUNC + CSdpDatabase* self = new(ELeave) CSdpDatabase; + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +EXPORT_C CSdpDatabase* CSdpDatabase::NewL() +/** +Creates a CSdpDatabase object.(Does NOT leave it on the cleanup stack.) + +@return Pointer to the created CSdpDatabase object +*/ + { + LOG_STATIC_FUNC + CSdpDatabase* self = CSdpDatabase::NewLC(); + CleanupStack::Pop(); + return self; + } + +CSdpDatabase::CSdpDatabase() +: iCanAddRecord(ETrue), + iRecords(CSdpServRecord::LinkOffset()), + iNextFreeHandle(KSdpMinServRecordHandle) + { + CONNECT_LOGGER + } + +void CSdpDatabase::ConstructL() + { + LOG_FUNC + } + +EXPORT_C CSdpDatabase::~CSdpDatabase() +/** Destructor +*/ + { + LOG_FUNC + // Delete all records on the record list + iRecords.ResetAndDestroy(); + CLOSE_LOGGER + } + +/** Adds a service record to this database. +@param aRecord The record being added +*/ +EXPORT_C void CSdpDatabase::AddRecord(CSdpServRecord* aRecord) + { + LOG_FUNC + iRecords.AddInOrder(*aRecord); //Panics if aRecord's handle is already bagged. + //Must do this AFTER adding latest record...hence need for 'iCanAddRecord' + iCanAddRecord = ReviseNextFreeHandle(); + } + +/** Creates a new record on this database +@leave KErrSdpDatabaseFull implies no more spare handles +*/ +EXPORT_C CSdpServRecord* CSdpDatabase::NewRecordL() + { + LOG_FUNC + // Add a new record only if we have spare handles... + // ...there are 2^32 - 0x10000 to choose from! + if(!iCanAddRecord) + { + User::Leave(KErrSdpDatabaseFull); + } + + CSdpServRecord* record = CSdpServRecord::NewL(); + CleanupStack::PushL(record); + + record + ->BuildUintL(TSdpIntBuf(0)) + ->BuildUintL(TSdpIntBuf(NextFreeHandle())); + + AddRecord(record); + CleanupStack::Pop(); //record + return record; + } + +/** Encodes complete database. */ +EXPORT_C void CSdpDatabase::EncodeDbL() + { + LOG_FUNC + for(TServRecordIter recIter(RecordIter()); recIter; recIter++) + {// Iterate through records in Db + for (TServAttrIter attrIter((*recIter).AttributeIter()); attrIter; attrIter++) + {// iterate through attributes in record + CSdpAttr* theAttr = &(*attrIter); + CSdpAttrValue* theAttrValue = &(theAttr->Value()); + TUint size = TElementEncoder::EncodedSize(theAttrValue->Type(), + theAttrValue->DataSize()); + + HBufC8* outbuf = HBufC8::NewLC(size); + TPtr8 writePtr = outbuf->Des(); + TElementEncoder theEncoder(writePtr); + CAttrEncoderVisitor::EncodeAttributeL(theEncoder, (*attrIter).Value()); + theAttr->BuildEncodedL(writePtr); + CleanupStack::PopAndDestroy(); //outbuf + } + } + } + +/** Dead function. Space filler for .def file (left in for BC) +*/ +EXPORT_C void CSdpDatabase::ParseDbL_Obscelete_DoesNothing() + { + LOG_FUNC + return; + } + +/** Returns the 'TSdpServRecordHandle' iNextFreeHandle. +@return the next free handle +*/ +EXPORT_C TSdpServRecordHandle CSdpDatabase::NextFreeHandle() + { + LOG_FUNC + return iNextFreeHandle; + } + +/** Finds a handle not used by any record in database. + Starts at current next free handle value, and discovers if + it is used by a record in the database. If so cycles it on one in + in the allowed range, and checks again. This algorithm continues + until an unused handle is found (=>return ETrue) or all handles + have been checked and are found to be in use. (=>return EFalse) + NB. We start by looking for the next available handle going upwards + in value. Only if none are found do we return to the lower limit and + search for "holes" below the last claimed handle. This should + reduce processing time. We could have gone further and incremented + iNextFreeHandle value before doing anything else, because it is likely + that the current iNextFreeHandle will have just been used when this + function is called +*/ +TBool CSdpDatabase::ReviseNextFreeHandle() + { + LOG_FUNC + if(iNextFreeHandle>KSdpMaxServRecordHandle|| + iNextFreeHandleKSdpMaxServRecordHandle) + iNextFreeHandle = KSdpMinServRecordHandle; + //We've run out of handles + if(iNextFreeHandle==origNextFreeHandle) + return EFalse; + //Run through all records again to check for new incremented handle. + recIter.SetToFirst(); + } + } + return ETrue; + } + + +EXPORT_C CAttrUuidVisitor* CAttrUuidVisitor::NewL() + { + LOG_STATIC_FUNC + CAttrUuidVisitor* self = new(ELeave)CAttrUuidVisitor(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +EXPORT_C CAttrUuidVisitor::~CAttrUuidVisitor() + { + LOG_FUNC + iUuidContainer.Close(); + } + +EXPORT_C RUUIDContainer& CAttrUuidVisitor::GetUuids() + { + LOG_FUNC + return iUuidContainer; + } + +void CAttrUuidVisitor::EncodeAttributeL(CSdpAttrValue& /*aSrcAttr*/) + { + LOG_FUNC + __ASSERT_DEBUG(ETrue, User::Panic(_L("EncodeAttributeL() erroneously called"), KErrArgument)); + } + +CAttrUuidVisitor::CAttrUuidVisitor() + { + LOG_FUNC + iUuidContainer.Reset(); + } + +void CAttrUuidVisitor::ConstructL() + { + LOG_FUNC + } + +// Implementation of MAttributeVisitor interface +void CAttrUuidVisitor::VisitAttributeL(CSdpAttr& /*aAttribute*/) + { + LOG_FUNC + __ASSERT_DEBUG(ETrue, Panic(ESdpDatabaseVisitAttributeLErroneouslyCalled)); + } + +void CAttrUuidVisitor::VisitAttributeValueL(CSdpAttrValue &aValue, TSdpElementType aType) + { + LOG_FUNC + switch (aType) + { + case ETypeUUID: + iUuidContainer.Add(aValue.UUID()); + break; + case ETypeEncoded: + { + TPtrC8 ptr = aValue.Des(); + if(ptr.Length() == KSdpElemHdrTypeShift + KSizeOf16BitUUID) + { + // 16-bit UUID + TUUID uuid = TUUID(BigEndian::Get16(&ptr[KSdpElemHdrTypeShift])); + iUuidContainer.Add(uuid); + } + else if(ptr.Length() == KSdpElemHdrTypeShift + KSizeOf32BitUUID) + { + // 32-bit UUID + TUUID uuid = TUUID(BigEndian::Get32(&ptr[KSdpElemHdrTypeShift])); + iUuidContainer.Add(uuid); + } + else if(ptr.Length() == KSdpElemHdrTypeShift + KSizeOf128BitUUID) + { + // 128-bit UUID + TUUID uuid = TUUID(BigEndian::Get32(&ptr[KSdpElemHdrTypeShift]), + BigEndian::Get32(&ptr[KSdpElemHdrTypeShift+sizeof(TUint32)]), + BigEndian::Get32(&ptr[KSdpElemHdrTypeShift+2*sizeof(TUint32)]), + BigEndian::Get32(&ptr[KSdpElemHdrTypeShift+3*sizeof(TUint32)])); + iUuidContainer.Add(uuid); + } + else + { + // We don't support other UUIDs + } + } + break; + default: + __ASSERT_DEBUG(ETrue, Panic(ESdpDatabaseUnexpectedAttributeType)); + break; + } + } + +void CAttrUuidVisitor::StartListL(CSdpAttrValueList& /*aList*/) + { + LOG_FUNC + } + +void CAttrUuidVisitor::EndListL() + { + LOG_FUNC + } +