diff -r 3406c99bc375 -r 07b41fa8d1dd stif/Parser/src/StifFileParser.cpp --- a/stif/Parser/src/StifFileParser.cpp Thu Jul 15 20:25:38 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,929 +0,0 @@ -/* -* Copyright (c) 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: This module contains implementation of CStifParser -* class member functions. -* -*/ - -// INCLUDE FILES -#include -#include "StifFileParser.h" -#include "StifTestInterface.h" -#include "ParserTracing.h" - -// EXTERNAL DATA STRUCTURES -// None - -// EXTERNAL FUNCTION PROTOTYPES -// None - -// CONSTANTS -// None - -// MACROS -// None - -// LOCAL CONSTANTS AND MACROS -// None - -// MODULE DATA STRUCTURES -// None - -// LOCAL FUNCTION PROTOTYPES -// None - -// FORWARD DECLARATIONS -// None - -// ==================== LOCAL FUNCTIONS ======================================= -// None - -// ================= MEMBER FUNCTIONS ========================================= - -/* -------------------------------------------------------------------------------- - - Class: CStifFileParser - - Method: CStifFileParser - - Description: Default constructor - - C++ default constructor can NOT contain any code, that - might leave. - - Parameters: TCommentType aCommentType: in: Comment type's indication - - Return Values: None - - Errors/Exceptions: None - - Status: Approved - -------------------------------------------------------------------------------- -*/ -CStifFileParser::CStifFileParser(CStifParser::TCommentType aCommentType) - { - iCommentType = aCommentType; - } - -/* -------------------------------------------------------------------------------- - - Class: CStifFileParser - - Method: ConstructL - - Description: Symbian OS second phase constructor - - Symbian OS default constructor can leave. - - Sets variables. - - Parameters: RFs& aFs: in: Handle to valid file server - RFile& aFile: in: Handle to the source file - TBool aIsUnicode in: Is file in unicode format - - Return Values: None - - Errors/Exceptions: None - - Status: Proposal - -------------------------------------------------------------------------------- -*/ -void CStifFileParser::ConstructL(RFs& aFs, - RFile& aFile, - TBool aIsUnicode) - { - //Initialization - iFileServer = aFs; - iBaseFile = aFile; - iCurrentFile = &aFile; - iIsUnicode = aIsUnicode; - iBytesPerChar = iIsUnicode ? 2 : 1; - - //Create file stack (INCLUDE feature) - iFileStack = new (ELeave) CStackDeprecated; - - //Add base file to file names array - TFileName fn; - iCurrentFile->FullName(fn); - HBufC* newFile = fn.AllocLC(); - User::LeaveIfError(iFileNames.Append(newFile)); - CleanupStack::Pop(newFile); - } - -/* -------------------------------------------------------------------------------- - - Class: CStifFileParser - - Method: NewL - - Description: Two-phased constructor. - - Starting creating parser with path and file information. - - Parameters: RFs& aFs: in: Handle to file server - RFile& aFile: in: Source path definition - TBool aIsUnicode in: Is file in unicode format - TCommentType aCommentType: in: Comment type's indication - - Return Values: CStifFileParser* : pointer to CStifFileParser object - - Errors/Exceptions: Leaves if ConstructL leaves - - Status: Proposal - -------------------------------------------------------------------------------- -*/ -CStifFileParser* CStifFileParser::NewL(RFs& aFs, - RFile& aFile, - TBool aIsUnicode, - CStifParser::TCommentType aCommentType) - { - // Create CStifParser object - CStifFileParser* parser = new (ELeave) CStifFileParser(aCommentType); - - CleanupStack::PushL(parser); - parser->ConstructL(aFs, aFile, aIsUnicode); - CleanupStack::Pop(parser); - - return parser; - } - -/* -------------------------------------------------------------------------------- - - Class: CStifFileParser - - Method: ~CStifFileParser - - Description: Destructor - - Parameters: None - - Return Values: None - - Errors/Exceptions: None - - Status: Proposal - -------------------------------------------------------------------------------- -*/ -CStifFileParser::~CStifFileParser() - { - //Close file stack - ClearFileStack(); - delete iFileStack; - - //Close section lines array - ClearSectionLinesArray(); - iSectionLines.Close(); - - //Close fila names array - while(iFileNames.Count() > 0) - { - delete iFileNames[0]; - iFileNames.Remove(0); - } - iFileNames.Close(); - } - -/* -------------------------------------------------------------------------------- - - Class: CStifFileParser - - Method: ReadLineL - - Description: Reads line from source file - - Parameters: TPtr& aLineBuffer: in: Descriptor in which line loads - TPtr& aEndOfLineBuffer: in: Descriptor in which end of line sequence is loaded (0x0A or 0x0D 0x0A) - - Return Values: TBool: determines whether line was readed or not - - Errors/Exceptions: Leaves if seek command leaves - Leaves if buffer is too small - - Status: Proposal - -------------------------------------------------------------------------------- -*/ -TBool CStifFileParser::ReadLineL(TPtr& aLineBuffer, - TPtr& aEndOfLineBuffer) - { - //Variables - TBuf8<128> buf8; - TBuf16<128> buf16; - TPtrC16 buf; - TInt pos; - TInt offset; - TChar char0x0A = 0x000A; - TChar char0x0D = 0x000D; - - TBuf<1> b0x0A; - b0x0A.Append(char0x0A); - - //Reset buffers - aLineBuffer.Zero(); - aEndOfLineBuffer.Zero(); - - //Read from source - User::LeaveIfError(iCurrentFile->Read(buf8)); - buf16.Copy(buf8); - if(iIsUnicode) - buf.Set((TUint16 *)(buf8.Ptr()), buf8.Length() / 2); - else - buf.Set(buf16.Ptr(), buf16.Length()); - - while(buf.Length()) - { - //Search for end of line char - pos = buf.Find(b0x0A); - - //If found, append readed data to output descriptor and move back file offset to correct position - if(pos >= 0) - { - offset = -((buf.Length() - pos - 1) * iBytesPerChar); - User::LeaveIfError(iCurrentFile->Seek(ESeekCurrent, offset)); - buf.Set(buf.Ptr(), pos + 1); - aLineBuffer.Append(buf); - break; - } - //Otherwise, append whole buffer to output descriptor - else - { - aLineBuffer.Append(buf); - } - //Read next part of data - User::LeaveIfError(iCurrentFile->Read(buf8)); - buf16.Copy(buf8); - if(iIsUnicode) - { - buf.Set((TUint16 *)(buf8.Ptr()), buf8.Length() / 2); - } - else - { - buf.Set(buf16.Ptr(), buf16.Length()); - } - } - - //Set correct end of line buffer - if(buf.Length() > 1) - { - if(buf[buf.Length() - 2] == char0x0D) - { - aEndOfLineBuffer.Append(char0x0D); - } - } - if(buf.Length() > 0) - { - if(buf[buf.Length() - 1] == char0x0A) - { - aEndOfLineBuffer.Append(char0x0A); - } - else - { - aEndOfLineBuffer.Zero(); - } - } - if(aEndOfLineBuffer.Length()) - { - aLineBuffer.SetLength(aLineBuffer.Length() - aEndOfLineBuffer.Length()); - } - - //If no data was found, try to get previous file from stack - if(aLineBuffer.Length() + aEndOfLineBuffer.Length() == 0) - { - //Pop file from stack. If stack is empty, then we achieved end of base file - if(!iFileStack->IsEmpty()) - { - PopFromFileStack(); - aEndOfLineBuffer.Copy(iEolBuf); - return aEndOfLineBuffer.Length(); - } - } - //Check if this is include line - else - { - if(aLineBuffer.Find(KIncludeKeyword) == 0) - { - TFileName fn; - TLex lex(aLineBuffer); - - fn.Copy(lex.NextToken()); //get INCLUDE keyword - fn.Copy(lex.NextToken()); //get cfg file name - if(fn.Length() > 0) - { - TStifUtil::CorrectFilePathL( fn ); - PushFileToStackL(fn); - iEolBuf.Copy(aEndOfLineBuffer); - } - else - { - __TRACE(KError, (_L("No filename was given after INCLUDE. Ignoring"))); - } - - //Read next line - return ReadLineL(aLineBuffer, aEndOfLineBuffer); - } - } - - return aLineBuffer.Length() + aEndOfLineBuffer.Length(); - } - -/* -------------------------------------------------------------------------------- - - Class: CStifFileParser - - Method: ReplaceCommentsLineL - - Description: Replaces comments with spaces from line and copy it to destination buffer - - Parameters: TPtr& aSrcBufPtr: in: Source line with comments - TPtr& aDstBufPtr: out: Destination line without comments - TWhatToFind& aFind: in out: Determines what method currently is looking for - - Return Values: None - - Errors/Exceptions: None - - Status: Proposal - -------------------------------------------------------------------------------- -*/ -void CStifFileParser::ReplaceCommentsLineL(TPtr& aSrcBufPtr, - TPtr& aDstBufPtr, - TWhatToFind& aFind) - { - //Variables - TLex lex(aSrcBufPtr); - TChar ch; - TChar chSpace(' '); - TChar chSlash('/'); - TChar chQuota('\"'); - TChar chMulti('*'); - TChar chHash('#'); - - //Clean buffer - aDstBufPtr.Zero(); - - while(!lex.Eos()) - { - ch = lex.Get(); - - //If the end of line, exit - if(!ch) - { - break; - } - - //We're looking for start od quoted text or comment - if(aFind == EStart) - { - //Special character readed - if(ch == chQuota) - { - aFind = EQuota; - aDstBufPtr.Append(chSpace); - } - //Possible start of comment - else if(ch == chSlash) - { - //Comment to the end of line found - if(lex.Peek() == chSlash) - { - break; - } - //Beginning of a comment found - else if(lex.Peek() == chMulti) - { - aFind = EEndOfComment; - ch = lex.Get(); - aDstBufPtr.Append(chSpace); - aDstBufPtr.Append(chSpace); - } - //No start of comment - add read slash - else - { - aDstBufPtr.Append(ch); - } - } - //Start of hash comment (to the end of line) - else if(ch == chHash) - { - break; - } - //Append readed character to the destination buffer - else - { - aDstBufPtr.Append(ch); - } - } - //We're looking for the end of quoted text - else if(aFind == EQuota) - { - if(ch == chQuota) - { - aFind = EStart; - aDstBufPtr.Append(chSpace); - } - else - { - aDstBufPtr.Append(chSpace); - } - } - //We're looking for the end of comment - else if(aFind == EEndOfComment) - { - //It may be the end of a comment - if(ch == chMulti) - { - ch = lex.Peek(); - //It is the end of a comment - if(ch == chSlash) - { - aFind = EStart; - ch = lex.Get(); - aDstBufPtr.Append(chSpace); - aDstBufPtr.Append(chSpace); - } - //It is not the end of a comment, add this character to the destinaton buffer - else - { - aDstBufPtr.Append(chSpace); - } - } - //It is not the end of a comment, add this character to the destinaton buffer - else - { - aDstBufPtr.Append(chSpace); - } - } - } - } - -/* -------------------------------------------------------------------------------- - - Class: CStifFileParser - - Method: ReplaceHashCommentsLineL - - Description: Copy line to destination buffer and deletes #-style comments - - Parameters: TPtr& aSrcBufPtr: in: Source line with comments - TPtr& aDstBufPtr: out: Destination line without comments - - Return Values: None - - Errors/Exceptions: None - - Status: Proposal - -------------------------------------------------------------------------------- -*/ -void CStifFileParser::ReplaceHashCommentsLineL(TPtr& aSrcBufPtr, - TPtr& aDstBufPtr) - { - //Variables - TLex lex(aSrcBufPtr); - TChar ch; - TChar chHash('#'); - - //Prepare destination buffer - aDstBufPtr.Zero(); - - //Copy source line to destination until # char is found - while(!lex.Eos()) - { - ch = lex.Get(); - - //If the end of line, exit - if(!ch) - { - break; - } - - if(ch == chHash) - { - break; - } - else - { - aDstBufPtr.Append(ch); - } - } - } - -/* -------------------------------------------------------------------------------- - - Class: CStifFileParser - - Method: NextSectionL - - Description: Finds n-th (aSeeked) section in file starting from m-th (aOffset) position - - Parameters: const TDesc& aStartTag: in: Starting tag of a section - const TDesc& aEndTag: in: Ending tag of a section - TInt& aOffset: in out: Current offset in file (*) - TInt aSeeked: in: Which section is to be found - - Notification: aOffset has different meaning than before adding INCLUDE functionality. - If it has 0 value, that means that we need to remove files stack and go - back to base file to the beginning. Otherwise we don't change current - file read-handler position. - - Return Values: HBufC *: address of a descriptor containing section. Section is returned without tags. - Caller must take care about the freeing descriptor. - - Errors/Exceptions: Leaves if aSeeked is less than 1 or aOffset is negative - Leaves if seek command leaves - Leaves if cannot allocate buffers - Leaves if cannot allocate section - Leaves if length of readed line exceeds KMaxLineLength constant - - Status: Proposal - -------------------------------------------------------------------------------- -*/ -HBufC* CStifFileParser::NextSectionL(const TDesC& aStartTag, - const TDesC& aEndTag, - TInt& aOffset, - TInt aSeeked) - { - // Check arguments - if(aSeeked < 1) - { - User::Leave(KErrArgument); - } - if(aOffset < 0) - { - User::Leave(KErrArgument); - } - - TInt foundSection = 0; - TInt ret; - - // Alloc buffers to read line - const TInt KMaxLineLength = 4096; //If length of readed line exceeds this constant, method will leave - - HBufC* buf = HBufC::NewL(KMaxLineLength); - CleanupStack::PushL(buf); - TPtr bufPtr(buf->Des()); - - HBufC* withoutCommentsBuf = HBufC::NewL(KMaxLineLength); - CleanupStack::PushL(withoutCommentsBuf); - TPtr withoutCommentsBufPtr(withoutCommentsBuf->Des()); - - HBufC* endOfLine = HBufC::NewL(2); //After reading a line it contains 0D0A or 0A or null (how readed line is ended) - CleanupStack::PushL(endOfLine); - TPtr endOfLinePtr(endOfLine->Des()); - - //Set valid position in file - //but only if offset shows to 0. Otherwise keep previus position - if(aOffset == 0) - { - User::LeaveIfError(iBaseFile.Seek(ESeekStart, aOffset)); - ClearFileStack(); - aOffset = 1; - } - - //Prepare to read lines - TBool validSectionBeginFound = EFalse; - TBool validSectionEndFound = EFalse; - TSectionFind whatToFindSection = ESectionStart; - //If no start tag is given start to find end tag immediatly - if(aStartTag.Length() == 0) - { - foundSection++; - whatToFindSection = ESectionEnd; - validSectionBeginFound = ETrue; - } - if(aEndTag.Length() == 0) - { - validSectionEndFound = ETrue; - } - TWhatToFind whatToFind = EStart; - - //Perform reading file - while(ReadLineL(bufPtr, endOfLinePtr)) - { - if(iCommentType == CStifParser::ECStyleComments) - { - ReplaceCommentsLineL(bufPtr, withoutCommentsBufPtr, whatToFind); - } - else - { - ReplaceHashCommentsLineL(bufPtr, withoutCommentsBufPtr); - } - if(whatToFindSection == ESectionStart) - { - //Find in line star tag (if start tag is not given, behave like we've found it) - if(aStartTag.Length() == 0) - { - ret = 0; - } - else - { - ret = withoutCommentsBuf->Find(aStartTag); - } - //If found remember position, move offset of file to actual position - if(ret >= 0) - { - whatToFindSection = ESectionEnd; - TInt offset = -(bufPtr.Length() + endOfLinePtr.Length() - ret - aStartTag.Length()) * iBytesPerChar; - User::LeaveIfError(iCurrentFile->Seek(ESeekCurrent, offset)); - - whatToFind = EStart; //reset marker, because if we've found tag, we couldn't be in the middle of comment or quota - foundSection++; - //Add this line to section lines array - if(foundSection == aSeeked) - { - validSectionBeginFound = ETrue; - } - continue; - } - } - else if(whatToFindSection == ESectionEnd) - { - //Find in line end tag (if end tag is not given, behave like we've found it) - if(aEndTag.Length() == 0) - { - ret = KErrNotFound; - } - else - { - ret = withoutCommentsBuf->Find(aEndTag); - } - //If found check if this is the one we're looking for - if(ret >= 0) - { - whatToFindSection = ESectionStart; - TInt offset = -(bufPtr.Length() + endOfLinePtr.Length() - ret - aEndTag.Length()) * iBytesPerChar; - User::LeaveIfError(iCurrentFile->Seek(ESeekCurrent, offset)); - - whatToFind = EStart; //reset marker, because if we've found tag, we couldn't be in the middle of comment or quota - if(foundSection == aSeeked) - { - //Add this line to section lines array - HBufC* line = HBufC::NewLC(bufPtr.Length()); - TPtr linePtr(line->Des()); - linePtr.Copy(bufPtr.MidTPtr(0, ret)); - User::LeaveIfError(iSectionLines.Append(line)); - CleanupStack::Pop(line); - validSectionEndFound = ETrue; - break; - } - else - { - continue; - } - } - else - { - //If we're in section we are looking for, add line to array - if(foundSection == aSeeked) - { - HBufC* line = HBufC::NewLC(bufPtr.Length() + endOfLinePtr.Length()); - TPtr linePtr(line->Des()); - linePtr.Copy(bufPtr); - linePtr.Append(endOfLinePtr); - User::LeaveIfError(iSectionLines.Append(line)); - CleanupStack::Pop(line); - } - } - } - } - - //Clean data - CleanupStack::PopAndDestroy(endOfLine); - CleanupStack::PopAndDestroy(withoutCommentsBuf); - CleanupStack::PopAndDestroy(buf); - - //Load into section if found - HBufC* section = NULL; - - if(validSectionBeginFound && validSectionEndFound) - { - //Count amount of memory needed for section - TInt i; - TInt size = 0; - for(i = 0; i < iSectionLines.Count(); i++) - size += iSectionLines[i]->Length(); - - //Copy section from array to buffer - section = HBufC::NewL(size); - CleanupStack::PushL(section); - TPtr sectionPtr(section->Des()); - - for(i = 0; i < iSectionLines.Count(); i++) - sectionPtr.Append(*iSectionLines[i]); - - ClearSectionLinesArray(); - - //Clean local data - CleanupStack::Pop(section); - - return section; - } - - ClearSectionLinesArray(); - - //If section was not found, then for compability with CSectionParser leave when not first section was seeking, return NULL when first section was seeking - if(foundSection != aSeeked) - { - if( aSeeked - foundSection > 1) - { - User::Leave(KErrNotFound); - } - } - - return section; - } - -/* -------------------------------------------------------------------------------- - - Class: CStifFileParser - - Method: ClearFileStack - - Description: Closes all files on file stack and clears the stack - - Parameters: None - - Return Values: None - - Errors/Exceptions: None - - Status: Proposal - -------------------------------------------------------------------------------- -*/ -void CStifFileParser::ClearFileStack(void) - { - while(!iFileStack->IsEmpty()) - { - PopFromFileStack(); - } - } - -/* -------------------------------------------------------------------------------- - - Class: CStifFileParser - - Method: PopFromFileStack - - Description: Pops RFile handle from file stack and sets correct current file handle - - Parameters: None - - Return Values: None - - Errors/Exceptions: None - - Status: Proposal - -------------------------------------------------------------------------------- -*/ -void CStifFileParser::PopFromFileStack(void) - { - if(!iFileStack->IsEmpty()) - { - //Pop from stack - iCurrentFile = iFileStack->Pop(); - - TFileName fn; - iCurrentFile->FullName(fn); - - //And remove from file names array - for(TInt i = iFileNames.Count() - 1; i >= 0; i--) - { - if(fn.CompareF(iFileNames[i]->Des()) == KErrNone) - { - delete iFileNames[i]; - iFileNames.Remove(i); - break; - } - } - __TRACE(KInfo, (_L("Closing file [%S]"), &fn)); - - //Close file - iCurrentFile->Close(); - delete iCurrentFile; - - //Set correct current file - if(iFileStack->IsEmpty()) - { - iCurrentFile = &iBaseFile; //base file, because stack is empty - } - else - { - iCurrentFile = iFileStack->Last(); - } - } - } - -/* -------------------------------------------------------------------------------- - - Class: CStifFileParser - - Method: PushFileToStack - - Description: Opens file and pushes it to stack - - Parameters: TDesc& aFileName in: name of file to open and add to stack - - Return Values: None - - Errors/Exceptions: None - - Status: Proposal - -------------------------------------------------------------------------------- -*/ -void CStifFileParser::PushFileToStackL(const TDesC& aFileName) - { - - //First check if file is not already included - for(TInt i = 0; i < iFileNames.Count(); i++) - { - if(aFileName.CompareF(iFileNames[i]->Des()) == KErrNone) - { - __TRACE(KError, (_L("File [%S] was already included. Ignoring"), &aFileName)); - return; - } - } - - //Open and add file to stack - RFile *nf = new RFile(); - - __TRACE(KInfo, (_L("Including file [%S]"), &aFileName)); - TInt r = nf->Open(iFileServer, aFileName, EFileRead | EFileShareAny); - if(r == KErrNone) - { - //Add to stack - iFileStack->PushL(nf); - - //And add to file names array - HBufC* newFile = aFileName.AllocLC(); - User::LeaveIfError(iFileNames.Append(newFile)); - CleanupStack::Pop(newFile); - - //Set valid pointer of current file - iCurrentFile = nf; - } - else - { - __TRACE(KError, (_L("Could not open file [%S]. Error %d. Ignoring"), &aFileName, r)); - } - } - -/* -------------------------------------------------------------------------------- - - Class: CStifFileParser - - Method: ClearSectionLinesArray - - Description: Deletes all descriptors assigned to array and empties array - - Parameters: None - - Return Values: None - - Errors/Exceptions: None - - Status: Proposal - -------------------------------------------------------------------------------- -*/ -void CStifFileParser::ClearSectionLinesArray(void) - { - while(iSectionLines.Count() > 0) - { - delete iSectionLines[0]; - iSectionLines.Remove(0); - } - } - -// End of File