--- a/smsprotocols/smsstack/test/smspdudb.cpp Mon May 03 13:37:20 2010 +0300
+++ b/smsprotocols/smsstack/test/smspdudb.cpp Thu May 06 15:10:38 2010 +0100
@@ -1,660 +1,660 @@
-// Copyright (c) 2003-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 "smspdudb.h"
-#include <testconfigfileparser.h>
-#include "Gsmumsg.h"
-#include "gsmubuf.h"
-
-const TInt KSmsPduDbMaxReadWriteChunk = 0x200;
-
-EXPORT_C CSmsPduDatabase* CSmsPduDatabase::NewL(RFs& aFs)
-/**
- * CSmsPduDatabase default factory function
- *
- * Calls the other overload of NewL with the default section, filename and component.
- */
- {
- return NewL(aFs, KSmsPduDbDefaultSection, KSmsPduDbDefaultFilename, KSmsPduDbDefaultComponent);
- }
-
-EXPORT_C CSmsPduDatabase* CSmsPduDatabase::NewL(RFs& aFs, const TDesC8& aSection, const TDesC& aFileName, const TDesC& aComponent)
- {
- CSmsPduDatabase* self = new (ELeave) CSmsPduDatabase(aFs);
- CleanupStack::PushL(self);
-
- //Construct iConfigFile and set iSection to aSection
- CTestConfig* testConfig = CTestConfig::NewLC(aFs, aComponent, aFileName);
- CleanupStack::Pop(testConfig);
-
- self->iConfigFile = testConfig;
- self->SetSectionL(aSection);
-
- CleanupStack::Pop(self);
- return self;
- }
-
-EXPORT_C CSmsPduDatabase* CSmsPduDatabase::NewL(RFs& aFs, const CTestConfigSection& aSection)
-/**
- * Constructs a CSmsPduDatabase and sets iSection to aSection.
- * @note iConfigFile is not constructed and should remain NULL
- */
- {
- CSmsPduDatabase* self = new (ELeave) CSmsPduDatabase(aFs);
- self->SetSection(aSection);
- return self;
- }
-
-EXPORT_C CSmsPduDatabase::~CSmsPduDatabase()
- {
- delete iConfigFile;
- // @note Don't delete iSection because it is either owned by iConfigFile or by another config file
- }
-
-TPtrC8 CSmsPduDatabase::GetTypeL(CSmsPDU::TSmsPDUType aType) const
- {
- TPtrC8 type;
-
- switch (aType)
- {
- case CSmsPDU::ESmsSubmit:
-
- type.Set(KSmsPduDbSubmit);
- break;
-
- case CSmsPDU::ESmsDeliver:
-
- type.Set(KSmsPduDbDeliver);
- break;
-
- case CSmsPDU::ESmsCommand:
-
- type.Set(KSmsPduDbCommand);
- break;
-
- case CSmsPDU::ESmsStatusReport:
-
- type.Set(KSmsPduDbStatusReport);
- break;
-
- case CSmsPDU::ESmsSubmitReport:
-
- type.Set(KSmsPduDbSubmitReport);
- break;
-
- case CSmsPDU::ESmsDeliverReport:
-
- type.Set(KSmsPduDbDeliverReport);
- break;
-
- default:
-
- User::Leave(KErrNotSupported);
- break;
- }
-
- return type;
- }
-
-TPtrC8 CSmsPduDatabase::GetConcatTypeL(CSmsPDU::TSmsPDUType aType) const
- {
- TPtrC8 type;
-
- switch (aType)
- {
- case CSmsPDU::ESmsSubmit:
-
- type.Set(KSmsPduDbSubmitConcat);
- break;
-
- case CSmsPDU::ESmsDeliver:
-
- type.Set(KSmsPduDbDeliverConcat);
- break;
-
- default:
-
- User::Leave(KErrNotSupported);
- break;
- }
-
- return type;
- }
-
-
-EXPORT_C CSmsPduDbPdu* CSmsPduDatabase::GetPduLC(CSmsPDU::TSmsPDUType aType, TInt aId) const
- {
- const TPtrC8 type(GetTypeL(aType));
- RSmsPduDbIdArray array(type);
- CleanupClosePushL(array);
- GetIdsL(array, aId);
-
- const CTestConfigItem& item = *array[0].iItem;
-
- CSmsPduDbPdu* pdu = CSmsPduDbPdu::NewL(iFs, item, aType);
- CleanupStack::PopAndDestroy(&array);
- CleanupStack::PushL(pdu);
- return pdu;
- }
-
-EXPORT_C void CSmsPduDatabase::GetPduL(RPointerArray<CSmsPduDbPdu>& aArray, CSmsPDU::TSmsPDUType aType) const
- {
- const TPtrC8 type(GetTypeL(aType));
- RSmsPduDbIdArray array(type);
- CleanupClosePushL(array);
-
- GetIdsL(array);
- const TInt count = array.Count();
-
- for (TInt i = 0; i < count; i++)
- {
- CSmsPduDbPdu* pdu = CSmsPduDbPdu::NewL(iFs, *array[i].iItem, aType);
- CleanupStack::PushL(pdu);
- User::LeaveIfError(aArray.Append(pdu));
- CleanupStack::Pop(pdu);
- }
-
- CleanupStack::PopAndDestroy(&array);
- }
-
-EXPORT_C CSmsPduDbConcatSegment* CSmsPduDatabase::GetConcatSegmentLC(CSmsPDU::TSmsPDUType aType, TInt aId, TInt aSegment) const
- {
- const TPtrC8 type(GetConcatTypeL(aType));
- RSmsPduDbIdArray array(type, ETrue);
- CleanupClosePushL(array);
- GetIdsL(array, aId);
-
- CSmsPduDbConcatSegment* concat = GetConcatSegmentL(array, aType, aId, aSegment);
-
- CleanupStack::PopAndDestroy(&array);
- CleanupStack::PushL(concat);
- return concat;
- }
-
-CSmsPduDbConcatSegment* CSmsPduDatabase::GetConcatSegmentL(const RSmsPduDbIdArray& aIdArray, CSmsPDU::TSmsPDUType aType, TInt aId, TInt aSegment) const
- {
- const TInt count = aIdArray.Count();
- CSmsPduDbConcatSegment* concat = NULL;
-
- for (TInt i = 0; i < count; i++) //order important
- {
- const TSmsPduDbId& id = aIdArray[i];
-
- if (id.iId == aId)
- {
- const TDesC8& val = id.iItem->Value();
- TInt segment = KErrNotFound;
- const TInt err = CTestConfig::GetElement(val, KSmsPduDbDelimiter, CSmsPduDbConcatSegment::EConcatSegment, segment);
-
- if (err == KErrNone && segment == aSegment)
- {
- concat = CSmsPduDbConcatSegment::NewL(iFs, *id.iItem, aType);
- break;
- }
- }
- }
-
- if (concat == NULL)
- User::Leave(KErrNotFound);
-
- return concat;
- }
-
-EXPORT_C CSmsPduDbConcat* CSmsPduDatabase::GetConcatLC(CSmsPDU::TSmsPDUType aType, TInt aId) const
- {
- const TPtrC8 type(GetConcatTypeL(aType));
- RSmsPduDbIdArray array(type, ETrue);
- CleanupClosePushL(array);
- GetIdsL(array, aId);
-
- CSmsPduDbConcat* concat = new (ELeave) CSmsPduDbConcat();
- CleanupStack::PushL(concat);
-
- const TInt count = array.Count();
-
- for (TInt i=0; i<count; i++)
- {
- const TSmsPduDbId& id = array[i];
- CSmsPduDbConcatSegment* concatSegment = CSmsPduDbConcatSegment::NewL(iFs, *id.iItem, aType);
- CleanupStack::PushL(concatSegment);
- User::LeaveIfError(concat->iSegments.Append(concatSegment));
- }
-
- concat->DecodeL(iFs);
-
- CleanupStack::PopAndDestroy(&array);
- return concat;
- }
-
-EXPORT_C void CSmsPduDatabase::GetConcatL(RPointerArray<CSmsPduDbConcat>& aArray, CSmsPDU::TSmsPDUType aType) const
- {
- const TPtrC8 type(GetConcatTypeL(aType));
- RSmsPduDbIdArray array(type, ETrue);
- CleanupClosePushL(array);
- GetIdsL(array);
-
- const TInt count = array.Count();
- TInt lastId = KErrNotFound;
- CSmsPduDbConcat* concat = NULL;
-
- for (TInt i=0; i<count; i++)
- {
- const CTestConfigItem& item = *array[i].iItem;
- const TInt id = array[i].iId;
-
- if (id != lastId || concat == NULL)
- {
- if (concat != NULL)
- concat->DecodeL(iFs);
-
- concat = new (ELeave) CSmsPduDbConcat();
- CleanupStack::PushL(concat);
- User::LeaveIfError(aArray.Append(concat));
- CleanupStack::Pop(concat);
- lastId = id;
- }
-
- CSmsPduDbConcatSegment* segment = CSmsPduDbConcatSegment::NewL(iFs, item, aType);
- CleanupStack::PushL(segment);
- User::LeaveIfError(concat->iSegments.Append(segment));
- CleanupStack::Pop(segment);
- }
-
- if (concat != NULL)
- concat->DecodeL(iFs);
-
- CleanupStack::PopAndDestroy(&array);
- }
-
-EXPORT_C CSmsPduDbMessage* CSmsPduDatabase::GetMessageLC(CSmsPDU::TSmsPDUType aType, TInt aId) const
- {
- RSmsPduDbIdArray array(KSmsPduDbMessage);
- CleanupClosePushL(array);
- GetIdsL(array, aId);
-
- const CTestConfigItem& item = *array[0].iItem;
- CSmsPduDbMessage* pdu = CSmsPduDbMessage::NewL(iFs, item, aType);
- CleanupStack::PushL(pdu);
-
-
- CleanupStack::PopAndDestroy(&array);
- return pdu;
- }
-
-EXPORT_C void CSmsPduDatabase::GetMessageL(RPointerArray<CSmsPduDbMessage>& aArray, CSmsPDU::TSmsPDUType aType) const
- {
- RSmsPduDbIdArray array(KSmsPduDbMessage);
- CleanupClosePushL(array);
- GetIdsL(array);
-
- const TInt count = array.Count();
-
- for (TInt i=0; i<count; i++)
- {
- const CTestConfigItem& item = *array[i].iItem;
- CSmsPduDbMessage* pdu = CSmsPduDbMessage::NewL(iFs, item, aType);
- CleanupStack::PushL(pdu);
- User::LeaveIfError(aArray.Append(pdu));
- CleanupStack::Pop(pdu);
- }
-
- CleanupStack::PopAndDestroy(&array);
- }
-
-CSmsPduDatabase::CSmsPduDatabase(RFs& aFs)
-: iFs(aFs)
- {
- }
-
-void CSmsPduDatabase::GetIdsL(RSmsPduDbIdArray& aIds) const
- {
- RPointerArray<const CTestConfigItem> array;
- CleanupClosePushL(array);
-
- iSection->ItemsL(array, aIds.Type());
-
- const TInt count = array.Count();
-
- for (TInt i=0; i<count; i++)
- {
- TSmsPduDbId item(array[i]);
- const TInt err = CTestConfig::GetElement(item.iItem->Value(), KSmsPduDbDelimiter, CSmsPduDbBase::ESmsPduDbId, item.iId);
- if (err == KErrNone)
- {
- aIds.InsertL(item);
- }
- }
-
- CleanupStack::PopAndDestroy(&array);
- }
-
-void CSmsPduDatabase::GetIdsL(RSmsPduDbIdArray& aIds, TInt aId) const
- {
- RSmsPduDbIdArray tempArray(aIds.Type(), ETrue);
- CleanupClosePushL(tempArray);
-
- GetIdsL(tempArray);
-
- TInt find = KErrNotFound;
-
- while ((find = tempArray.Find(aId)) != KErrNotFound)
- {
- User::LeaveIfError(aIds.Append(tempArray[find]));
- tempArray.Remove(find);
- }
-
- CleanupStack::PopAndDestroy(&tempArray);
- if (aIds.Count() == 0)
- User::Leave(KErrNotFound);
- }
-
-void CSmsPduDatabase::ReadFileL(const TDesC& aInputFileName, const TDesC& aInputComponent, CBufFlat& aData) const
- {
- TParse parse;
- User::LeaveIfError(CTestConfig::ResolveFile(iFs, aInputComponent, aInputFileName, parse));
-
- RFile file;
- User::LeaveIfError(file.Open(iFs, parse.FullName(), EFileRead));
- CleanupClosePushL(file);
-
- TInt size(0);
- User::LeaveIfError(file.Size(size));
-
- for (TInt i = 0; i < size; i += KSmsPduDbMaxReadWriteChunk)
- {
- const TInt readSize = Min(KSmsPduDbMaxReadWriteChunk, size - i);
- TBuf8<KSmsPduDbMaxReadWriteChunk> read;
- User::LeaveIfError(file.Read(read, readSize));
- const TInt pos = aData.Size();
- aData.InsertL(pos, read);
- }
-
- CleanupStack::PopAndDestroy(&file);
- }
-
-void CSmsPduDatabase::WriteFileL(const TDesC& aOutputFileName, const CBufFlat& aData) const
- {
- RFile file;
- User::LeaveIfError(file.Replace(iFs, aOutputFileName, EFileWrite));
- CleanupClosePushL(file);
-
- const TInt size = aData.Size();
-
- for (TInt i = 0; i < size; i += KSmsPduDbMaxReadWriteChunk)
- {
- const TInt readSize = Min(KSmsPduDbMaxReadWriteChunk, size - i);
- TBuf8<KSmsPduDbMaxReadWriteChunk> read;
- aData.Read(i, read, readSize);
- User::LeaveIfError(file.Write(read));
- }
-
- User::LeaveIfError(file.Flush());
-
- CleanupStack::PopAndDestroy(&file);
- }
-
-EXPORT_C void CSmsPduDatabase::RewriteFileL(const TDesC& aInputFileName, const TDesC& aInputComponent, const TDesC& aOutputFileName) const
- {
- CBufFlat* buffer = CBufFlat::NewL(0x100); //< TODO Remove this magic number
- CleanupStack::PushL(buffer);
-
- ReadFileL(aInputFileName, aInputComponent, *buffer);
-
- ParseFileL(*buffer);
-
- WriteFileL(aOutputFileName, *buffer);
-
- CleanupStack::PopAndDestroy(buffer);
- }
-
-void CSmsPduDatabase::ParseFileL(CBufFlat& aData) const
- {
- TPtrC8 ptr(aData.Ptr(0));
- TLex8 lex(ptr);
- lex.Mark();
-
- while (!lex.Eos())
- {
- if (lex.Peek() == KSmsPduDbTagStart)
- {
- ParseTagL(aData, ptr, lex);
- }
- else
- {
- lex.Inc();
- }
- }
- }
-
-void CSmsPduDatabase::ParseTagL(CBufFlat& aData, TPtrC8& aPtr, TLex8& aLex) const
- {
- const TInt startingPos = aLex.Offset();
-
- const TPtrC8 remainder(aLex.Remainder());
- const TInt locate = remainder.Locate(KSmsPduDbTagEnd);
- TInt err = locate;
-
- if (locate != KErrNotFound)
- {
- aLex.Mark();
- aLex.Inc(locate+1);
-
- const TPtrC8 marked(aLex.MarkedToken());
- CSmsPduDbPdu* pdu = NULL;
-
- TRAP(err, pdu = PduFactoryL(marked));
-
- if (err == KErrNone)
- {
- CleanupStack::PushL(pdu);
- TBuf8<RMobileSmsMessaging::KGsmTpduSize*2> hexPdu;
- pdu->GetHexPdu(hexPdu);
- aData.Delete(startingPos, marked.Length());
- aData.InsertL(startingPos, hexPdu);
- aPtr.Set(aData.Ptr(0));
- aLex = aPtr;
- aLex.Inc(startingPos + pdu->iPdu.Length());
- CleanupStack::PopAndDestroy(pdu);
- }
- }
-
- if (err != KErrNone)
- {
- aLex.Inc();
- }
- }
-
-TBool CSmsPduDatabase::IsPdu(const TDesC8& aTag, CSmsPDU::TSmsPDUType& aType) const
- {
- TBool ret = EFalse;
-
- if (aTag.CompareF(KSmsPduDbSubmit) == KErrNone)
- {
- ret = ETrue;
- aType = CSmsPDU::ESmsSubmit;
- }
- else if (aTag.CompareF(KSmsPduDbDeliver) == KErrNone)
- {
- ret = ETrue;
- aType = CSmsPDU::ESmsDeliver;
- }
- else if (aTag.CompareF(KSmsPduDbStatusReport) == KErrNone)
- {
- ret = ETrue;
- aType = CSmsPDU::ESmsStatusReport;
- }
- else if (aTag.CompareF(KSmsPduDbCommand) == KErrNone)
- {
- ret = ETrue;
- aType = CSmsPDU::ESmsCommand;
- }
- else if (aTag.CompareF(KSmsPduDbSubmitReport) == KErrNone)
- {
- ret = ETrue;
- aType = CSmsPDU::ESmsSubmitReport;
- }
- else if (aTag.CompareF(KSmsPduDbDeliverReport) == KErrNone)
- {
- ret = ETrue;
- aType = CSmsPDU::ESmsDeliverReport;
- }
-
- return ret;
- }
-
-TBool CSmsPduDatabase::IsConcatSegment(const TDesC8& aTag, CSmsPDU::TSmsPDUType& aType) const
- {
- TBool ret = EFalse;
-
- if (aTag.CompareF(KSmsPduDbSubmitConcat) == KErrNone)
- {
- ret = ETrue;
- aType = CSmsPDU::ESmsSubmit;
- }
- else if (aTag.CompareF(KSmsPduDbDeliverConcat) == KErrNone)
- {
- ret = ETrue;
- aType = CSmsPDU::ESmsDeliver;
- }
-
- return ret;
- }
-
-EXPORT_C CSmsPduDbPdu* CSmsPduDatabase::PduFactoryL(const CTestConfigItem& aItem, CSmsPDU::TSmsPDUType aTypeForMessageTags) const
- {
- const TDesC8& type = aItem.Item();
- CSmsPduDbPdu* pdu = NULL;
- CSmsPDU::TSmsPDUType pduType;
-
- if (IsPdu(type, pduType))
- {
- pdu = CSmsPduDbPdu::NewL(iFs, aItem, pduType);
- }
- else if (IsConcatSegment(type, pduType))
- {
- pdu = CSmsPduDbConcatSegment::NewL(iFs, aItem, pduType);
- }
- else if (IsMessage(type))
- {
- pdu = CSmsPduDbMessage::NewL(iFs, aItem, aTypeForMessageTags);
- }
- else
- {
- //Attempt to parse aItem.Value() using the other overload of PduFactoryL()
- pdu = PduFactoryL(aItem.Value(), aTypeForMessageTags);
- }
-
- __ASSERT_DEBUG(pdu != NULL, PduDbPanic(EPduDbPanicPduNotConstructed));
- return pdu;
- }
-
-EXPORT_C CSmsPduDbPdu* CSmsPduDatabase::PduFactoryL(const TDesC8& aTag, CSmsPDU::TSmsPDUType aTypeForMessageTags) const
-/**
- * Parses tags of the form <MESSAGE_TYPE; ID; {SEGMENT}>, e.g. <SUBMIT,21> or <MESSAGE,2> or <SUBMITCONCAT; 32; 2>
- * If the MESSAGE_TYPE and ID combination if found in the PDU database then a CSmsPduDbPdu-derived object is created.
- * SEGMENT is only compulsory if MESSAGE_TYPE is a concatenated message.
- *
- * @param aTag Tag of the form <MESSAGE_TYPE; ID; {SEGMENT}>. MESSAGE_TYPE and ID are compulsory and must be delimited by a semicolon (;)
- * @param aTypeForMessageTags PDU Type used when creating a CSmsPduDbMessage. This occurs if MESSAGE_TYPE == "message"
- */
- {
- TPtrC8 tag(CTestConfig::Trim(aTag));
- const TInt len = tag.Length();
-
- if (len < 4)
- User::Leave(KErrBadName);
-
- TInt midStart = 0;
- TInt midLen = len;
- if (tag[0] == KSmsPduDbTagStart)
- {
- midStart++;
- midLen--;
- }
-
- if (tag[len-1] == KSmsPduDbTagEnd)
- midLen--;
-
- tag.Set(tag.Mid(midStart, midLen));
-
- TPtrC8 type;
- TInt id(0);
-
- User::LeaveIfError(CTestConfig::GetElement(tag, KSmsPduDbTagDelimitier, ETagType, type));
- User::LeaveIfError(CTestConfig::GetElement(tag, KSmsPduDbTagDelimitier, ETagId, id));
-
- CSmsPduDbPdu* pdu = NULL;
- CSmsPDU::TSmsPDUType pduType;
-
- if (IsPdu(type, pduType))
- {
- pdu = GetPduLC(pduType, id);
- }
- else if (IsConcatSegment(type, pduType))
- {
- TInt segment;
- User::LeaveIfError(CTestConfig::GetElement(tag, KSmsPduDbTagDelimitier, ETagSegment, segment));
- pdu = GetConcatSegmentLC(pduType, id, segment);
- }
- else if (IsMessage(type))
- {
- pdu = GetMessageLC(aTypeForMessageTags, id);
- }
- else
- {
- User::Leave(KErrBadName);
- }
-
- __ASSERT_DEBUG(pdu != NULL, PduDbPanic(EPduDbPanicPduNotConstructed));
- CleanupStack::Pop(pdu);
- return pdu;
- }
-
-EXPORT_C CSmsPduDbPdu* CSmsPduDatabase::PduFactory(const TDesC8& aTag, CSmsPDU::TSmsPDUType aTypeForMessageTags) const
- {
- CSmsPduDbPdu* pdu = NULL;
- TRAPD(err, (pdu = PduFactoryL(aTag, aTypeForMessageTags)));
- return ((err == KErrNone) ? pdu : NULL);
- }
-
-EXPORT_C CSmsPduDbPdu* CSmsPduDatabase::PduFactory(const CTestConfigItem& aItem, CSmsPDU::TSmsPDUType aTypeForMessageTags) const
- {
- CSmsPduDbPdu* pdu = NULL;
- TRAPD(err, (pdu = PduFactoryL(aItem, aTypeForMessageTags)));
- return ((err == KErrNone) ? pdu : NULL);
- }
-
-TInt CSmsPduDatabase::RSmsPduDbIdArray::Compare(const TSmsPduDbId& aLeft, const TSmsPduDbId& aRight)
- {
- return aLeft.iId - aRight.iId;
- }
-
-TInt CSmsPduDatabase::RSmsPduDbIdArray::Find(TInt aId) const
- {
- TLinearOrder<TSmsPduDbId> order(Compare);
- const TSmsPduDbId tempId(NULL, aId);
- return FindInOrder(tempId, order);
- }
-
-void CSmsPduDatabase::RSmsPduDbIdArray::InsertL(const TSmsPduDbId& aId)
- {
- TLinearOrder<TSmsPduDbId> order(Compare);
-
- if (iAllowDuplicates)
- User::LeaveIfError(InsertInOrderAllowRepeats(aId, order));
- else
- User::LeaveIfError(InsertInOrder(aId, order));
- }
+// Copyright (c) 2003-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 "smspdudb.h"
+#include <testconfigfileparser.h>
+#include "Gsmumsg.h"
+#include "gsmubuf.h"
+
+const TInt KSmsPduDbMaxReadWriteChunk = 0x200;
+
+EXPORT_C CSmsPduDatabase* CSmsPduDatabase::NewL(RFs& aFs)
+/**
+ * CSmsPduDatabase default factory function
+ *
+ * Calls the other overload of NewL with the default section, filename and component.
+ */
+ {
+ return NewL(aFs, KSmsPduDbDefaultSection, KSmsPduDbDefaultFilename, KSmsPduDbDefaultComponent);
+ }
+
+EXPORT_C CSmsPduDatabase* CSmsPduDatabase::NewL(RFs& aFs, const TDesC8& aSection, const TDesC& aFileName, const TDesC& aComponent)
+ {
+ CSmsPduDatabase* self = new (ELeave) CSmsPduDatabase(aFs);
+ CleanupStack::PushL(self);
+
+ //Construct iConfigFile and set iSection to aSection
+ CTestConfig* testConfig = CTestConfig::NewLC(aFs, aComponent, aFileName);
+ CleanupStack::Pop(testConfig);
+
+ self->iConfigFile = testConfig;
+ self->SetSectionL(aSection);
+
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+EXPORT_C CSmsPduDatabase* CSmsPduDatabase::NewL(RFs& aFs, const CTestConfigSection& aSection)
+/**
+ * Constructs a CSmsPduDatabase and sets iSection to aSection.
+ * @note iConfigFile is not constructed and should remain NULL
+ */
+ {
+ CSmsPduDatabase* self = new (ELeave) CSmsPduDatabase(aFs);
+ self->SetSection(aSection);
+ return self;
+ }
+
+EXPORT_C CSmsPduDatabase::~CSmsPduDatabase()
+ {
+ delete iConfigFile;
+ // @note Don't delete iSection because it is either owned by iConfigFile or by another config file
+ }
+
+TPtrC8 CSmsPduDatabase::GetTypeL(CSmsPDU::TSmsPDUType aType) const
+ {
+ TPtrC8 type;
+
+ switch (aType)
+ {
+ case CSmsPDU::ESmsSubmit:
+
+ type.Set(KSmsPduDbSubmit);
+ break;
+
+ case CSmsPDU::ESmsDeliver:
+
+ type.Set(KSmsPduDbDeliver);
+ break;
+
+ case CSmsPDU::ESmsCommand:
+
+ type.Set(KSmsPduDbCommand);
+ break;
+
+ case CSmsPDU::ESmsStatusReport:
+
+ type.Set(KSmsPduDbStatusReport);
+ break;
+
+ case CSmsPDU::ESmsSubmitReport:
+
+ type.Set(KSmsPduDbSubmitReport);
+ break;
+
+ case CSmsPDU::ESmsDeliverReport:
+
+ type.Set(KSmsPduDbDeliverReport);
+ break;
+
+ default:
+
+ User::Leave(KErrNotSupported);
+ break;
+ }
+
+ return type;
+ }
+
+TPtrC8 CSmsPduDatabase::GetConcatTypeL(CSmsPDU::TSmsPDUType aType) const
+ {
+ TPtrC8 type;
+
+ switch (aType)
+ {
+ case CSmsPDU::ESmsSubmit:
+
+ type.Set(KSmsPduDbSubmitConcat);
+ break;
+
+ case CSmsPDU::ESmsDeliver:
+
+ type.Set(KSmsPduDbDeliverConcat);
+ break;
+
+ default:
+
+ User::Leave(KErrNotSupported);
+ break;
+ }
+
+ return type;
+ }
+
+
+EXPORT_C CSmsPduDbPdu* CSmsPduDatabase::GetPduLC(CSmsPDU::TSmsPDUType aType, TInt aId) const
+ {
+ const TPtrC8 type(GetTypeL(aType));
+ RSmsPduDbIdArray array(type);
+ CleanupClosePushL(array);
+ GetIdsL(array, aId);
+
+ const CTestConfigItem& item = *array[0].iItem;
+
+ CSmsPduDbPdu* pdu = CSmsPduDbPdu::NewL(iFs, item, aType);
+ CleanupStack::PopAndDestroy(&array);
+ CleanupStack::PushL(pdu);
+ return pdu;
+ }
+
+EXPORT_C void CSmsPduDatabase::GetPduL(RPointerArray<CSmsPduDbPdu>& aArray, CSmsPDU::TSmsPDUType aType) const
+ {
+ const TPtrC8 type(GetTypeL(aType));
+ RSmsPduDbIdArray array(type);
+ CleanupClosePushL(array);
+
+ GetIdsL(array);
+ const TInt count = array.Count();
+
+ for (TInt i = 0; i < count; i++)
+ {
+ CSmsPduDbPdu* pdu = CSmsPduDbPdu::NewL(iFs, *array[i].iItem, aType);
+ CleanupStack::PushL(pdu);
+ User::LeaveIfError(aArray.Append(pdu));
+ CleanupStack::Pop(pdu);
+ }
+
+ CleanupStack::PopAndDestroy(&array);
+ }
+
+EXPORT_C CSmsPduDbConcatSegment* CSmsPduDatabase::GetConcatSegmentLC(CSmsPDU::TSmsPDUType aType, TInt aId, TInt aSegment) const
+ {
+ const TPtrC8 type(GetConcatTypeL(aType));
+ RSmsPduDbIdArray array(type, ETrue);
+ CleanupClosePushL(array);
+ GetIdsL(array, aId);
+
+ CSmsPduDbConcatSegment* concat = GetConcatSegmentL(array, aType, aId, aSegment);
+
+ CleanupStack::PopAndDestroy(&array);
+ CleanupStack::PushL(concat);
+ return concat;
+ }
+
+CSmsPduDbConcatSegment* CSmsPduDatabase::GetConcatSegmentL(const RSmsPduDbIdArray& aIdArray, CSmsPDU::TSmsPDUType aType, TInt aId, TInt aSegment) const
+ {
+ const TInt count = aIdArray.Count();
+ CSmsPduDbConcatSegment* concat = NULL;
+
+ for (TInt i = 0; i < count; i++) //order important
+ {
+ const TSmsPduDbId& id = aIdArray[i];
+
+ if (id.iId == aId)
+ {
+ const TDesC8& val = id.iItem->Value();
+ TInt segment = KErrNotFound;
+ const TInt err = CTestConfig::GetElement(val, KSmsPduDbDelimiter, CSmsPduDbConcatSegment::EConcatSegment, segment);
+
+ if (err == KErrNone && segment == aSegment)
+ {
+ concat = CSmsPduDbConcatSegment::NewL(iFs, *id.iItem, aType);
+ break;
+ }
+ }
+ }
+
+ if (concat == NULL)
+ User::Leave(KErrNotFound);
+
+ return concat;
+ }
+
+EXPORT_C CSmsPduDbConcat* CSmsPduDatabase::GetConcatLC(CSmsPDU::TSmsPDUType aType, TInt aId) const
+ {
+ const TPtrC8 type(GetConcatTypeL(aType));
+ RSmsPduDbIdArray array(type, ETrue);
+ CleanupClosePushL(array);
+ GetIdsL(array, aId);
+
+ CSmsPduDbConcat* concat = new (ELeave) CSmsPduDbConcat();
+ CleanupStack::PushL(concat);
+
+ const TInt count = array.Count();
+
+ for (TInt i=0; i<count; i++)
+ {
+ const TSmsPduDbId& id = array[i];
+ CSmsPduDbConcatSegment* concatSegment = CSmsPduDbConcatSegment::NewL(iFs, *id.iItem, aType);
+ CleanupStack::PushL(concatSegment);
+ User::LeaveIfError(concat->iSegments.Append(concatSegment));
+ }
+
+ concat->DecodeL(iFs);
+
+ CleanupStack::PopAndDestroy(&array);
+ return concat;
+ }
+
+EXPORT_C void CSmsPduDatabase::GetConcatL(RPointerArray<CSmsPduDbConcat>& aArray, CSmsPDU::TSmsPDUType aType) const
+ {
+ const TPtrC8 type(GetConcatTypeL(aType));
+ RSmsPduDbIdArray array(type, ETrue);
+ CleanupClosePushL(array);
+ GetIdsL(array);
+
+ const TInt count = array.Count();
+ TInt lastId = KErrNotFound;
+ CSmsPduDbConcat* concat = NULL;
+
+ for (TInt i=0; i<count; i++)
+ {
+ const CTestConfigItem& item = *array[i].iItem;
+ const TInt id = array[i].iId;
+
+ if (id != lastId || concat == NULL)
+ {
+ if (concat != NULL)
+ concat->DecodeL(iFs);
+
+ concat = new (ELeave) CSmsPduDbConcat();
+ CleanupStack::PushL(concat);
+ User::LeaveIfError(aArray.Append(concat));
+ CleanupStack::Pop(concat);
+ lastId = id;
+ }
+
+ CSmsPduDbConcatSegment* segment = CSmsPduDbConcatSegment::NewL(iFs, item, aType);
+ CleanupStack::PushL(segment);
+ User::LeaveIfError(concat->iSegments.Append(segment));
+ CleanupStack::Pop(segment);
+ }
+
+ if (concat != NULL)
+ concat->DecodeL(iFs);
+
+ CleanupStack::PopAndDestroy(&array);
+ }
+
+EXPORT_C CSmsPduDbMessage* CSmsPduDatabase::GetMessageLC(CSmsPDU::TSmsPDUType aType, TInt aId) const
+ {
+ RSmsPduDbIdArray array(KSmsPduDbMessage);
+ CleanupClosePushL(array);
+ GetIdsL(array, aId);
+
+ const CTestConfigItem& item = *array[0].iItem;
+ CSmsPduDbMessage* pdu = CSmsPduDbMessage::NewL(iFs, item, aType);
+ CleanupStack::PushL(pdu);
+
+
+ CleanupStack::PopAndDestroy(&array);
+ return pdu;
+ }
+
+EXPORT_C void CSmsPduDatabase::GetMessageL(RPointerArray<CSmsPduDbMessage>& aArray, CSmsPDU::TSmsPDUType aType) const
+ {
+ RSmsPduDbIdArray array(KSmsPduDbMessage);
+ CleanupClosePushL(array);
+ GetIdsL(array);
+
+ const TInt count = array.Count();
+
+ for (TInt i=0; i<count; i++)
+ {
+ const CTestConfigItem& item = *array[i].iItem;
+ CSmsPduDbMessage* pdu = CSmsPduDbMessage::NewL(iFs, item, aType);
+ CleanupStack::PushL(pdu);
+ User::LeaveIfError(aArray.Append(pdu));
+ CleanupStack::Pop(pdu);
+ }
+
+ CleanupStack::PopAndDestroy(&array);
+ }
+
+CSmsPduDatabase::CSmsPduDatabase(RFs& aFs)
+: iFs(aFs)
+ {
+ }
+
+void CSmsPduDatabase::GetIdsL(RSmsPduDbIdArray& aIds) const
+ {
+ RPointerArray<const CTestConfigItem> array;
+ CleanupClosePushL(array);
+
+ iSection->ItemsL(array, aIds.Type());
+
+ const TInt count = array.Count();
+
+ for (TInt i=0; i<count; i++)
+ {
+ TSmsPduDbId item(array[i]);
+ const TInt err = CTestConfig::GetElement(item.iItem->Value(), KSmsPduDbDelimiter, CSmsPduDbBase::ESmsPduDbId, item.iId);
+ if (err == KErrNone)
+ {
+ aIds.InsertL(item);
+ }
+ }
+
+ CleanupStack::PopAndDestroy(&array);
+ }
+
+void CSmsPduDatabase::GetIdsL(RSmsPduDbIdArray& aIds, TInt aId) const
+ {
+ RSmsPduDbIdArray tempArray(aIds.Type(), ETrue);
+ CleanupClosePushL(tempArray);
+
+ GetIdsL(tempArray);
+
+ TInt find = KErrNotFound;
+
+ while ((find = tempArray.Find(aId)) != KErrNotFound)
+ {
+ User::LeaveIfError(aIds.Append(tempArray[find]));
+ tempArray.Remove(find);
+ }
+
+ CleanupStack::PopAndDestroy(&tempArray);
+ if (aIds.Count() == 0)
+ User::Leave(KErrNotFound);
+ }
+
+void CSmsPduDatabase::ReadFileL(const TDesC& aInputFileName, const TDesC& aInputComponent, CBufFlat& aData) const
+ {
+ TParse parse;
+ User::LeaveIfError(CTestConfig::ResolveFile(iFs, aInputComponent, aInputFileName, parse));
+
+ RFile file;
+ User::LeaveIfError(file.Open(iFs, parse.FullName(), EFileRead));
+ CleanupClosePushL(file);
+
+ TInt size(0);
+ User::LeaveIfError(file.Size(size));
+
+ for (TInt i = 0; i < size; i += KSmsPduDbMaxReadWriteChunk)
+ {
+ const TInt readSize = Min(KSmsPduDbMaxReadWriteChunk, size - i);
+ TBuf8<KSmsPduDbMaxReadWriteChunk> read;
+ User::LeaveIfError(file.Read(read, readSize));
+ const TInt pos = aData.Size();
+ aData.InsertL(pos, read);
+ }
+
+ CleanupStack::PopAndDestroy(&file);
+ }
+
+void CSmsPduDatabase::WriteFileL(const TDesC& aOutputFileName, const CBufFlat& aData) const
+ {
+ RFile file;
+ User::LeaveIfError(file.Replace(iFs, aOutputFileName, EFileWrite));
+ CleanupClosePushL(file);
+
+ const TInt size = aData.Size();
+
+ for (TInt i = 0; i < size; i += KSmsPduDbMaxReadWriteChunk)
+ {
+ const TInt readSize = Min(KSmsPduDbMaxReadWriteChunk, size - i);
+ TBuf8<KSmsPduDbMaxReadWriteChunk> read;
+ aData.Read(i, read, readSize);
+ User::LeaveIfError(file.Write(read));
+ }
+
+ User::LeaveIfError(file.Flush());
+
+ CleanupStack::PopAndDestroy(&file);
+ }
+
+EXPORT_C void CSmsPduDatabase::RewriteFileL(const TDesC& aInputFileName, const TDesC& aInputComponent, const TDesC& aOutputFileName) const
+ {
+ CBufFlat* buffer = CBufFlat::NewL(0x100); //< TODO Remove this magic number
+ CleanupStack::PushL(buffer);
+
+ ReadFileL(aInputFileName, aInputComponent, *buffer);
+
+ ParseFileL(*buffer);
+
+ WriteFileL(aOutputFileName, *buffer);
+
+ CleanupStack::PopAndDestroy(buffer);
+ }
+
+void CSmsPduDatabase::ParseFileL(CBufFlat& aData) const
+ {
+ TPtrC8 ptr(aData.Ptr(0));
+ TLex8 lex(ptr);
+ lex.Mark();
+
+ while (!lex.Eos())
+ {
+ if (lex.Peek() == KSmsPduDbTagStart)
+ {
+ ParseTagL(aData, ptr, lex);
+ }
+ else
+ {
+ lex.Inc();
+ }
+ }
+ }
+
+void CSmsPduDatabase::ParseTagL(CBufFlat& aData, TPtrC8& aPtr, TLex8& aLex) const
+ {
+ const TInt startingPos = aLex.Offset();
+
+ const TPtrC8 remainder(aLex.Remainder());
+ const TInt locate = remainder.Locate(KSmsPduDbTagEnd);
+ TInt err = locate;
+
+ if (locate != KErrNotFound)
+ {
+ aLex.Mark();
+ aLex.Inc(locate+1);
+
+ const TPtrC8 marked(aLex.MarkedToken());
+ CSmsPduDbPdu* pdu = NULL;
+
+ TRAP(err, pdu = PduFactoryL(marked));
+
+ if (err == KErrNone)
+ {
+ CleanupStack::PushL(pdu);
+ TBuf8<RMobileSmsMessaging::KGsmTpduSize*2> hexPdu;
+ pdu->GetHexPdu(hexPdu);
+ aData.Delete(startingPos, marked.Length());
+ aData.InsertL(startingPos, hexPdu);
+ aPtr.Set(aData.Ptr(0));
+ aLex = aPtr;
+ aLex.Inc(startingPos + pdu->iPdu.Length());
+ CleanupStack::PopAndDestroy(pdu);
+ }
+ }
+
+ if (err != KErrNone)
+ {
+ aLex.Inc();
+ }
+ }
+
+TBool CSmsPduDatabase::IsPdu(const TDesC8& aTag, CSmsPDU::TSmsPDUType& aType) const
+ {
+ TBool ret = EFalse;
+
+ if (aTag.CompareF(KSmsPduDbSubmit) == KErrNone)
+ {
+ ret = ETrue;
+ aType = CSmsPDU::ESmsSubmit;
+ }
+ else if (aTag.CompareF(KSmsPduDbDeliver) == KErrNone)
+ {
+ ret = ETrue;
+ aType = CSmsPDU::ESmsDeliver;
+ }
+ else if (aTag.CompareF(KSmsPduDbStatusReport) == KErrNone)
+ {
+ ret = ETrue;
+ aType = CSmsPDU::ESmsStatusReport;
+ }
+ else if (aTag.CompareF(KSmsPduDbCommand) == KErrNone)
+ {
+ ret = ETrue;
+ aType = CSmsPDU::ESmsCommand;
+ }
+ else if (aTag.CompareF(KSmsPduDbSubmitReport) == KErrNone)
+ {
+ ret = ETrue;
+ aType = CSmsPDU::ESmsSubmitReport;
+ }
+ else if (aTag.CompareF(KSmsPduDbDeliverReport) == KErrNone)
+ {
+ ret = ETrue;
+ aType = CSmsPDU::ESmsDeliverReport;
+ }
+
+ return ret;
+ }
+
+TBool CSmsPduDatabase::IsConcatSegment(const TDesC8& aTag, CSmsPDU::TSmsPDUType& aType) const
+ {
+ TBool ret = EFalse;
+
+ if (aTag.CompareF(KSmsPduDbSubmitConcat) == KErrNone)
+ {
+ ret = ETrue;
+ aType = CSmsPDU::ESmsSubmit;
+ }
+ else if (aTag.CompareF(KSmsPduDbDeliverConcat) == KErrNone)
+ {
+ ret = ETrue;
+ aType = CSmsPDU::ESmsDeliver;
+ }
+
+ return ret;
+ }
+
+EXPORT_C CSmsPduDbPdu* CSmsPduDatabase::PduFactoryL(const CTestConfigItem& aItem, CSmsPDU::TSmsPDUType aTypeForMessageTags) const
+ {
+ const TDesC8& type = aItem.Item();
+ CSmsPduDbPdu* pdu = NULL;
+ CSmsPDU::TSmsPDUType pduType;
+
+ if (IsPdu(type, pduType))
+ {
+ pdu = CSmsPduDbPdu::NewL(iFs, aItem, pduType);
+ }
+ else if (IsConcatSegment(type, pduType))
+ {
+ pdu = CSmsPduDbConcatSegment::NewL(iFs, aItem, pduType);
+ }
+ else if (IsMessage(type))
+ {
+ pdu = CSmsPduDbMessage::NewL(iFs, aItem, aTypeForMessageTags);
+ }
+ else
+ {
+ //Attempt to parse aItem.Value() using the other overload of PduFactoryL()
+ pdu = PduFactoryL(aItem.Value(), aTypeForMessageTags);
+ }
+
+ __ASSERT_DEBUG(pdu != NULL, PduDbPanic(EPduDbPanicPduNotConstructed));
+ return pdu;
+ }
+
+EXPORT_C CSmsPduDbPdu* CSmsPduDatabase::PduFactoryL(const TDesC8& aTag, CSmsPDU::TSmsPDUType aTypeForMessageTags) const
+/**
+ * Parses tags of the form <MESSAGE_TYPE; ID; {SEGMENT}>, e.g. <SUBMIT,21> or <MESSAGE,2> or <SUBMITCONCAT; 32; 2>
+ * If the MESSAGE_TYPE and ID combination if found in the PDU database then a CSmsPduDbPdu-derived object is created.
+ * SEGMENT is only compulsory if MESSAGE_TYPE is a concatenated message.
+ *
+ * @param aTag Tag of the form <MESSAGE_TYPE; ID; {SEGMENT}>. MESSAGE_TYPE and ID are compulsory and must be delimited by a semicolon (;)
+ * @param aTypeForMessageTags PDU Type used when creating a CSmsPduDbMessage. This occurs if MESSAGE_TYPE == "message"
+ */
+ {
+ TPtrC8 tag(CTestConfig::Trim(aTag));
+ const TInt len = tag.Length();
+
+ if (len < 4)
+ User::Leave(KErrBadName);
+
+ TInt midStart = 0;
+ TInt midLen = len;
+ if (tag[0] == KSmsPduDbTagStart)
+ {
+ midStart++;
+ midLen--;
+ }
+
+ if (tag[len-1] == KSmsPduDbTagEnd)
+ midLen--;
+
+ tag.Set(tag.Mid(midStart, midLen));
+
+ TPtrC8 type;
+ TInt id(0);
+
+ User::LeaveIfError(CTestConfig::GetElement(tag, KSmsPduDbTagDelimitier, ETagType, type));
+ User::LeaveIfError(CTestConfig::GetElement(tag, KSmsPduDbTagDelimitier, ETagId, id));
+
+ CSmsPduDbPdu* pdu = NULL;
+ CSmsPDU::TSmsPDUType pduType;
+
+ if (IsPdu(type, pduType))
+ {
+ pdu = GetPduLC(pduType, id);
+ }
+ else if (IsConcatSegment(type, pduType))
+ {
+ TInt segment;
+ User::LeaveIfError(CTestConfig::GetElement(tag, KSmsPduDbTagDelimitier, ETagSegment, segment));
+ pdu = GetConcatSegmentLC(pduType, id, segment);
+ }
+ else if (IsMessage(type))
+ {
+ pdu = GetMessageLC(aTypeForMessageTags, id);
+ }
+ else
+ {
+ User::Leave(KErrBadName);
+ }
+
+ __ASSERT_DEBUG(pdu != NULL, PduDbPanic(EPduDbPanicPduNotConstructed));
+ CleanupStack::Pop(pdu);
+ return pdu;
+ }
+
+EXPORT_C CSmsPduDbPdu* CSmsPduDatabase::PduFactory(const TDesC8& aTag, CSmsPDU::TSmsPDUType aTypeForMessageTags) const
+ {
+ CSmsPduDbPdu* pdu = NULL;
+ TRAPD(err, (pdu = PduFactoryL(aTag, aTypeForMessageTags)));
+ return ((err == KErrNone) ? pdu : NULL);
+ }
+
+EXPORT_C CSmsPduDbPdu* CSmsPduDatabase::PduFactory(const CTestConfigItem& aItem, CSmsPDU::TSmsPDUType aTypeForMessageTags) const
+ {
+ CSmsPduDbPdu* pdu = NULL;
+ TRAPD(err, (pdu = PduFactoryL(aItem, aTypeForMessageTags)));
+ return ((err == KErrNone) ? pdu : NULL);
+ }
+
+TInt CSmsPduDatabase::RSmsPduDbIdArray::Compare(const TSmsPduDbId& aLeft, const TSmsPduDbId& aRight)
+ {
+ return aLeft.iId - aRight.iId;
+ }
+
+TInt CSmsPduDatabase::RSmsPduDbIdArray::Find(TInt aId) const
+ {
+ TLinearOrder<TSmsPduDbId> order(Compare);
+ const TSmsPduDbId tempId(NULL, aId);
+ return FindInOrder(tempId, order);
+ }
+
+void CSmsPduDatabase::RSmsPduDbIdArray::InsertL(const TSmsPduDbId& aId)
+ {
+ TLinearOrder<TSmsPduDbId> order(Compare);
+
+ if (iAllowDuplicates)
+ User::LeaveIfError(InsertInOrderAllowRepeats(aId, order));
+ else
+ User::LeaveIfError(InsertInOrder(aId, order));
+ }