📄 elementsengine.cpp
字号:
/**
*
* @brief Asynchronous test engine to verify the functionality of the Elements project
*
* Copyright (c) EMCC Software Ltd 2003
* @version 1.0
*/
// INCLUDE FILES
// Class include
#include "elementsengine.h"
// System includes
#include <e32cons.h>
#include <s32file.h>
// User includes
#include "elementrarray.h"
#include "elementcarray.h"
#include "csvfileloader.h"
#include "chemicalelement.h"
// ===================== CONSTANTS ==========================
_LIT(KMetalsFileName, "C:\\metals.csv");
_LIT(KNonMetalsFileName, "C:\\nonmetals.csv");
_LIT(KSemiMetalsFileName, "C:\\semimetals.csv");
_LIT(KTxtLoaded, "Loaded ");
_LIT(KTxtLoadedReturn, " loaded\n");
_LIT(KTxtSemiMetals, "Semimetals");
_LIT(KTxtNonMetals, "Nonmetals");
_LIT(KTxtMetals, "Metals");
_LIT(KTxtTestFileName, "C:\\elements");
_LIT(KTxtStoreTestFileName, "C:\\elementsstore");
const TInt KPanicLoadFailed = 1;
const TInt KPanicWrongElementCount = 2;
const TInt KPanicSampleElementSymbolInWrongPlace = 3;
const TInt KPanicSampleElementAtomicNumberInWrongPlace = 4;
_LIT(KTxtSampleElementSymbol, "Nd");
const TInt KMaxFeedbackLen = 100;
const TInt KNumberOfCsvFilesToLoad = 3;
const TInt KUidMetalsStreamId = 0x101F613F;
const TInt KUidNonmetalsStreamId = 0x101F6140;
const TInt KUidSemimetalsStreamId = 0x101F6141;
const TInt KExpectedElementCount = 118;
// ================= MEMBER FUNCTIONS =======================
CElementsEngine::CElementsEngine(CConsoleBase& aConsole) :
iConsole(aConsole)
{
}
CElementsEngine::~CElementsEngine()
{
delete iMetalsCsvFileLoader;
delete iNonMetalsCsvFileLoader;
delete iSemiMetalsCsvFileLoader;
delete iElementList;
delete iStore;
delete iRootDictionary;
iFs.Close();
}
CElementsEngine* CElementsEngine::NewLC(CConsoleBase& aConsole)
{
CElementsEngine* self = new (ELeave) CElementsEngine(aConsole);
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
CElementsEngine* CElementsEngine::NewL(CConsoleBase& aConsole)
{
CElementsEngine* self = CElementsEngine::NewLC(aConsole);
CleanupStack::Pop(self);
return self;
}
void CElementsEngine::ConstructL()
{
User::LeaveIfError(iFs.Connect());
iElementList = new (ELeave) CElementRArray();
//iElementList = CElementCArray::NewL();
}
void CElementsEngine::LoadFromCsvFilesL()
{
delete iMetalsCsvFileLoader;
iMetalsCsvFileLoader = 0;
iMetalsCsvFileLoader = CCsvFileLoader::NewL(iFs, *iElementList, *this, KMetalsFileName);
iMetalsCsvFileLoader->Start();
delete iNonMetalsCsvFileLoader;
iNonMetalsCsvFileLoader = 0;
iNonMetalsCsvFileLoader = CCsvFileLoader::NewL(iFs, *iElementList, *this, KNonMetalsFileName);
iNonMetalsCsvFileLoader->Start();
delete iSemiMetalsCsvFileLoader;
iSemiMetalsCsvFileLoader = 0;
iSemiMetalsCsvFileLoader = CCsvFileLoader::NewL(iFs, *iElementList, *this, KSemiMetalsFileName);
iSemiMetalsCsvFileLoader->Start();
}
void CElementsEngine::NotifyElementLoaded(TInt aNewElementIndex)
{
//Start with KTxtLoaded...
TBuf<KMaxFeedbackLen> loadedFeedbackString(KTxtLoaded);
//...append the name of the new element...
loadedFeedbackString.Append((iElementList->At(aNewElementIndex)).Name());
//...append a new line...
loadedFeedbackString.Append(KTxtNewLine);
//...and print to the console
iConsole.Printf(loadedFeedbackString);
}
void CElementsEngine::NotifyLoadCompleted(TInt aCompletionStatus, const CCsvFileLoader& aLoader)
{
__ASSERT_ALWAYS(aCompletionStatus == KErrNone, Panic(KPanicLoadFailed));
TBuf<KMaxFeedbackLen> completedFeedbackString;
if (&aLoader == iMetalsCsvFileLoader)
{
completedFeedbackString = KTxtMetals;
}
else if (&aLoader == iNonMetalsCsvFileLoader)
{
completedFeedbackString = KTxtNonMetals;
}
else
{
completedFeedbackString = KTxtSemiMetals;
}
completedFeedbackString.Append(KTxtLoadedReturn);
iConsole.Printf(completedFeedbackString);
iFilesCompleted++;
if (iFilesCompleted == KNumberOfCsvFilesToLoad)
{
CActiveScheduler::Stop(); //Loading is completed--stop the scheduler
TestElementList(); //Carry out some simple tests on the data
}
}
void CElementsEngine::TestElementList()
{
__ASSERT_ALWAYS(iElementList->NumberOfElements() == KExpectedElementCount, Panic(KPanicWrongElementCount));
TRAPD(err, iElementList->SortBySymbolL());
__ASSERT_ALWAYS(!err, Panic(err));
TInt sampleElementSymbolLocationWhenSortedBySymbol = 0;
TRAP(err, sampleElementSymbolLocationWhenSortedBySymbol =
iElementList->FindElementBySymbolL(KTxtSampleElementSymbol));
__ASSERT_ALWAYS(!err, Panic(err));
__ASSERT_ALWAYS(sampleElementSymbolLocationWhenSortedBySymbol == 61,
Panic(KPanicSampleElementSymbolInWrongPlace));
TRAP(err, iElementList->SortByAtomicNumberL());
__ASSERT_ALWAYS(!err, Panic(err));
TInt sampleElementSymbolLocationWhenSortedByAtomicNumber = 0;
TRAP(err, sampleElementSymbolLocationWhenSortedByAtomicNumber =
iElementList->FindElementBySymbolL(KTxtSampleElementSymbol));
__ASSERT_ALWAYS(!err, Panic(err));
__ASSERT_ALWAYS(sampleElementSymbolLocationWhenSortedByAtomicNumber == 59,
Panic(KPanicSampleElementAtomicNumberInWrongPlace));
TRAP(err, TestElementListStreamingL());
__ASSERT_ALWAYS(!err, Panic(err));
//etc...
}
void CElementsEngine::TestElementListStreamingL()
{
RFileWriteStream writeStream;
User::LeaveIfError(writeStream.Create(iFs, KTxtTestFileName, EFileWrite));
writeStream.PushL();
iElementList->ExternalizeL(writeStream);
writeStream.CommitL();
writeStream.Pop();
writeStream.Release();
iElementList->DeleteAllElements();
__ASSERT_ALWAYS(iElementList->NumberOfElements() == 0, Panic(KPanicWrongElementCount));
RFileReadStream readStream;
User::LeaveIfError(readStream.Open(iFs, KTxtTestFileName, EFileRead));
readStream.PushL();
iElementList->InternalizeL(readStream);
readStream.Pop();
readStream.Close();
__ASSERT_ALWAYS(iElementList->NumberOfElements() == KExpectedElementCount, Panic(KPanicWrongElementCount));
User::LeaveIfError(iFs.Delete(KTxtTestFileName));
//Now test Stores
CreateStoreL();
CreateRootDictionaryL();
WriteElementsToStoreL();
WriteRootDictionaryL();
//Delete all of the elements
iElementList->DeleteAllElements();
__ASSERT_ALWAYS(iElementList->NumberOfElements() == 0, Panic(KPanicWrongElementCount));
//delete the store to free resources before we can delete the file
delete iStore;
iStore = 0;
//Now read them back from the store
ReadElementsFromStoreL();
__ASSERT_ALWAYS(iElementList->NumberOfElements() == KExpectedElementCount, Panic(KPanicWrongElementCount));
User::LeaveIfError(iFs.Delete(KTxtStoreTestFileName));
}
void CElementsEngine::CreateStoreL()
{
CFileStore* store = CDirectFileStore::CreateLC(iFs, KTxtStoreTestFileName, EFileWrite);
store->SetTypeL(TUidType(store->Layout()));
CleanupStack::Pop(); //store
iStore = store;
}
void CElementsEngine::CreateRootDictionaryL()
{
iRootDictionary = CStreamDictionary::NewL();
}
void CElementsEngine::Panic(TInt aReason)
{
_LIT(KTxtElementsPanicCategory, "Elements");
User::Panic(KTxtElementsPanicCategory, aReason);
}
void CElementsEngine::WriteElementsToStoreL() const
{
//First, write out the different element types to separate streams
TStreamId metalsStreamId = WriteSpecificElementTypeToStoreL(CChemicalElement::EMetallic);
TStreamId nonmetalsStreamId = WriteSpecificElementTypeToStoreL(CChemicalElement::ENonmetallic);
TStreamId semimetalsStreamId = WriteSpecificElementTypeToStoreL(CChemicalElement::ESemimetallic);
//Now assign their IDs to the dictionary store
iRootDictionary->AssignL(TUid::Uid(KUidMetalsStreamId), metalsStreamId);
iRootDictionary->AssignL(TUid::Uid(KUidNonmetalsStreamId), nonmetalsStreamId);
iRootDictionary->AssignL(TUid::Uid(KUidSemimetalsStreamId), semimetalsStreamId);
}
void CElementsEngine::ReadElementsFromStoreL()
{
//Open the store
//(Pretend we don't have this already!)
CFileStore* store = CDirectFileStore::OpenLC(iFs, KTxtStoreTestFileName, EFileRead);
//Create and internalise the dictionary from the root stream:
//(Pretend we don't have this already!)
CStreamDictionary* dictionary = CStreamDictionary::NewLC();
RStoreReadStream dictionaryStream;
dictionaryStream.OpenLC(*store, store->Root()); //dictionary stream is the root stream
dictionaryStream >> *dictionary; //Stream in the dictionary
CleanupStack::PopAndDestroy(); //dictionaryStream
//Now use the dictionary to look up the stream ids
TStreamId metalsStreamId = dictionary->At(TUid::Uid(KUidMetalsStreamId));
TStreamId nonmetalsStreamId = dictionary->At(TUid::Uid(KUidNonmetalsStreamId));
TStreamId semimetalsStreamId = dictionary->At(TUid::Uid(KUidSemimetalsStreamId));
CleanupStack::PopAndDestroy(dictionary);
//Read in each stream
RStoreReadStream stream;
stream.OpenLC(*store, metalsStreamId);
stream >> *iElementList; //Cleanup stack used because >> can leave!
CleanupStack::PopAndDestroy(); //stream
stream.OpenLC(*store, nonmetalsStreamId);
stream >> *iElementList; //Cleanup stack used because >> can leave!
CleanupStack::PopAndDestroy(); //stream
stream.OpenLC(*store, semimetalsStreamId);
stream >> *iElementList; //Cleanup stack used because >> can leave!
CleanupStack::PopAndDestroy(); //stream
CleanupStack::PopAndDestroy(store);
}
void CElementsEngine::WriteRootDictionaryL() const
{
RStoreWriteStream root;
TStreamId id = root.CreateLC(*iStore);
root << *iRootDictionary;
root.CommitL();
CleanupStack::PopAndDestroy(); //root
iStore->SetRootL(id);
iStore->CommitL();
}
TStreamId CElementsEngine::WriteSpecificElementTypeToStoreL(CChemicalElement::TElementType aElementType) const
{
//First make an element list containing only the specified element type
//(Could just use an RArray "raw," but then I'd have to write my own exernalizer!)
CElementList* list = new (ELeave) CElementRArray;
CleanupStack::PushL(list);
for (TInt i = 0; i < iElementList->NumberOfElements() ;i++)
{
const CChemicalElement& element = iElementList->At(i);
if (element.Type() != aElementType)
{
//Not the right type
continue;
}
//Now make a copy of this element
CChemicalElement* copy = CChemicalElement::NewLC(element.Name(), element.Symbol(),
element.AtomicNumber(), element.RelativeAtomicMass(), aElementType, element.Radioactive());
list->AppendL(copy);
CleanupStack::Pop(copy); //Ownership transferred to list which is already on stack
}
//Now we have a list with its own copies, we can externalise it
RStoreWriteStream stream;
TStreamId id = stream.CreateLC(*iStore);
stream << *list;
stream.CommitL();
//deleting list is safe, since it has its own copies of the elements!
CleanupStack::PopAndDestroy(2, list); //stream, list
return id;
}
// End of File
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -