tzservices/tzloc/src/TzLocalizationResourceReader.cpp
changeset 0 2e3d3ce01487
child 81 676b6116ca93
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "TzLocalizationResourceReader.h"	//CTzLocalizationResourceReader
       
    17 #include "TzLocalizationDataTypes.h"		//CTzLocalizedCity etc
       
    18 #include "TzLocalizer.h"					//TTzLocalizerPanics
       
    19 
       
    20 #include <bautils.h>						//BaflUtils::NearestLanguageFile
       
    21 
       
    22 // Resource File locations
       
    23 _LIT(KTzLocalizationTimeZoneResourceFileName,"\\Resource\\TimeZoneLocalization\\timezones.rSC");
       
    24 _LIT(KTzLocalizationGroupResourceFileName,"\\Resource\\TimeZoneLocalization\\timezonegroups.rSC");
       
    25 _LIT(KFlashPath,"c:\\Resource\\TimeZoneLocalization\\");
       
    26 _LIT(KFlashDrive, "c:");
       
    27 _LIT(KRom, "z:");
       
    28 
       
    29 /**
       
    30 Allocates and constructs a new CTzLocalizationResourceReader object
       
    31 @return the newly constructed CTzLocalizationResourceReader
       
    32 @internalTechnology
       
    33 */
       
    34 CTzLocalizationResourceReader* CTzLocalizationResourceReader::NewL()
       
    35 	{
       
    36 	CTzLocalizationResourceReader* self = CTzLocalizationResourceReader::NewLC();
       
    37 	CleanupStack::Pop(self);
       
    38 	return self;
       
    39 	}
       
    40 
       
    41 /**
       
    42 Allocates and constructs a new CTzLocalizationResourceReader object
       
    43 The pointer to the new object is left on the cleanup stack
       
    44 @return the newly constructed CTzLocalizationResourceReader
       
    45 @internalTechnology
       
    46 */
       
    47 CTzLocalizationResourceReader* CTzLocalizationResourceReader::NewLC()
       
    48 	{
       
    49 	CTzLocalizationResourceReader* self = new (ELeave) CTzLocalizationResourceReader();
       
    50 	CleanupStack::PushL(self);
       
    51 	self->ConstructL();
       
    52 	return self;
       
    53 	}
       
    54 
       
    55 /**
       
    56 Second phase contructor
       
    57 @internalTechnology
       
    58 */
       
    59 void CTzLocalizationResourceReader::ConstructL()
       
    60 	{
       
    61 	User::LeaveIfError(iFs.Connect());
       
    62 
       
    63 	// Assign Panic category, in case it's needed
       
    64 	_LIT(KTzLocalizationCategory,"TZLOCALIZATION");
       
    65 	
       
    66 	// If resource files are found on flash drive,
       
    67 	// these will be used exclusively otherwise the 
       
    68 	// default ones on ROM will be used.	
       
    69 	CDir* dirList;
       
    70 	// Get a list of files on flash drive
       
    71 	TInt ret = iFs.GetDir(KFlashPath, KEntryAttMaskSupported, ESortNone, dirList);
       
    72 	CleanupStack::PushL(dirList);
       
    73 	TFileName* timeZoneResourceFileName = new(ELeave) TFileName;
       
    74 	CleanupStack::PushL(timeZoneResourceFileName);
       
    75 	TFileName* groupResourceFileName = new(ELeave) TFileName;
       
    76 	CleanupStack::PushL(groupResourceFileName);
       
    77 	TInt count = 0;
       
    78 	if(dirList != NULL)
       
    79 		{
       
    80 		count = dirList->Count();		
       
    81 		}
       
    82 	
       
    83 	// Use the files on ROM
       
    84 	if(ret == KErrPathNotFound || count == 0)
       
    85 		{
       
    86 		timeZoneResourceFileName->Format(KRom);
       
    87 		timeZoneResourceFileName->Append(KTzLocalizationTimeZoneResourceFileName);
       
    88 
       
    89 		groupResourceFileName->Format(KRom);
       
    90 		groupResourceFileName->Append(KTzLocalizationGroupResourceFileName);		
       
    91 		}
       
    92 	// Use the files on system drive
       
    93 	else if(ret == KErrNone)
       
    94 		{		
       
    95 		if(count > 0)
       
    96 			{
       
    97 			timeZoneResourceFileName->Format(KFlashDrive);
       
    98 			timeZoneResourceFileName->Append(KTzLocalizationTimeZoneResourceFileName);
       
    99 			
       
   100 			groupResourceFileName->Format(KFlashDrive);
       
   101 			groupResourceFileName->Append(KTzLocalizationGroupResourceFileName);
       
   102 			}
       
   103 		}
       
   104 	else
       
   105 		{
       
   106 		User::Leave(ret);
       
   107 		}
       
   108 	// Form the time zone resource filename using BaflUtils::NearestLanguageFile
       
   109 	BaflUtils::NearestLanguageFile(iFs,*timeZoneResourceFileName);
       
   110 
       
   111 	// Form the time zone group resource filename using BaflUtils::NearestLanguageFile
       
   112 	BaflUtils::NearestLanguageFile(iFs,*groupResourceFileName);
       
   113 	
       
   114 	// Open resource files - this can be done now, as it is opened in EFileShareReadersOnly mode		
       
   115 	TRAPD(timeZoneResErr,iTimeZoneResourceFile.OpenL(iFs,*timeZoneResourceFileName));
       
   116 	if(timeZoneResErr == KErrNotFound || timeZoneResErr == KErrPathNotFound)
       
   117 		{
       
   118 		User::Panic(KTzLocalizationCategory,CTzLocalizer::ETzLocalizerPanicResourceFileNotFound);
       
   119 		}
       
   120 	User::LeaveIfError(timeZoneResErr);		
       
   121 	iTimeZoneResourceFile.ConfirmSignatureL();
       
   122 		
       
   123 	TRAPD(groupResErr,iGroupResourceFile.OpenL(iFs,*groupResourceFileName));
       
   124 	
       
   125 	// Set iGroupResourceFileExists to so that it can be checked before 
       
   126 	// iGroupResourceFile is used
       
   127 	iGroupResourceFileExists = (groupResErr == KErrNone);
       
   128 	if(iGroupResourceFileExists)
       
   129 		{
       
   130 		iGroupResourceFile.ConfirmSignatureL();
       
   131 		iGroupResourceFileExists = ETrue;
       
   132 		}
       
   133 	CleanupStack::PopAndDestroy(3, dirList); // groupResourceFileName, timeZoneResourceFileName, dirList
       
   134 	}
       
   135 
       
   136 /**
       
   137 Destructor
       
   138 @internalTechnology
       
   139 */
       
   140 CTzLocalizationResourceReader::~CTzLocalizationResourceReader()
       
   141 	{
       
   142 	iTimeZoneResourceFile.Close();
       
   143 	if(iGroupResourceFileExists)
       
   144 		{
       
   145 		iGroupResourceFile.Close();
       
   146 		}
       
   147 	delete iResourceBuffer;
       
   148 	iFs.Close();
       
   149 	}
       
   150 
       
   151 /**
       
   152 Searches the time zone resource file for the given time zone ID. This function will
       
   153 leave if the specified ID is not found.
       
   154 @param aTimeZoneId time zone to search for.
       
   155 @return The resource ID or KErrNotFound.
       
   156 @internalTechnology
       
   157 */
       
   158 TInt CTzLocalizationResourceReader::FindTimeZoneResourceIdL(const TInt aTimeZoneId)
       
   159 	{
       
   160 	TInt initialOffset = FirstTimeZoneResourceIdL();
       
   161 
       
   162 	TInt idToCheck;
       
   163 
       
   164 	// Search through all resources
       
   165 	TInt i = 0;
       
   166 	while(iTimeZoneResourceFile.OwnsResourceIdL(initialOffset + i))
       
   167 		{
       
   168 		// Read current resource contents
       
   169 		BufferResourceL(iTimeZoneResourceFile,initialOffset + i);
       
   170 
       
   171 		// get the first int16 (WORD in resource STRUCT)
       
   172 		idToCheck = iResourceReader.ReadInt16();
       
   173 
       
   174 		// get rid of the buffer, it's no longer needed
       
   175 		ResetResourceBuffer();
       
   176 
       
   177 		// perform check
       
   178 		if(idToCheck == aTimeZoneId)
       
   179 			{
       
   180 			// return the current resource ID
       
   181 			return initialOffset + i;
       
   182 			}
       
   183 		++i;
       
   184 		}
       
   185 
       
   186 	// If it's got to here the aId hasn't been found, so leave
       
   187 	User::Leave(KErrNotFound);
       
   188 
       
   189 	return KErrNotFound;	// To satisfy compiler
       
   190 	}
       
   191 
       
   192 /**
       
   193 Returns the resource Id of the specified resource. This
       
   194 leaves if this resource is not found in the resource file.
       
   195 @param aResourceFile The resource file that the offset belongs to.
       
   196 @param aOffset The offset to return.
       
   197 @return The resource Id of the first resource containing localised data.
       
   198 @internalTechnology
       
   199 */
       
   200 TInt CTzLocalizationResourceReader::LocalizedResourceIdL(const RResourceFile& aResourceFile, const TTzResourceOffset aOffset)
       
   201 	{
       
   202 	TInt resourceIdToReturn = aResourceFile.Offset();
       
   203 
       
   204 	// Skip on the relevant number of resources, using the Offset enum
       
   205 	resourceIdToReturn += aOffset;
       
   206 
       
   207 	if(!aResourceFile.OwnsResourceIdL(resourceIdToReturn))
       
   208 		{
       
   209 		User::Leave(KErrNotFound);
       
   210 		}
       
   211 
       
   212 	return resourceIdToReturn;
       
   213 	}
       
   214 
       
   215 /**
       
   216 Returns the resource Id of the first time zone resource. This
       
   217 leaves if this resource is not found in the resource file.
       
   218 @return The resource Id of the first time zone resource.
       
   219 @internalTechnology
       
   220 */
       
   221 TInt CTzLocalizationResourceReader::FirstTimeZoneResourceIdL()
       
   222 	{
       
   223 	return LocalizedResourceIdL(iTimeZoneResourceFile,ETzFirstTimeZoneResource);
       
   224 	}
       
   225 
       
   226 /**
       
   227 Returns the resource Id of the first group resource. This
       
   228 leaves if this resource is not found in the resource file.
       
   229 This should only be called if iGroupResourceFile != NULL
       
   230 @return The resource Id of the first group resource.
       
   231 @internalTechnology
       
   232 */
       
   233 TInt CTzLocalizationResourceReader::FirstGroupResourceIdL()
       
   234 	{
       
   235 	return LocalizedResourceIdL(iGroupResourceFile,ETzFirstLocalizedResource);
       
   236 	}
       
   237 
       
   238 /**
       
   239 Returns the resource Id of the resource containing the default cached zone
       
   240 information. This leaves if this resource is not found in the resource file.
       
   241 @return The resource Id of the resource containing the default cached zone
       
   242 information.
       
   243 @internalTechnology
       
   244 */
       
   245 TInt CTzLocalizationResourceReader::CachedTimeZoneResourceIdL()
       
   246 	{
       
   247 	return LocalizedResourceIdL(iTimeZoneResourceFile,ETzFirstLocalizedResource);
       
   248 	}
       
   249 
       
   250 /**
       
   251 Fills iResourceBuffer with the resource specified by aResourceId and sets up
       
   252 iResourceReader to read from this resource. This should always be followed by a
       
   253 call to ResetResourceBuffer.  This function will leave if the requested resource
       
   254 is not found in the specified resource file.
       
   255 @param aResourceFile The resourcefile to read from.
       
   256 @param aResourceId The resource to read from.
       
   257 @internalTechnology
       
   258 */
       
   259 void CTzLocalizationResourceReader::BufferResourceL(const RResourceFile& aResourceFile, const TInt aResourceId)
       
   260 	{
       
   261 	if(!aResourceFile.OwnsResourceIdL(aResourceId))
       
   262 		{
       
   263 		User::Leave(KErrNotFound);
       
   264 		}
       
   265 
       
   266 	// Assign buffer for holding resource
       
   267 	iResourceBuffer = aResourceFile.AllocReadL(aResourceId);
       
   268 
       
   269 	// TResourceReader for getting data out of the buffer
       
   270 	iResourceReader.SetBuffer(iResourceBuffer);
       
   271 	}
       
   272 
       
   273 /**
       
   274 Resets the iResourceBuffer that contains the binary data of a resource.
       
   275 @internalTechnology
       
   276 */
       
   277 void CTzLocalizationResourceReader::ResetResourceBuffer()
       
   278 	{
       
   279 	delete iResourceBuffer;
       
   280 	iResourceBuffer = NULL;
       
   281 	}
       
   282 
       
   283 /**
       
   284 From MTzLocalizationReader
       
   285 Reads the specified time zone from the resource file.
       
   286 @param aTimeZoneId The ID of the time zone to return
       
   287 @return The specfied localized time zone object.
       
   288 @leave KErrNotFound Leaves if the requested Time Zone is not found.
       
   289 @internalTechnology
       
   290 */
       
   291 CTzLocalizedTimeZone* CTzLocalizationResourceReader::ReadTimeZoneL(const TInt aTimeZoneId)
       
   292 	{
       
   293 	TInt resourceId = FindTimeZoneResourceIdL(aTimeZoneId);
       
   294 
       
   295 	return DoReadTimeZoneL(resourceId);
       
   296 	}
       
   297 
       
   298 /**
       
   299 From MTzLocalizationReader
       
   300 Reads the time zone specified in aTzLocalizedId time
       
   301 zone from the resource file. If the resource ID is invalid, the time zone is
       
   302 read using the time zone ID.
       
   303 @param aTzLocalizedId The TTzLocalizedId specifying the resource ID and Time
       
   304 zone Id of the Time zone to return.
       
   305 @return The specfied localized time zone object.
       
   306 @leave KErrNotFound Leaves if the requested Time Zone is not found.
       
   307 @internalTechnology
       
   308 */
       
   309 CTzLocalizedTimeZone* CTzLocalizationResourceReader::ReadTimeZoneL(const TTzLocalizedId& aTzLocalizedId)
       
   310 	{
       
   311 	CTzLocalizedTimeZone* timeZoneToReturn;
       
   312 
       
   313 	// Check if the resource is in the time zone resource file
       
   314 	if(iTimeZoneResourceFile.OwnsResourceIdL(aTzLocalizedId.ResourceId()))
       
   315 		{
       
   316 		timeZoneToReturn = DoReadTimeZoneL(aTzLocalizedId.ResourceId());
       
   317 		}
       
   318 	// If the resource ID of aTzLocalizedId isn't found in the reource file,
       
   319 	// attempt to search for the timezone using the timezone id.
       
   320 	else
       
   321 		{
       
   322 		timeZoneToReturn = ReadTimeZoneL(aTzLocalizedId.TimeZoneId());
       
   323 		}
       
   324 
       
   325 	return timeZoneToReturn;
       
   326 	}
       
   327 
       
   328 /**
       
   329 From MTzLocalizationReader
       
   330 Reads all time zones from the resource file and appends them to the supplied array.
       
   331 @param aTimeZones An array that at the end of this function contains all time zones.
       
   332 @leave KErrNotFound Leaves if the no time zones are found in the resource file.
       
   333 @internalTechnology
       
   334 */
       
   335 void CTzLocalizationResourceReader::ReadAllTimeZonesL(CTzLocalizedTimeZoneArray& aTimeZones)
       
   336 	{
       
   337 	TInt initialOffset = FirstTimeZoneResourceIdL();
       
   338 
       
   339 	// Variables for us in loop
       
   340 	CTzLocalizedTimeZone* timeZone;
       
   341 
       
   342 	// Search through all resources
       
   343 	TInt i = 0;
       
   344 	while(iTimeZoneResourceFile.OwnsResourceIdL(initialOffset + i))
       
   345 		{
       
   346 		// Read new time zone
       
   347 		timeZone = DoReadTimeZoneL(initialOffset + i);
       
   348 		CleanupStack::PushL(timeZone);
       
   349 
       
   350 		// Add new time zone to the array (ownership is transferred into array)
       
   351 		aTimeZones.AppendL(timeZone);
       
   352 		CleanupStack::Pop(timeZone);
       
   353 		timeZone = NULL;
       
   354 
       
   355 		++i;
       
   356 		}
       
   357 
       
   358 	// If no owned resources were found - Leave
       
   359 	if(i == 0)
       
   360 		{
       
   361 		User::Leave(KErrNotFound);
       
   362 		}
       
   363 	}
       
   364 
       
   365 /**
       
   366 Reads in and returns a localized time zone found at the specified resource id.
       
   367 @param aResourceId The resource ID of the time zone in the time zone resource
       
   368 file
       
   369 @return The localized time zone found at the specified resource ID.
       
   370 @internalTechnology
       
   371 */
       
   372 CTzLocalizedTimeZone* CTzLocalizationResourceReader::DoReadTimeZoneL(const TInt aResourceId)
       
   373 	{
       
   374 	BufferResourceL(iTimeZoneResourceFile,aResourceId);
       
   375 
       
   376 	CTzLocalizedTimeZone* timeZone = CreateTimeZoneFromResourceL(aResourceId);
       
   377 
       
   378 	ResetResourceBuffer();
       
   379 
       
   380 	return timeZone;
       
   381 	}
       
   382 
       
   383 /**
       
   384 This does the actual reading of a localized time zone from the resource file.
       
   385 The iResourceReader MUST already have been set up with a call to
       
   386 BufferResourceL(iTimeZoneResourceFile,...), BEFORE this function is called.
       
   387 
       
   388 @return A CTzLocalizedTimeZone containing the localized time zone information
       
   389 that is currently found in iResourceReader.
       
   390 
       
   391 @internalTechnology
       
   392 */
       
   393 CTzLocalizedTimeZone* CTzLocalizationResourceReader::CreateTimeZoneFromResourceL(const TInt aResourceId)
       
   394 	{
       
   395 	// Read localized time zone data form the resource file in the correct order
       
   396 	TInt16 timeZoneId = (TInt16)iResourceReader.ReadInt16();
       
   397 	TPtrC standardName(iResourceReader.ReadTPtrC());
       
   398 	TPtrC daylightName(iResourceReader.ReadTPtrC());
       
   399 	TPtrC shortStandardName(iResourceReader.ReadTPtrC());
       
   400 	TPtrC shortDaylightName(iResourceReader.ReadTPtrC());
       
   401 
       
   402 	TTzLocalizedId tzlocalId(timeZoneId,aResourceId);
       
   403 	CTzLocalizedTimeZone* timeZone = CTzLocalizedTimeZone::NewL
       
   404 		(
       
   405 		tzlocalId,
       
   406 		standardName,
       
   407 		daylightName,
       
   408 		shortStandardName,
       
   409 		shortDaylightName
       
   410 		);
       
   411 
       
   412 	return timeZone;
       
   413 	}
       
   414 
       
   415 /**
       
   416 From MTzLocalizationReader Reads all cities from the resource file and appends
       
   417 them to the supplied array.
       
   418 @param aCities An array that at the end of this function will contain all
       
   419 cities contained in the resource file.
       
   420 
       
   421 @leave KErrNotFound Leaves if no cities are found.
       
   422 @internalTechnology
       
   423 */
       
   424 void CTzLocalizationResourceReader::ReadCitiesL(CTzLocalizedCityArray& aCities)
       
   425 	{
       
   426 	TInt initialOffset = FirstTimeZoneResourceIdL();
       
   427 
       
   428 	// Search through all resources
       
   429 	TInt i = 0;
       
   430 
       
   431 	while(iTimeZoneResourceFile.OwnsResourceIdL(initialOffset + i))
       
   432 		{
       
   433 		// Read new city into the city array
       
   434 		DoReadCitiesL(aCities, initialOffset + i);
       
   435 		++i;
       
   436 		}
       
   437 
       
   438 	// If no owned resources were found - Leave
       
   439 	if(i == 0)
       
   440 		{
       
   441 		User::Leave(KErrNotFound);
       
   442 		}
       
   443 	}
       
   444 
       
   445 /**
       
   446 From MTzLocalizationReader Read the cities that are in the specified time zone
       
   447 into the specified city array.
       
   448 @param aCities An array of cities that will contain the cities from the
       
   449 specified time zone.
       
   450 @param aTimeZoneId The ID of the time zone containing the cities to return,.
       
   451 @leave KErrNotFound Leaves if the specified time zone is not found or it
       
   452 contains no cities.
       
   453 @internalTechnology
       
   454 */
       
   455 void CTzLocalizationResourceReader::ReadCitiesL(CTzLocalizedCityArray& aCities, const TInt aTimeZoneId)
       
   456 	{
       
   457 	TInt resourceId = FindTimeZoneResourceIdL(aTimeZoneId);
       
   458 
       
   459 	DoReadCitiesL(aCities, resourceId);
       
   460 	}
       
   461 
       
   462 /**
       
   463 From MTzLocalizationReader Read the cities that are in the specified time zone
       
   464 into the specifed city array. If the resource ID is invalid, the correct
       
   465 resource ID is found in the resource file.
       
   466 @param An array of cities that will contain the cities from the specified time
       
   467 zone.
       
   468 @param aTzLocalizedId The TTzLocalizedId specifying of the time zone ID and
       
   469 resource ID of the time zone containing the cities to return,.
       
   470 @leave KErrNotFound Leaves if the specified time zone is not found or it
       
   471 contains no cities.
       
   472 @internalTechnology
       
   473 */
       
   474 void CTzLocalizationResourceReader::ReadCitiesL(CTzLocalizedCityArray& aCities, const TTzLocalizedId& aTzLocalizedId)
       
   475 	{
       
   476 	// Check if the resource is in the time zone resource file
       
   477 	if(iTimeZoneResourceFile.OwnsResourceIdL(aTzLocalizedId.ResourceId()))
       
   478 		{
       
   479 		DoReadCitiesL(aCities, aTzLocalizedId.ResourceId());
       
   480 		}
       
   481 	// search for aTzLocalizedId's timezone ID instead
       
   482 	else
       
   483 		{
       
   484 		ReadCitiesL(aCities, aTzLocalizedId.TimeZoneId());
       
   485 		}
       
   486 	}
       
   487 
       
   488 /**
       
   489 Reads in and adds the array of cities contained in the specified resource ID to
       
   490 the supplied city array
       
   491 @param The array of cities to which the the cities found in the time zone at
       
   492 the specified resource ID will be appended to.
       
   493 @param aResourceId The resource ID of the time zone that contains the cities to
       
   494 be read.
       
   495 @internalTechnology
       
   496 */
       
   497 void CTzLocalizationResourceReader::DoReadCitiesL(CTzLocalizedCityArray& aCities, const TInt aResourceId)
       
   498 	{
       
   499 	BufferResourceL(iTimeZoneResourceFile,aResourceId);
       
   500 
       
   501 	AddCityArrayFromResourceL(aCities,aResourceId);
       
   502 
       
   503 	ResetResourceBuffer();
       
   504 	}
       
   505 
       
   506 /**
       
   507 This does the actual reading of the localized cities from the resource file.
       
   508 The iResourceReader MUST already have been set up with a call to
       
   509 BufferResourceL(iTimeZoneResourceFile,...) BEFORE this function is called.
       
   510 @param aCities The array of cities to add the resource cities to.
       
   511 @param aResourceId The resource ID of the time zone containing the cities to
       
   512 read.
       
   513 @return An array of CTzLocalizedCity objects containing the cities that are
       
   514 currently found in iResourceReader.
       
   515 @internalTechnology
       
   516 */
       
   517 void CTzLocalizationResourceReader::AddCityArrayFromResourceL(CTzLocalizedCityArray& aCities, const TInt aResourceId)
       
   518 	{
       
   519 	// Eat up the localised time zone info from the resource
       
   520 	CTzLocalizedTimeZone* timeZone = CreateTimeZoneFromResourceL(aResourceId);
       
   521 
       
   522 	// Create a TTZlocalizedId to give to all the cities
       
   523 	TTzLocalizedId tzLocalizedId(timeZone->TimeZoneId(),aResourceId);
       
   524 
       
   525 	// Delete timeZone as it is no longer needed
       
   526 	delete timeZone;
       
   527 	timeZone = NULL;
       
   528 
       
   529 	// Get the number of cities (which automatically precedes the array as a WORD in the STRUCT)
       
   530 	TInt numCities = iResourceReader.ReadInt16();
       
   531 
       
   532 	// Leave if no cities are found
       
   533 	if(numCities < 1)
       
   534 		{
       
   535 		User::Leave(KErrNotFound);
       
   536 		}
       
   537 
       
   538 	// variables for use in the loop
       
   539 	TUint8 groupId;
       
   540 	TPtrC cityName;
       
   541 	CTzLocalizedCity* city;
       
   542 
       
   543 	// Loop through all the cities
       
   544 	for(TInt i = 0; i < numCities; ++i)
       
   545 		{
       
   546 		groupId = iResourceReader.ReadUint8();
       
   547 		cityName.Set(iResourceReader.ReadTPtrC());
       
   548 
       
   549 		city = CTzLocalizedCity::NewLC(cityName,tzLocalizedId,groupId);
       
   550         city->SetCityIndex(i);
       
   551 
       
   552 		aCities.AppendL(city);
       
   553 
       
   554 		CleanupStack::Pop(city);
       
   555 		city = NULL;
       
   556 		}
       
   557 	}
       
   558 
       
   559 /**
       
   560 From MTzLocalizationReader
       
   561 Reads the cities from the specified city group and adds them to the specified city array.
       
   562 @param aCities The array to add the cities from the specified group to.
       
   563 @param aGroupId The ID of the group containing the cities to return.
       
   564 @leave KErrNotFound Leaves if no groups are found in the resource file, or if
       
   565 the group numbering in the resource file is incorrect.
       
   566 @internalTechnology
       
   567 */
       
   568 void CTzLocalizationResourceReader::ReadCitiesInGroupL(CTzLocalizedCityArray& aCities, const TUint8 aGroupId)
       
   569 	{
       
   570 	if(iGroupResourceFileExists)
       
   571 	// Only do this if a groups resource file exists - otherwise no groups have been specified
       
   572 		{
       
   573 		TInt initialOffset = FirstTimeZoneResourceIdL();
       
   574 
       
   575 		// Variables for use in loop
       
   576 		TUint8 groupIdToCheck;
       
   577 		CTzLocalizedCityArray* citiesInTimeZone = CTzLocalizedCityArray::NewLC();
       
   578 		CTzLocalizedCity* currentCity;
       
   579 
       
   580 		// Loop through all time zones looking for cities in the requested group
       
   581 		TInt i = 0;
       
   582 		while(iTimeZoneResourceFile.OwnsResourceIdL(initialOffset + i))
       
   583 			{
       
   584 			DoReadCitiesL(*citiesInTimeZone, initialOffset + i);
       
   585 
       
   586 			// Check cities in this time zone to see if they are in the specified group
       
   587 			// in reverse order, because we remove as we go.
       
   588 			TInt numCitiesInZone = citiesInTimeZone->Count();
       
   589 			for(TInt j = numCitiesInZone - 1; j>=0; --j)
       
   590 				{
       
   591 				groupIdToCheck = citiesInTimeZone->At(j).GroupId();
       
   592 				currentCity = &(citiesInTimeZone->At(j));
       
   593 				
       
   594 				// Remove currentCity from citiesInTimeZone now, so that we 
       
   595 				// don't have to PopAndDestroy citiesInGroup and reallocate 
       
   596 				// once per while loop
       
   597 				citiesInTimeZone->Remove(j);
       
   598 
       
   599 				// If we are adding this city, move it from citiesInTimeZone to the aCities
       
   600 				if(groupIdToCheck == aGroupId)
       
   601 					{
       
   602 					aCities.AppendL(currentCity);
       
   603 					}
       
   604 				// otherwise get rid of it while we still have a pointer to it.
       
   605 				else
       
   606 					{
       
   607 					delete currentCity;
       
   608 					}
       
   609 				currentCity = NULL;
       
   610 				}
       
   611 			++i;
       
   612 			}
       
   613 		CleanupStack::PopAndDestroy(citiesInTimeZone);
       
   614 		citiesInTimeZone = NULL;
       
   615 		}
       
   616 	}
       
   617 
       
   618 /**
       
   619 From MTzLocalizationReader
       
   620 Reads all groups from the resource file and adds them to the specified group array.
       
   621 No groups are added to the array if none are found.
       
   622 @param aGroups The array to add the city groups to.
       
   623 @internalTechnology
       
   624 */
       
   625 void CTzLocalizationResourceReader::ReadAllGroupsL(CTzLocalizedCityGroupArray& aGroups)
       
   626 	{
       
   627 	if(iGroupResourceFileExists)
       
   628 		{
       
   629 		TInt initialOffset = FirstGroupResourceIdL();
       
   630 
       
   631 		// Variables for use in the loop
       
   632 		CTzLocalizedCityGroup* groupToAdd;
       
   633 
       
   634 		TInt i = 0;
       
   635 		while(iGroupResourceFile.OwnsResourceIdL(initialOffset + i))
       
   636 			{
       
   637 			groupToAdd = DoReadGroupL(initialOffset + i);
       
   638 
       
   639 			CleanupStack::PushL(groupToAdd);
       
   640 			aGroups.AppendL(groupToAdd);
       
   641 			// we are transferring ownership into the array			
       
   642 			CleanupStack::Pop(groupToAdd);
       
   643 			groupToAdd = NULL;
       
   644 
       
   645 			++i;
       
   646 			}
       
   647 		}
       
   648 	}
       
   649 
       
   650 /**
       
   651 From MTzLocalizationReader Reads the specified group and returns it.
       
   652 @param aGroupId The ID of the group to return.
       
   653 @return The specified city group object or NULL if the groups resource file
       
   654 does not exist.
       
   655 @leave KErrNotFound Leaves if the specified group ID is not found.
       
   656 @internalTechnology
       
   657 */
       
   658 CTzLocalizedCityGroup* CTzLocalizationResourceReader::ReadGroupL(const TUint8 aGroupId)
       
   659 	{
       
   660 	if(aGroupId < 1)
       
   661 		{
       
   662 		User::Leave(KErrArgument);
       
   663 		}
       
   664 
       
   665 	CTzLocalizedCityGroup* group = NULL;
       
   666 	
       
   667 	if(iGroupResourceFileExists)
       
   668 		{
       
   669 		TInt initialOffset = FirstGroupResourceIdL();
       
   670 
       
   671 		// The groups are numbered 1 to N, where N is the number of resources
       
   672 		TInt resourceToRead = initialOffset + aGroupId - 1;
       
   673 
       
   674 		// Assign a group to return
       
   675 		group = DoReadGroupL(resourceToRead);
       
   676 		}
       
   677 	else
       
   678 	// The group resource file doesn't exist - leave with KErrNotFound
       
   679 	// This means that it is transparent to the user, whether the groups 
       
   680 	// resource file exists or not, because this function already leaves
       
   681 	// with KErrNotFound if the specified Group ID is not found.
       
   682 		{
       
   683 		User::Leave(KErrNotFound);
       
   684 		}
       
   685 
       
   686 	return group;
       
   687 	}
       
   688 
       
   689 
       
   690 /**
       
   691 Reads in the group at the specified resource ID from the group resource file.
       
   692 Should only be called if iGroupResourceFile != NULL
       
   693 @param aResourceId The resource ID to get the group from.
       
   694 @return The group specifed by aResourceId.
       
   695 @leave KErrNotFound Leaves if the specified resouce ID is not found.
       
   696 @internalTechnology
       
   697 */
       
   698 CTzLocalizedCityGroup* CTzLocalizationResourceReader::DoReadGroupL(const TInt aResourceId)
       
   699 	{
       
   700 	BufferResourceL(iGroupResourceFile,aResourceId);
       
   701 
       
   702 	CTzLocalizedCityGroup* group = CreateGroupFromResourceL();
       
   703 
       
   704 	ResetResourceBuffer();
       
   705 
       
   706 	return group;
       
   707 	}
       
   708 
       
   709 /**
       
   710 This does the actual reading of a city group from the group resource file.
       
   711 The iResourceReader MUST already have been set up with a call to
       
   712 BufferResourceL(iGroupResourceFile,...), BEFORE this function is called.
       
   713 @param aResourceId The resource ID of the group to read.
       
   714 @return The group at the specifed resource ID in the the group resource file.
       
   715 @leave KErrNotFound Leaves if the specified resouce ID is not found.
       
   716 @internalTechnology
       
   717 */
       
   718 CTzLocalizedCityGroup* CTzLocalizationResourceReader::CreateGroupFromResourceL()
       
   719 	{
       
   720 	TUint8 groupId = iResourceReader.ReadUint8();
       
   721 	TPtrC groupName(iResourceReader.ReadTPtrC());
       
   722 
       
   723 	CTzLocalizedCityGroup* group = CTzLocalizedCityGroup::NewL(groupName,groupId);
       
   724 
       
   725 	return group;
       
   726 	}
       
   727 
       
   728 /**
       
   729 From MtzLocalizationReader
       
   730 Read and return the default city from the specified time zone.
       
   731 @param aTimeZoneId The ID of the time zone of the default city to return
       
   732 @return The defulat city of the specified time zone.
       
   733 @internalTechnology
       
   734 */
       
   735 CTzLocalizedCity* CTzLocalizationResourceReader::ReadDefaultCityL(const TInt aTimeZoneId)
       
   736 	{
       
   737 	// Read the cities from the specified resource
       
   738 	CTzLocalizedCityArray* cities = CTzLocalizedCityArray::NewLC();
       
   739 	ReadCitiesL(*cities,aTimeZoneId);
       
   740 
       
   741 	// Move first element (which is the default city) out of cities
       
   742 	// to stop it being deleted when cities is
       
   743 	CTzLocalizedCity* defaultCity = &(cities->At(0));
       
   744 	cities->Remove(0);
       
   745 
       
   746 	CleanupStack::PopAndDestroy(cities);
       
   747 
       
   748 	return defaultCity;
       
   749 	}
       
   750 
       
   751 /**
       
   752 From MtzLocalizationReader
       
   753 Read and return the default city from the specified time zone.
       
   754 @param aTzLocalizedId The TTzLocalizedId of the time zone of the default city to return
       
   755 @return The defulat city of the specified time zone.
       
   756 @internalTechnology
       
   757 */
       
   758 CTzLocalizedCity* CTzLocalizationResourceReader::ReadDefaultCityL(const TTzLocalizedId& aTzLocalizedId)
       
   759 	{
       
   760 	// Read the cities from the specified resource
       
   761 	CTzLocalizedCityArray* cities = CTzLocalizedCityArray::NewLC();
       
   762 	ReadCitiesL(*cities,aTzLocalizedId);
       
   763 
       
   764 	// Move first element (which is the default city) out of cities
       
   765 	// to stop it being deleted when cities is
       
   766 	CTzLocalizedCity* defaultCity = &(cities->At(0));
       
   767 	cities->Remove(0);
       
   768 
       
   769 	CleanupStack::PopAndDestroy(cities);
       
   770 
       
   771 	return defaultCity;
       
   772 	}
       
   773 
       
   774 /**
       
   775 From MTzLocalizationReader
       
   776 Read and return the specified cached zone.
       
   777 @param aFrequentlyUsedZone the cached zone to return
       
   778 @return The specified cached zone.
       
   779 @internalTechnology
       
   780 */
       
   781 CTzLocalizedTimeZone* CTzLocalizationResourceReader::ReadFrequentlyUsedZoneL(const CTzLocalizedTimeZone::TTzFrequentlyUsedZone aFrequentlyUsedZone)
       
   782 	{
       
   783 	// You cannot pass ECachedTimeZones in as the argument, because it is only
       
   784 	// used to keep count of how many cached zones there are.
       
   785 	__ASSERT_ALWAYS(aFrequentlyUsedZone != CTzLocalizedTimeZone::ECachedTimeZones, User::Leave(KErrArgument));
       
   786 
       
   787 	TInt offset = CachedTimeZoneResourceIdL();
       
   788 
       
   789 	BufferResourceL(iTimeZoneResourceFile,offset);
       
   790 
       
   791 	TInt defaultHomeZoneId = iResourceReader.ReadInt16();
       
   792 	TInt defaultInterestZoneId = iResourceReader.ReadInt16();
       
   793 	TInt defaultRecentZone1Id = iResourceReader.ReadInt16();
       
   794 	TInt defaultRecentZone2Id = iResourceReader.ReadInt16();
       
   795 
       
   796 	ResetResourceBuffer();
       
   797 
       
   798 	CTzLocalizedTimeZone* cachedTimeZone = NULL;
       
   799 
       
   800 	switch(aFrequentlyUsedZone)
       
   801 		{
       
   802 		case CTzLocalizedTimeZone::EHomeZone:
       
   803 			cachedTimeZone = ReadTimeZoneL(defaultHomeZoneId);
       
   804 		break;
       
   805 		case CTzLocalizedTimeZone::EInterestZone:
       
   806 			cachedTimeZone = ReadTimeZoneL(defaultInterestZoneId);
       
   807 		break;
       
   808 		case CTzLocalizedTimeZone::ERecentZone1:
       
   809 			cachedTimeZone = ReadTimeZoneL(defaultRecentZone1Id);
       
   810 		break;
       
   811 		case CTzLocalizedTimeZone::ERecentZone2:
       
   812 			cachedTimeZone = ReadTimeZoneL(defaultRecentZone2Id);
       
   813 		break;
       
   814 		case CTzLocalizedTimeZone::ECurrentZone:	// FALL THROUGH to default - current zone not supported
       
   815 		default:
       
   816 			User::Leave(KErrArgument);
       
   817 		}
       
   818 
       
   819 	return cachedTimeZone;
       
   820 	}
       
   821 
       
   822 /**
       
   823 From MTzLocalizationReader
       
   824 Read and return the city used to set thespecified cached zone.
       
   825 @param aFrequentlyUsedZone the cached zone specifying which city to return.
       
   826 @return The city used to set thespecified cached zone.
       
   827 @internalTechnology
       
   828 */
       
   829 CTzLocalizedCity* CTzLocalizationResourceReader::ReadCachedTimeZoneCityL(const CTzLocalizedTimeZone::TTzFrequentlyUsedZone aFrequentlyUsedZone)
       
   830 	{
       
   831 	// You cannot pass ECachedTimeZones in as the argument, because it is only
       
   832 	// used to keep count of how many cached zones there are.
       
   833 	__ASSERT_ALWAYS(aFrequentlyUsedZone != CTzLocalizedTimeZone::ECachedTimeZones, User::Leave(KErrArgument));
       
   834 
       
   835 	TInt offset = CachedTimeZoneResourceIdL();
       
   836 
       
   837 	BufferResourceL(iTimeZoneResourceFile,offset);
       
   838 
       
   839 	TInt defaultHomeZoneId = iResourceReader.ReadInt16();
       
   840 	TInt defaultInterestZoneId = iResourceReader.ReadInt16();
       
   841 	TInt defaultRecentZone1Id = iResourceReader.ReadInt16();
       
   842 	TInt defaultRecentZone2Id = iResourceReader.ReadInt16();
       
   843 
       
   844 	ResetResourceBuffer();
       
   845 
       
   846 	CTzLocalizedCity* cachedCity = NULL;
       
   847 
       
   848 	switch(aFrequentlyUsedZone)
       
   849 		{
       
   850 		case CTzLocalizedTimeZone::EHomeZone:
       
   851 			cachedCity = ReadDefaultCityL(defaultHomeZoneId);
       
   852 		break;
       
   853 		case CTzLocalizedTimeZone::EInterestZone:
       
   854 			cachedCity = ReadDefaultCityL(defaultInterestZoneId);
       
   855 		break;
       
   856 		case CTzLocalizedTimeZone::ERecentZone1:
       
   857 			cachedCity = ReadDefaultCityL(defaultRecentZone1Id);
       
   858 		break;
       
   859 		case CTzLocalizedTimeZone::ERecentZone2:
       
   860 			cachedCity = ReadDefaultCityL(defaultRecentZone2Id);
       
   861 		break;
       
   862 		case CTzLocalizedTimeZone::ECurrentZone:	// FALL THROUGH to default - current zone not supported
       
   863 		default:
       
   864 			User::Leave(KErrArgument);
       
   865 		}
       
   866 
       
   867 	return cachedCity;
       
   868 	}
       
   869 //============================================================================
       
   870 // End of file
       
   871 //============================================================================
       
   872 
       
   873