tzpcside/tzcompiler/Source/TZScanner.cpp
changeset 0 2e3d3ce01487
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tzpcside/tzcompiler/Source/TZScanner.cpp	Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,225 @@
+// Copyright (c) 2004-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:
+// DST TZ Database Compiler 
+// 
+//
+
+#include "TzGlobals.h"
+#include <string>
+#include <vector>
+#include "TZDocument.h"
+#include "TZScanner.h"
+#include "TZNode.h"
+
+#include <ctype.h>
+
+using namespace std;
+//============================================================================
+// CTzCpScanner::CTzCpScanner
+// Parser construction
+//============================================================================
+CTzCpScanner::CTzCpScanner()
+	{
+	//Add valid characters
+	iValidChars = "+-_<>=:/%";
+	}
+//============================================================================
+// CTzCpScanner::~CTzCpScanner
+// Parser destructor
+//============================================================================
+CTzCpScanner::~CTzCpScanner()
+	{
+	}
+//============================================================================
+// CTzCpScanner::Scan
+// From MScanner
+// Returns KErrNone if succesful or any other TzErrorCode
+//============================================================================
+int CTzCpScanner::Scan(const char* aFileName)
+	{
+	iFileName = aFileName;
+	dbFile.open(aFileName);
+
+	if (dbFile.is_open())
+		{
+		dbFile.clear();		//This resets the eof flag and character position
+		scanState = EWaitFirstChar;
+		iLineNo = 0;
+		iColumnNo = 0;
+		ControlScanning();
+		dbFile.close();
+		return TzGlobals::ETzNone;
+		}
+	else 
+	//File was not opened
+		{
+		cout << "Cannot open " << aFileName << endl;
+		throw TzGlobals::ETzAbortScannerFileIOError;
+		}
+	}
+//============================================================================
+// CTzCpScanner::ControlScanning
+// Reads the data file line by line.  Each line is converted to a number of 
+// CTzNodes and ownership of the node is passed to the document.
+// The general structure of a node is split into elements and attributes
+// An 'element' node encapsulates the entire line as read from the data file
+// by owning 'attribute' nodes, the actual fields on the line.
+// The decisions made here are purely based on the first character of each
+// line in the file to be parsed.  The parser is unaware of the content or
+// meaning of the file being parsed.
+// Current rules used are:
+//	1:	We are only interested in lines that start with 'R','Z','L' or '\t'
+//	2:	The end of a token is a newline, tab, space or '#'
+//	3:	If a line starts with a tab the element is created as a child of the 
+//		previous node
+//	4:	All other elements are created as chilren of the document root node
+//	5:	There is no limit on the number of attributes owned by an element
+//============================================================================
+void CTzCpScanner::ControlScanning()
+
+	{
+	char tmpChar;
+	char firstChar;
+	string tmpString;
+
+	do
+		{
+		if (dbFile.eof())
+			tmpChar = EOF;			// define something out of the range of normal characters
+		else
+			{
+			dbFile.get(tmpChar);	// get next char
+			++iColumnNo;
+			}
+
+		switch (scanState)
+			{
+			case EWaitFirstChar:
+				{
+				++iLineNo;			// we have a new line
+				iColumnNo = 0;		// reset the column count
+				firstChar = tmpChar;
+				tmpString.erase();	// is this the right call to empty the string ?
+				if ((tmpChar == 'R') || (tmpChar == 'Z') || (tmpChar == 'L'))
+					{
+					tmpString += tmpChar;
+					iDocument->CreateRootChildElement();
+					scanState = EWaitTokenEnd;
+					}
+				else if (tmpChar == '\t')
+					{
+					iDocument->CreateChildElement();
+					tmpString += tmpChar;
+					// this creates an element whose name is '/t'
+					// We add two '/t' to achieve the same number of fields in the Stdtimealignment and Zone lines
+					iDocument->AddAttribute(tmpString.c_str());	
+					iDocument->AddAttribute(tmpString.c_str());
+					tmpString.erase();	// clear the string for the next state
+					scanState = EWaitTokenStart;
+					}
+				else if (tmpChar == '\n')
+					{
+					// do nothing
+					}
+				else if ((tmpChar == KCharOlsonStartOfComment) || isspace(tmpChar))
+					{
+					// ignore the whole line
+					scanState = EWaitLineFeed;
+					}
+				else if (tmpChar != EOF)					
+					{
+					iDocument->HandleScanError(iFileName.c_str(),iLineNo,iColumnNo,tmpChar);
+					}
+				}
+			break;
+			
+			case EWaitTokenEnd:
+				{
+				// can we assume that there will always be a whitespace before a comment ('#')?
+				// how about 'CR'; the model assumes there will be a 'CRLF', perhaps that's not right
+				if ((tmpChar == ' ') || (tmpChar == '\t') || (tmpChar == '\n') || (tmpChar == EOF))
+					{
+					iDocument->AddAttribute(tmpString.c_str());
+					tmpString.erase();		// clear the string for the next state
+					if (tmpChar == '\n')
+						{
+						scanState = EWaitFirstChar;
+						if (firstChar != 'Z')
+							{
+							iDocument->CloseElement();
+							}
+						}
+					else
+						{
+						scanState = EWaitTokenStart;
+						}
+					}
+				else
+					{
+					std::string strValidChars = iValidChars;
+					int pos = strValidChars.find(tmpChar);
+					if ((!isalpha(tmpChar)) && (!isdigit(tmpChar)) && (pos == string::npos))
+						{
+						iDocument->HandleScanError(iFileName.c_str(),iLineNo,iColumnNo,tmpChar);
+						}
+					
+					tmpString += tmpChar;
+					}
+				}
+			break;
+			
+			case EWaitTokenStart:
+				{
+				if (tmpChar == '#')
+					{
+					// ignore the whole line
+					scanState = EWaitLineFeed;
+					//If a comment appears on a zone line we don't want to close the element
+					if (firstChar != 'Z')
+						{
+						iDocument->CloseElement();
+						}
+					}
+				else if ((tmpChar != ' ') && (tmpChar != '\t') && (tmpChar != '\n')) // valid char
+					{
+					tmpString += tmpChar;
+					scanState = EWaitTokenEnd;
+					}
+				}
+			break;
+			
+			case EWaitLineFeed:
+				{
+				// ignore every thing till the end of line
+				if (tmpChar == '\n')
+					{
+					scanState = EWaitFirstChar;
+					}
+				}
+			break;
+
+			default:
+				{
+				cout << "State Error!" << endl;
+				}
+			break;
+			}
+		}
+		while (tmpChar != EOF);
+		iDocument->CloseElement(); 
+	}
+
+//============================================================================
+// End of file
+//============================================================================