tzpcside/tzcompiler/Source/TzEntities.cpp
changeset 0 2e3d3ce01487
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tzpcside/tzcompiler/Source/TzEntities.cpp	Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,500 @@
+// 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 "TzEntities.h"
+#include "TzTables.h"
+#include "TZNode.h"
+#include "TZDocument.h"
+#include "TzHelpers.h"
+#include <iostream>
+#include <fstream>
+#include <cstdio>
+#include <algorithm>
+using namespace std;
+//============================================================================
+// CTzCpString::CTzCpString
+//============================================================================
+CTzCpString::CTzCpString(CTZDocument& aDocument)
+	:	CPersistedEntityWrapper(aDocument)
+	{
+	}
+//============================================================================
+// CTzCpString::ExternaliseL
+//============================================================================
+void CTzCpString::ExternaliseL(ofstream& aFilestream)
+	{
+	iOffset = (int)aFilestream.tellp() - iDocument.DbHeader()->iOffsetToStringTable;
+	TUint8 stringLength = iString.length();
+	aFilestream.write((char*)&stringLength,sizeof(stringLength));
+	aFilestream << iString.c_str();
+	}
+//============================================================================
+// CTzCpRegion::CTzCpRegion
+//============================================================================
+CTzCpRegion::CTzCpRegion(CTZDocument& aDocument)
+	:	CPersistedEntityWrapper(aDocument)
+	{
+	iRegionalZonesIndex = new CTzCpRegionalZonesIndex(aDocument);
+	}
+//============================================================================
+// CTzCpRegion::~CTzCpRegion
+//============================================================================
+CTzCpRegion::~CTzCpRegion()
+	{
+	for (int x = 0; x < iRegionalZonesIndex->iZoneIndex.size();++x)
+		{
+		iRegionalZonesIndex->iZoneIndex[x]->DecrRefCount();
+		}
+	
+	delete iRegionalZonesIndex;
+	}
+
+//============================================================================
+// CTzCpRegion::ExternaliseL
+//============================================================================
+void CTzCpRegion::ExternaliseL(ofstream& aFilestream)
+	{
+	iPersistedEntity.iOffsetToRegionName = iRegionNameRef->iOffset;
+	iPersistedEntity.iOffsetToRegionalZoneIndex = iRegionalZonesIndex->iOffset;
+	aFilestream.write((char*)&iPersistedEntity,sizeof(iPersistedEntity));
+	}
+//============================================================================
+// CTzCpRuleUse::CTzCpRuleUse
+// RuleUse constructor.
+//============================================================================
+CTzCpRuleUse::CTzCpRuleUse(CTZDocument& aDocument)
+	:	CPersistedEntityWrapper(aDocument)
+	{
+	}
+//============================================================================
+// CTzCpRuleUse::~CTzCpRuleUse 
+//============================================================================
+CTzCpRuleUse::~CTzCpRuleUse()
+	{
+	iRuleLetterPtr->DecrRefCount();
+	iRuleDefinitionPtr->DecrRefCount();
+	}
+//============================================================================
+// CTzCpRuleUse::AssembleL
+// Populates the CTzCpRuleUse from the current node.
+// RuleUse 'To' field may contain 'only' in the olsen files
+// This is to show the rule was in use for that year only.  In this case
+// we change the to field to match the from field.
+//============================================================================
+void CTzCpRuleUse::AssembleL(CTZNode& aNode)
+	{
+	iPersistedEntity.iFromYear	= atoi(aNode.NodeList()[2]->iValue.c_str());
+	if (aNode.NodeList()[3]->iValue.c_str()[0] == 'o')
+		{
+		iPersistedEntity.iUntilYear = iPersistedEntity.iFromYear;
+		}
+	else if (aNode.NodeList()[3]->iValue.c_str()[0] == 'm')
+		{
+		iPersistedEntity.iUntilYear = KMaxTUint16;
+		}
+	else 
+		{
+		iPersistedEntity.iUntilYear = atoi(aNode.NodeList()[3]->iValue.c_str());				
+		}
+	}
+//============================================================================
+// CTzCpLink::CTzCpLink
+//============================================================================
+CTzCpLink::CTzCpLink(CTZDocument& aDocument)
+	:	CPersistedEntityWrapper(aDocument)
+	{
+	}
+//============================================================================
+// CTzCpLink::AssembleL
+//============================================================================
+int CTzCpLink::AssembleL(CTZNode& aNode)
+	{
+	//Add the from value into the string table as is
+	//aNode.iNodeList[ELinkFormatFromZone]->iValue;
+	//Split the 'To' value into its region/zone parts
+	//'Region' is first part of a zone identity. eg 'Europe' in 'Europe/London'
+	//'Zone'  is second part of a zone identity. eg 'London' in 'Europe/London'
+	string linkString	= aNode.NodeList()[ELinkFormatToZone]->iValue;
+	string fromString	= aNode.NodeList()[ELinkFormatFromZone]->iValue;
+	int slashChar		= linkString.find('/',0);
+	iLinkString			= &iDocument.StringTable()->AddString(fromString);
+	iLinkString->IncrRefCount();
+
+	if (slashChar > 0)
+		{
+		iRegionString = &iDocument.StringTable()->AddString(linkString.substr(0,slashChar));
+		}
+	else
+		{
+		iRegionString = &iDocument.StringTable()->AddString("");
+		}
+	iRegionString->IncrRefCount();
+
+	iZoneString			= &iDocument.StringTable()->AddString(linkString.substr(slashChar+1));
+	iZoneString->IncrRefCount();
+	return 0;
+	}
+//============================================================================
+// CTzCpLink::ExternaliseL
+//============================================================================
+void CTzCpLink::ExternaliseL(ofstream& aFilestream)
+	{
+	iPersistedEntity.iOffsetToLinkName	= iLinkString->iOffset;
+	iPersistedEntity.iOffsetToZone		= iLinkedZoneOffset->iOffset;
+	aFilestream.write((char*)&iPersistedEntity,sizeof(iPersistedEntity));
+	}
+//============================================================================
+// CTzCpRuleUse::ExternaliseL
+//============================================================================
+void CTzCpRuleUse::ExternaliseL(ofstream& aFilestream)
+	{
+	iOffset = (int)aFilestream.tellp() - iDocument.DbHeader()->iOffsetToRuleUsesTable;
+	iPersistedEntity.iOffsetToRuleDefinition	= iRuleDefinitionPtr->iOffset;
+	iPersistedEntity.iOffsetToRuleLetterString	= iRuleLetterPtr->iOffset;
+	aFilestream.write((char*)&iPersistedEntity,sizeof(iPersistedEntity));
+	}
+//============================================================================
+// CTzCpRuleDefinition::CTzCpRuleDefinition
+//============================================================================
+CTzCpRuleDefinition::CTzCpRuleDefinition(CTZDocument& aDocument)
+	:	CPersistedEntityWrapper(aDocument)
+	{
+	}
+//============================================================================
+// CTzCpRuleDefinition::AssembleL
+// Populates the CTzCpRuleDefinition from the current node
+//============================================================================
+int CTzCpRuleDefinition::AssembleL(CTZNode& aNode)
+	{
+	//Set the time offset
+	//Assuming that the 'SAVE' field in a rule is of the format H:MM
+	string tmpString	= aNode.NodeList()[ERuleFormatSave]->iValue;
+	int breakAt			= tmpString.find_first_of(':');
+	int hours			= atoi(tmpString.c_str());
+	int minutes			= 0;
+	if (tmpString.length() > 1)
+		{
+		minutes			= atoi(tmpString.substr(2).c_str());
+		}
+	iPersistedEntity.iStdTimeOffset		= (hours*60) + minutes;
+
+	//Set the month ( 0 - 11)
+	iPersistedEntity.iMonth = CTzCpHelpers::GetMonth(aNode.NodeList()[ERuleFormatIn]->iValue);
+	
+	//Set the day rule
+	tmpString = aNode.NodeList()[ERuleFormatOn]->iValue;
+	string searchDayAfterString  = ">=";
+	string searchDayBeforeString = "<=";
+
+	if (tmpString.c_str()[0] == 'l')
+		{
+		iPersistedEntity.iDayRule = ETzDayInLastWeekOfMonth;
+		}
+	else if (strstr(tmpString.c_str(),searchDayAfterString.c_str()) != NULL)
+		{
+		iPersistedEntity.iDayRule = ETzDayAfterDate;
+		}
+	else if (strstr(tmpString.c_str(),searchDayBeforeString.c_str()) != NULL)
+		{
+		iPersistedEntity.iDayRule = ETzDayBeforeDate;
+		}
+	else
+		{
+		iPersistedEntity.iDayRule = ETzFixedDate;
+		}
+
+	//Set the day of month.  This is only required if the day rule is 
+	//ETzFixedDate, EDayBeforeDate or EDayAfterDate.  Defaults to 0.
+	TInt tmpDay;
+	switch (iPersistedEntity.iDayRule)
+		{
+		case ETzFixedDate:
+			tmpDay = atoi(tmpString.c_str());
+			tmpDay = tmpDay ? tmpDay-1 : 0; // OG: zero-based Day (as used in TDateTime in Symbian OS)
+			iPersistedEntity.iDayOfMonth = tmpDay;
+		break;
+		case ETzDayBeforeDate:
+		case ETzDayAfterDate:
+			tmpDay = atoi(tmpString.substr(5).c_str());
+			tmpDay = tmpDay ? tmpDay-1 : 0; // OG: zero-based Day (as used in TDateTime in Symbian OS)
+			iPersistedEntity.iDayOfMonth = tmpDay;
+		break;
+		default:
+			iPersistedEntity.iDayOfMonth = 0;
+		break;
+		}
+	
+	//Set the day of the week.  This only applies if day rule != ETzFixedDate
+	iPersistedEntity.iDayOfWeek = CTzCpHelpers::GetDay(tmpString);
+	
+	//Set the time of change (in minutes)
+	tmpString	= aNode.NodeList()[ERuleFormatAt]->iValue;
+	iPersistedEntity.iTimeOfChange = CTzCpHelpers::GetTimeOfDayInMinutes(tmpString);
+
+	//set the time reference
+	iPersistedEntity.iTimeReference = CTzCpHelpers::GetTimeReference(tmpString);
+	
+	//Spare flags - these will probably be used for implementing write access 
+	//if required
+	//iPersistedEntity.iReferenceCount	= 0;	//Unused for now
+	//iPersistedEntity.iStatus			= 0;	//Unused for now
+	return 0;
+	}
+//============================================================================
+// CTzCpRuleDefinition::ExternaliseL
+//============================================================================
+void CTzCpRuleDefinition::ExternaliseL(ofstream& aFilestream)
+	{
+	iOffset = (int)aFilestream.tellp() - iDocument.DbHeader()->iOffsetToRuleDefinitionsTable;
+	aFilestream.write((char*)&iPersistedEntity,sizeof(iPersistedEntity));
+	}
+//============================================================================
+// CTzCpRuleSet::CTzCpRuleSet
+//============================================================================
+CTzCpRuleSet::CTzCpRuleSet(CTZDocument& aDocument,std::string aRuleSetName)
+	:	CPersistedEntityWrapper(aDocument) , iName(aRuleSetName)
+	{
+	}
+//============================================================================
+// CTzCpRuleSet::~CTzCpRuleSet
+//============================================================================
+CTzCpRuleSet::~CTzCpRuleSet()
+	{
+	int size = RuleUses().size();
+	for (int x = 0; x < size;x++)
+		{
+		iVector[x]->DecrRefCount();
+		}
+	}
+
+//============================================================================
+// CTzCpRuleSet::ExternaliseL
+//============================================================================
+void CTzCpRuleSet::ExternaliseL(ofstream& aFilestream)
+	{
+	iOffset = (int)aFilestream.tellp() - iDocument.DbHeader()->iOffsetToRuleSetsTable;
+	iPersistedEntity.iNumberOfRuleUses = iVector.size();
+
+	aFilestream.write((char*)&iPersistedEntity,sizeof(iPersistedEntity)-sizeof(iPersistedEntity.iOffsetsToRuleUses));
+	TUint16 ruleUseOffset;
+	for (int x = 0; x < iPersistedEntity.iNumberOfRuleUses;x++)
+		{
+		ruleUseOffset = iVector[x]->iOffset;
+		aFilestream.write((char*)&ruleUseOffset,sizeof(ruleUseOffset));
+		}
+	}
+//============================================================================
+// CTzCpRuleSet::AddRuleUse
+// Adds the index of the CTzCpRuleUse in the rule use table
+// to the collection of rule uses
+//============================================================================
+void CTzCpRuleSet::AddRuleUse(CTzCpRuleUse& aRuleUse)
+	{
+	iVector.push_back(&aRuleUse); //The address of the ruleuse
+	}
+//============================================================================
+// CTzCpRegionalZonesIndex::CTzCpRegionalZoneIndex
+//============================================================================
+CTzCpRegionalZonesIndex::CTzCpRegionalZonesIndex(CTZDocument& aDocument)
+	:	CPersistedEntityWrapper(aDocument)
+	{
+	}
+
+//============================================================================
+// CTzCpRegionalZonesIndex::ExternaliseL
+//============================================================================
+void CTzCpRegionalZonesIndex::ExternaliseL(ofstream& aFilestream)
+	{
+	iOffset = (int)aFilestream.tellp() - iDocument.DbHeader()->iOffsetToRegionalZonesTable;
+
+	// sort zone index alphabetically before externalising it
+	sort(iZoneIndex.begin(),iZoneIndex.end(),CTzCpZone::SZoneNameSort());
+
+	iPersistedEntity.iNumberOfZones = iZoneIndex.size();
+	aFilestream.write((char*)&iPersistedEntity,sizeof(iPersistedEntity) - sizeof(iPersistedEntity.iOffsetsToZones));
+	//Write out the zone offsets
+	for (int x = 0; x < iPersistedEntity.iNumberOfZones;x++)
+		{
+		TUint16 zoneOffset = iZoneIndex[x]->iOffset;
+		aFilestream.write((char*)&zoneOffset,sizeof(zoneOffset));
+		}
+	}
+//============================================================================
+// CTzCpRegionalZonesIndex::AddZoneIndex
+// We add the address of the reference to avoid a double deletion - 
+// this zone will already 
+//============================================================================
+void CTzCpRegionalZonesIndex::AddZoneIndex(CTzCpZone& aZoneRef)
+	{
+	iZoneIndex.push_back(&aZoneRef);
+	}
+//============================================================================
+// CTzCpZone::CTzCpZone
+//============================================================================
+CTzCpZone::CTzCpZone(CTZDocument& aDocument)
+	:	CPersistedEntityWrapper(aDocument)
+	{
+	}
+//============================================================================
+// CTzCpZone::~CTzCpZone
+// When we destroy a zone, we need to decrement all its referenced entity 
+// reference counts by 1.
+//============================================================================
+CTzCpZone::~CTzCpZone()
+	{
+	iRegionNameRef->DecrRefCount();
+	iZoneNameRef->DecrRefCount();
+
+	for (int x = 0; x < iTimeAlignments.size();++x)
+		{
+		iTimeAlignments[x]->DecrRefCount();
+		}
+	}
+
+//============================================================================
+// CTzCpZone::ExternaliseL
+//============================================================================
+void CTzCpZone::ExternaliseL(ofstream& aFilestream)
+	{
+	iOffset = (int)aFilestream.tellp() - iDocument.DbHeader()->iOffsetToZones;
+	iPersistedEntity.iLocationId				= iLocationId;
+	iPersistedEntity.iOffsetToZoneName			= iZoneNameRef->iOffset;
+	iPersistedEntity.iOffsetToRegionName		= iRegionNameRef->iOffset;
+	iPersistedEntity.iNumberOfStdTimeAlignments	= iTimeAlignments.size();
+
+	aFilestream.write((char*)&iPersistedEntity,sizeof(iPersistedEntity)-sizeof(iPersistedEntity.iOffsetsToTimeAlignments));
+	
+	//Externalise the time alignment offsets
+	for (int x = 0; x < iPersistedEntity.iNumberOfStdTimeAlignments; x++)
+		{
+		TUint16 stdoffset = iTimeAlignments[x]->iOffset;
+		aFilestream.write((char*)&stdoffset,sizeof(stdoffset));
+		}
+	}
+//============================================================================
+// CTzCpStdTimeAlignment::CTzCpStdTimeAlignment
+//============================================================================
+CTzCpStdTimeAlignment::CTzCpStdTimeAlignment(CTZDocument& aDocument)
+	:	CPersistedEntityWrapper(aDocument)
+	{
+	}
+//============================================================================
+// CTzCpStdTimeAlignment::~CTzCpStdTimeAlignment
+// When we destroy a CTzCpStdTimeAlignment we need to decrement all its 
+// referenced entity reference counts by 1.
+//============================================================================
+CTzCpStdTimeAlignment::~CTzCpStdTimeAlignment()
+	{
+	iOffsetToTimeZoneFormatName->DecrRefCount();
+
+	for (int x = 0; x < iOffsetsToTimeZonesShortNames.size();++x)
+		{
+		iOffsetsToTimeZonesShortNames[x]->DecrRefCount();
+		}
+		iRuleSet->DecrRefCount();
+	}
+//============================================================================
+// CTzCpStdTimeAlignment::AssembleL
+// Populates the CTzCpStdTimeAlignment from the current node
+//============================================================================
+int CTzCpStdTimeAlignment::AssembleL(CTZNode& aNode)
+	{
+	string tmpString;
+	//Until Year
+	if (EZoneFormatUntilYear >= aNode.NodeList().size())
+		{
+		iPersistedEntity.iUntilYear	= KMaxYear;
+		}
+	else
+		{
+		iPersistedEntity.iUntilYear	= atoi(aNode.NodeList()[EZoneFormatUntilYear]->iValue.c_str());
+		}
+	//Until Month
+	if (EZoneFormatUntilMonth >= aNode.NodeList().size())
+		{
+		iPersistedEntity.iUntilMonth	= 0;
+		}
+	else
+		{
+		tmpString = aNode.NodeList()[EZoneFormatUntilMonth]->iValue;
+		if (tmpString.empty())
+			iPersistedEntity.iUntilMonth = 0;
+		else
+			iPersistedEntity.iUntilMonth = CTzCpHelpers::GetMonth(tmpString);
+		}
+	//Until DayOfMonth
+	if (EZoneFormatUntilDay >= aNode.NodeList().size())
+		{
+		iPersistedEntity.iUntilDayOfMonth	= 0;
+		}
+	else
+		{
+		tmpString = aNode.NodeList()[EZoneFormatUntilDay]->iValue;
+		TInt tmpDay = atoi(aNode.NodeList()[EZoneFormatUntilDay]->iValue.c_str());
+		tmpDay = tmpDay ? tmpDay-1 : 0; // zero-based Day (as used in TDateTime in Symbian OS)
+		iPersistedEntity.iUntilDayOfMonth	= tmpDay;
+		}
+	//Until minutes
+	//Until Time Reference
+	if (EZoneFormatUntilMinutes >= aNode.NodeList().size())
+		{
+		iPersistedEntity.iUntilTimeInMinutes = 0;
+		iPersistedEntity.iUntilTimeReference = 0;
+		}
+	else
+		{
+		tmpString = aNode.NodeList()[EZoneFormatUntilMinutes]->iValue;
+		iPersistedEntity.iUntilTimeInMinutes = CTzCpHelpers::GetTimeOfDayInMinutes(tmpString);
+		iPersistedEntity.iUntilTimeReference = CTzCpHelpers::GetTimeReference(tmpString);
+		}
+	//GMTOffset in minutes
+	tmpString = aNode.NodeList()[EZoneFormatGMTOffset]->iValue;
+	iPersistedEntity.iUtcOffset = CTzCpHelpers::GetTimeOfDayInMinutes(tmpString);
+
+	//Set these in the document after completion.
+	//Offset to ruleset
+	iPersistedEntity.iOffsetToRuleSet = 0;
+	//offset to timezoneformat	
+	iPersistedEntity.iOffsetToTimeZoneFormatName = 0;
+	return 0;
+	}
+//============================================================================
+// CTzCpStdTimeAlignment::ExternaliseL
+//============================================================================
+void CTzCpStdTimeAlignment::ExternaliseL(ofstream& aFilestream)
+	{
+	iOffset = (int)aFilestream.tellp() - iDocument.DbHeader()->iOffsetToStdTimeAlignmentsTable;
+	//Retrieve the ruleset offset
+	iPersistedEntity.iOffsetToRuleSet = iRuleSet->iOffset;
+	 //Retrieve the time zone format name offset
+	iPersistedEntity.iOffsetToTimeZoneFormatName = iDocument.StringTable()->Strings()[iPersistedEntity.iOffsetToTimeZoneFormatName]->iOffset;
+	//Set the number of time zones
+	iPersistedEntity.iNumberOfTimeZones = iOffsetsToTimeZonesShortNames.size();
+
+	aFilestream.write((char*)&iPersistedEntity,sizeof(iPersistedEntity)-sizeof(iPersistedEntity.iOffsetsToTimeZones));
+	//Write the time zone offsets
+	int size = iOffsetsToTimeZonesShortNames.size();
+	for (int x = 0; x < size; x++)
+		{
+		TUint16 offsetToTimeZone = iOffsetsToTimeZonesShortNames[x]->iOffset;
+		aFilestream.write((char*)&offsetToTimeZone,sizeof(offsetToTimeZone));
+		}
+	}
+//============================================================================
+// End of file
+//============================================================================