imaging/imagingplugins/codecs/JPEGCodec/Exif/ifdgeneralentry.cpp
changeset 0 5752a19fdefe
equal deleted inserted replaced
-1:000000000000 0:5752a19fdefe
       
     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 "ifdgeneral.h"
       
    17 #include "ifdgeneralentry.h"
       
    18 #include "ExifTagDescriptions.h"
       
    19 #include "ExifTagHelper.h"
       
    20 #include "ImageUtils.h"
       
    21 
       
    22 const TUint KAnySize = 0; // For tags that have no upper limit on their content size.
       
    23 
       
    24 GLDEF_C void Cleanup(TAny *aObject)
       
    25       {
       
    26       User::Free(aObject);
       
    27       }
       
    28  
       
    29 // Sets the value/offset field (four bytes) of this Ifd entry.
       
    30 void CIfdGeneralEntry::SetValueOffset(const TUint8* aValueOffset)
       
    31 	{
       
    32 	/*
       
    33 	Need to check the type of data, and store accordingly - see Exif2.2 specification pp.14: 
       
    34 	"If the value is < 4 bytes, the value is stored in the 4 byte area starting from the left,
       
    35 	i.e. from the lower end of the byte offset.  For example, in big endian format, if the
       
    36 	type is SHORT and the value is 1, it is recorded as 00010000.H."
       
    37 	*/
       
    38 	TUint totalSize = KDataFormatSize[Format()] * ComponentCount();
       
    39 	
       
    40 	switch(totalSize)
       
    41 		{
       
    42 		case (sizeof(TUint8)): // 1 byte in length.
       
    43 			Mem::Copy(iDirEntryData+KValueOffsetFieldPosition, aValueOffset, sizeof(TUint8));
       
    44 			Mem::FillZ(iDirEntryData+KValueOffsetFieldPosition+sizeof(TUint8), KThreeBytes); // Fill remaining 3 bytes with zeros.
       
    45 			break;
       
    46 		case (sizeof(TUint16)): // 2 bytes in length.
       
    47 			{
       
    48 			const TUint16* shortValue = reinterpret_cast<const TUint16*>(aValueOffset);
       
    49 			Mem::Copy(iDirEntryData+KValueOffsetFieldPosition, shortValue, sizeof(TUint16)); // Fill remaining 2 bytes with zeros.
       
    50 			Mem::FillZ(iDirEntryData+KValueOffsetFieldPosition+sizeof(TUint16), sizeof(TUint16));
       
    51 			}
       
    52 			break;
       
    53 		case KThreeBytes: // 3 bytes in length.  Fall through.
       
    54 		case (sizeof(TUint32)): // 4 bytes in length.
       
    55 			{
       
    56 			const TUint32* longValue = reinterpret_cast<const TUint32*>(aValueOffset);
       
    57 			Mem::Copy(iDirEntryData+KValueOffsetFieldPosition, longValue, sizeof(TUint32));
       
    58 			if(totalSize == KThreeBytes)
       
    59 				{
       
    60 				Mem::FillZ(iDirEntryData+KValueOffsetFieldPosition+KThreeBytes, sizeof(TUint8));
       
    61 				}
       
    62 			}
       
    63 			break;
       
    64 		}
       
    65 	}
       
    66 
       
    67 
       
    68 // Sets the tag field (two bytes) of this Ifd entry.
       
    69 void CIfdGeneralEntry::SetTag(const TUint aTag)
       
    70 	{
       
    71 	Mem::Copy(iDirEntryData, &aTag, KSizeOfTagField);
       
    72 	}
       
    73 
       
    74 // Sets the format field (two bytes) of this Ifd entry.
       
    75 void CIfdGeneralEntry::SetFormat(const TUint aFormat)
       
    76 	{
       
    77 	Mem::Copy(iDirEntryData+KFormatFieldPosition, &aFormat, KSizeOfFormatField);
       
    78 	}
       
    79 
       
    80 // Sets the component count field (four bytes) of this Ifd entry.
       
    81 void CIfdGeneralEntry::SetComponentCount(const TUint aComponentCount)
       
    82 	{
       
    83 	Mem::Copy(iDirEntryData+KComponentCountFieldPosition, &aComponentCount, KSizeOfComponentCountField);
       
    84 	}
       
    85 	
       
    86 // Returns the tag value of this Ifd entry.
       
    87 TUint CIfdGeneralEntry::Tag()
       
    88 	{
       
    89 	return PtrReadUtil::ReadUint16(iDirEntryData);
       
    90 	}
       
    91 
       
    92 // Returns the format of this Ifd entry.
       
    93 TUint CIfdGeneralEntry::Format()
       
    94 	{
       
    95 	return PtrReadUtil::ReadUint16(iDirEntryData+KFormatFieldPosition);
       
    96 	}
       
    97 	
       
    98 // Returns the component count of this Ifd entry.
       
    99 TUint CIfdGeneralEntry::ComponentCount()
       
   100 	{
       
   101 	return PtrReadUtil::ReadUint32(iDirEntryData+KComponentCountFieldPosition);
       
   102 	}
       
   103 
       
   104 // Returns the value/offset field of this Ifd entry.
       
   105 TUint CIfdGeneralEntry::ValueOffset()
       
   106 	{
       
   107 	return PtrReadUtil::ReadUint32(iDirEntryData+KValueOffsetFieldPosition);
       
   108 	}
       
   109 
       
   110 // Returns a pointer to the data that the value/offset points to.
       
   111 const TUint8* CIfdGeneralEntry::ActualValue()
       
   112 	{
       
   113 	// If there is data that the value/offset field points to, then return a pointer to it.
       
   114 	return iActualData;
       
   115 	}
       
   116 
       
   117 TInt CIfdGeneralEntry::ExtraSize()
       
   118 	{
       
   119 	return TotalSize() - KMinimumIfdEntrySize;
       
   120 	}
       
   121 
       
   122 CIfdGeneralEntry* CIfdGeneralEntry::NewLC()
       
   123 	{
       
   124 	CIfdGeneralEntry* self = new (ELeave) CIfdGeneralEntry;
       
   125 	CleanupStack::PushL(self);
       
   126 	self->ConstructL();
       
   127 	return self;
       
   128 	}
       
   129 	
       
   130 
       
   131 CIfdGeneralEntry* CIfdGeneralEntry::NewLC(const TUint& aTag, const TUint& aFormat, const TUint& aComponentCount, const TUint8* aParam, CIfdGeneral* aIfd)
       
   132 	{
       
   133 	TBool ignored; // NewLC is called by functions that don't require checking if the tag is known or not
       
   134 	CIfdGeneralEntry* self = new (ELeave) CIfdGeneralEntry();
       
   135 	CleanupStack::PushL(self);
       
   136 	self->ConstructL(aTag, aFormat, aComponentCount, aParam, aIfd, ignored);
       
   137 	return self;
       
   138 	}
       
   139 	
       
   140 CIfdGeneralEntry* CIfdGeneralEntry::NewL(const TUint& aTag, const TUint& aFormat, const TUint& aComponentCount, const TUint8* aParam, CIfdGeneral* aIfd, TBool& aUnknownTag)
       
   141 	{
       
   142 	CIfdGeneralEntry* self = new (ELeave) CIfdGeneralEntry();
       
   143 	CleanupStack::PushL(self);
       
   144 	self->ConstructL(aTag, aFormat, aComponentCount, aParam, aIfd, aUnknownTag);
       
   145 	CleanupStack::Pop(self);
       
   146 	return self;
       
   147 	}
       
   148 
       
   149 CIfdGeneralEntry::CIfdGeneralEntry()
       
   150 	{
       
   151 	}
       
   152 
       
   153 void CIfdGeneralEntry::ConstructL()
       
   154 	{
       
   155 	iDirEntryData = static_cast<TUint8*>(User::Alloc(KMinimumIfdEntrySize));
       
   156 	if(iDirEntryData == NULL)
       
   157 		{
       
   158 		User::Leave(KErrNoMemory);
       
   159 		}
       
   160 	}
       
   161 
       
   162 void CIfdGeneralEntry::ConstructL(const TUint& aTag, const TUint& aFormat, TUint aComponentCount, const TUint8* aValueOffset, CIfdGeneral* aIfd, TBool& aUnknownTag)
       
   163 	{
       
   164 	// the code here used to check if the tag was invalid and if so leave with KErrArgument
       
   165 	// now if the tag is invalid it just bypasses the further checks
       
   166 	// this is to future proof against versions of exif which introduce additional tags
       
   167 	// to the exif 2.2 spec
       
   168 	TUint expectedComponentCount = 0;
       
   169 
       
   170 	ASSERT(aIfd);
       
   171 		
       
   172 	iIfd = aIfd;
       
   173 	if(aIfd->FindTag(aTag))
       
   174 		{
       
   175 		// Known tag
       
   176 		aUnknownTag = EFalse;
       
   177 		
       
   178 		TUint expectedFormat = 0;
       
   179 		
       
   180 		User::LeaveIfError(iIfd->GetFormat(aTag, expectedFormat));
       
   181 		User::LeaveIfError(iIfd->GetComponentCount(aTag, expectedComponentCount));
       
   182 
       
   183 		if ((aTag == KTagA002[ETagValue])||
       
   184 			(aTag == KTagA003[ETagValue])||
       
   185 			(aTag == KTag1001[ETagValue]) || 
       
   186 			(aTag == KTag1002[ETagValue]))
       
   187 			{
       
   188 			//do nothing Tag A002 A003 can be short or long 
       
   189 			// Interop Tag 1001 and 1002 can be unsigned short or long
       
   190 			}
       
   191 		else if(expectedFormat != aFormat)
       
   192 			{
       
   193 			User::Leave(KErrArgument);
       
   194 			}
       
   195 	
       
   196 		if(expectedComponentCount != 0) // If 0, then size is undefined.
       
   197 			{
       
   198 			if(aComponentCount > expectedComponentCount)
       
   199 				{
       
   200 				User::Leave(KErrNotSupported);
       
   201 				}
       
   202 			}
       
   203 		
       
   204 		// Check overflow.
       
   205 		if(aFormat >= KDataFormatSizeLength)
       
   206 			{
       
   207 			User::Leave(KErrOverflow);
       
   208 			}
       
   209 		}
       
   210 	else
       
   211 		{
       
   212 		// Unknown tag
       
   213 		// Create this entry anyway as it may be an extension to the EXIF standard
       
   214 		// but inform the caller
       
   215 		aUnknownTag = ETrue;
       
   216 		}
       
   217 	iDirEntryData = static_cast<TUint8*>(User::AllocL(KMinimumIfdEntrySize)); // Alloc standard entry size.
       
   218 	Mem::FillZ(iDirEntryData, KMinimumIfdEntrySize);
       
   219 	SetTag(aTag); // Simply set the tag.
       
   220 	SetFormat(aFormat); // Set the format (associated with the tag).
       
   221 	SetComponentCount(aComponentCount);	
       
   222 		
       
   223 	// Determine if we have a value or an offset to a value.
       
   224 	TInt bytes = KDataFormatSize[aFormat];
       
   225 	TUint size = aComponentCount * bytes;
       
   226 	TUint8* tempValue = NULL;
       
   227 	if(IsStringFormat())
       
   228 		{
       
   229 		tempValue = static_cast<TUint8*>(User::AllocL(size+sizeof(TUint8)));
       
   230 		Mem::Copy(tempValue, aValueOffset, size);
       
   231 		
       
   232 		if (tempValue[size-1] != KNullCharacter)
       
   233 			{	
       
   234 			Mem::Copy(tempValue+size, &KNullCharacter, sizeof(KNullCharacter));	
       
   235 			size++;
       
   236 			aComponentCount++;
       
   237 			SetComponentCount(aComponentCount);	
       
   238 			}
       
   239 			
       
   240 		aValueOffset = tempValue;
       
   241 		}				
       
   242 	else if(IsRationalFormat())
       
   243 		{
       
   244 		//Since rational default values only store the numerator in the CExifTag constant we
       
   245 		//must set the denominator.
       
   246 		if(expectedComponentCount == 1)
       
   247 			{
       
   248 			tempValue = static_cast<TUint8*>(User::AllocL(KSizeOfRational));
       
   249 			Mem::Copy(tempValue, aValueOffset, sizeof(TUint));
       
   250 			TUint denominator = 1;
       
   251 			Mem::Copy(tempValue+sizeof(TUint), &denominator, sizeof(TUint));
       
   252 			aValueOffset = tempValue;		
       
   253 			}
       
   254 		}
       
   255 	CleanupStack::PushL(TCleanupItem(Cleanup,tempValue));
       
   256 
       
   257 	if(size > KSizeOfValueOffsetField)
       
   258 		{
       
   259 		// We have an Offset, so will set the actual value (i.e. that which the value/offset field points to).
       
   260 		User::LeaveIfError(SetActualData(aValueOffset, aComponentCount, bytes));
       
   261 		// Will not set the value/offset field now, as will be set later once the whole block of data is needed.
       
   262 		}
       
   263 	else
       
   264 		{
       
   265 		// We have an actual value, so will set this in the ValueOffset.		
       
   266 		SetValueOffset(aValueOffset);
       
   267 		// The actual value field will be left blank - no need to store the data twice.
       
   268 		}	
       
   269 	CleanupStack::Pop(tempValue);
       
   270 	User::Free(tempValue);	
       
   271 	}
       
   272 	
       
   273 CIfdGeneralEntry::~CIfdGeneralEntry()
       
   274 	{
       
   275 	// from encoder
       
   276 	delete iDirEntryData;
       
   277 	delete iActualData;
       
   278 	}
       
   279 
       
   280 // Sets the data that the value/offset field points to.
       
   281 TInt CIfdGeneralEntry::SetActualData(const TAny* aActualData, const TUint aSize, const TUint aBytes)
       
   282 	{
       
   283 	/* 
       
   284 	Pass aSize, since we don't know how many components the value has.
       
   285 	Will need to check the format type, in order to overcome the problems with 'undefined' types.
       
   286 	*/
       
   287 	TInt size = aSize * aBytes;
       
   288 	iActualData = static_cast<TUint8*>(User::ReAlloc(iActualData, size));
       
   289 
       
   290 	if(iActualData == NULL)
       
   291 		{
       
   292 		return KErrNoMemory;
       
   293 		}
       
   294 	Mem::Copy(iActualData, aActualData, size);
       
   295 
       
   296 	SetComponentCount(aSize);
       
   297 	return KErrNone;
       
   298 	}
       
   299 
       
   300 // Updates a rational that has a component count of 1.	
       
   301 TInt CIfdGeneralEntry::UpdateRational(TInt aNumerator, TInt aDenominator)
       
   302 	{
       
   303 	// Cannot change a rational entry with a component count > 1 or a non-rational entry.
       
   304 	if(ComponentCount() > 1 || !IsRationalFormat())
       
   305 		{		
       
   306 		return KErrArgument;
       
   307 		}
       
   308 	// We're only dealing with a single rational value.
       
   309 	
       
   310 	// A rational is always > 4 bytes long, so we store it in the actual data field.	
       
   311 	TUint8* rational = static_cast<TUint8*>(User::Alloc(KSizeOfRational));
       
   312 	if(rational == NULL)
       
   313 		{
       
   314 		return KErrNoMemory;
       
   315 		}
       
   316 	TUint8* tempPtr = Mem::Copy(rational, &aNumerator, sizeof(aNumerator));
       
   317     Mem::Copy(tempPtr, &aDenominator, sizeof(aDenominator));    
       
   318 	if(SetActualData(rational, sizeof(TUint8), KSizeOfRational) == KErrNoMemory)
       
   319 		{
       
   320 		User::Free(rational);
       
   321 		return KErrNoMemory;
       
   322 		}
       
   323 	User::Free(rational);
       
   324 	return KErrNone;
       
   325 	}
       
   326 
       
   327 // Updates a value of ASCII type when Ifd knowledge is needed.
       
   328 TInt CIfdGeneralEntry::UpdateString(const HBufC8* aStringValue)
       
   329 	{
       
   330 	if(aStringValue == NULL)
       
   331 		{
       
   332 		return KErrArgument;
       
   333 		}
       
   334 		
       
   335 	//Need to check format type of object.
       
   336 	if(!IsStringFormat())
       
   337 		{
       
   338 		// Cannot change non-ASCII entry.
       
   339 		return KErrArgument;
       
   340 		}
       
   341 			
       
   342 	TUint legalCompCount = KAnySize;
       
   343 	TInt err = KErrNone;
       
   344 
       
   345 	err = iIfd->GetComponentCount(Tag(), legalCompCount);
       
   346 	
       
   347 	TUint stringLength=aStringValue->Length();	
       
   348 	const TUint8* ptr = aStringValue->Ptr();		
       
   349 	TBool nullTerminationNeeded = EFalse;
       
   350 	
       
   351 	//Do some string length checks.
       
   352 	if (legalCompCount != KAnySize)
       
   353 		{
       
   354 		// We have a fixed length string type. Only accept strings that equal the
       
   355 		// fixed length when NULL termianted.
       
   356 		if (stringLength == legalCompCount-1 && ptr[stringLength-1] != KNullCharacter)
       
   357 			{
       
   358 			//If we add a NULL termination string will be legal
       
   359 			nullTerminationNeeded = ETrue;
       
   360 			}
       
   361 		else if (stringLength == legalCompCount && ptr[stringLength-1] == KNullCharacter)
       
   362 			{
       
   363 			//Okay as it is.
       
   364 			}
       
   365 		else
       
   366 			{
       
   367 			return KErrArgument;
       
   368 			}
       
   369 		}
       
   370 	else
       
   371 		{
       
   372 		//No length checks needed, but still might have to add a null terminator.
       
   373 		nullTerminationNeeded = (ptr[stringLength-1] != KNullCharacter);
       
   374 		}
       
   375 		
       
   376 	HBufC8* stringValueCopy = NULL;
       
   377 	if (nullTerminationNeeded)
       
   378 		{
       
   379 		stringValueCopy = HBufC8::New(aStringValue->Length()+1);
       
   380 		if(stringValueCopy == NULL)
       
   381 			{
       
   382 			return KErrNoMemory;
       
   383 			}
       
   384 
       
   385 		*stringValueCopy = *aStringValue;
       
   386 		stringValueCopy->Des().Append(KNullCharacter);
       
   387 		stringLength++;
       
   388 		
       
   389 		ptr = stringValueCopy->Ptr();			
       
   390 		}
       
   391 		
       
   392 	if(stringLength > KSizeOfValueOffsetField)
       
   393 		{
       
   394 		// We have an Offset, so will set the actual value.		
       
   395 		err = SetActualData(ptr, stringLength, sizeof(TUint8));
       
   396 		// Will NOT set the value/offset field now, since it will no-doubt change.
       
   397 		}
       
   398 	else
       
   399 		{
       
   400 		// We have an actual value, so will set this in the ValueOffset.		
       
   401 		SetComponentCount(stringLength);
       
   402 		SetValueOffset(ptr);
       
   403 		// The actualvalue field will be left blank - no need to store the data twice.
       
   404 		err=KErrNone;
       
   405 		}	
       
   406 	delete stringValueCopy;	
       
   407 	return err;
       
   408 	}
       
   409 	
       
   410 /*
       
   411 	Must have a catch-all update function since there are some anomolies to the standard rules.		
       
   412 	Furthermore, this function may also be used to set data of the undefined format.
       
   413 */
       
   414 TInt CIfdGeneralEntry::UpdateData(TUint aComponentCount, const TUint8* aData)
       
   415 	{
       
   416 	TUint maxSize = 0;
       
   417 	// Get the maximum possible size.
       
   418 	TUint tag = Tag();
       
   419 		
       
   420 	iIfd->GetComponentCount(tag, maxSize);
       
   421 		
       
   422 	if(maxSize != KAnySize) // If KAnySize, then size is undefined.
       
   423 		{
       
   424 		if(aComponentCount > maxSize)
       
   425 			{
       
   426 			return KErrNotSupported;
       
   427 			}
       
   428 		}
       
   429 
       
   430 	// Check overflow.  Will indicate that the format-type is not recognised.
       
   431 	TUint format = Format();
       
   432 	if(format == 0)
       
   433 		{
       
   434 		return KErrCorrupt;
       
   435 		}
       
   436 	
       
   437 	if(format >= KDataFormatSizeLength)
       
   438 		{
       
   439 		return KErrNotSupported;
       
   440 		}
       
   441 		
       
   442 	// We are updating existing data, and so will already know the format type.
       
   443 	// Determine if we have a value or an offset to a value.
       
   444 	TInt bytes = KDataFormatSize[format];
       
   445 	TUint size = aComponentCount * bytes;
       
   446 
       
   447 	TUint8* tempValue = NULL;
       
   448 	// Add NULL to the end if it's ASCII
       
   449 	if(IsStringFormat())
       
   450 		{
       
   451 		// verify if the last character is NULL
       
   452 		if(aData[aComponentCount-1]==KNullCharacter)
       
   453 			{
       
   454 			//String already NULL terminated.
       
   455 			if ((maxSize != KAnySize) && (aComponentCount != maxSize))
       
   456 				{
       
   457 				return KErrNotSupported;
       
   458 				}
       
   459 			}
       
   460 		else
       
   461 			{
       
   462 			// Note: This branch is only executed when reading an Exif source
       
   463 			// that contains a non-NULL terminated ASCII string, which is 
       
   464 			// against the Exif 2.2 Spec.
       
   465 
       
   466 			// Since we will add a terminating NULL to the string,
       
   467 			// must check max size of this particular tag.
       
   468 			if((maxSize != KAnySize) && (aComponentCount != maxSize-1))
       
   469 				{
       
   470 				return KErrNotSupported;
       
   471 				}
       
   472 			
       
   473 			//Add the NULL terminator
       
   474 			tempValue = static_cast<TUint8*>(User::Alloc(size + sizeof(TUint8)));
       
   475 			if(tempValue == NULL)
       
   476 				{
       
   477 				return KErrNoMemory;
       
   478 				}
       
   479 			Mem::Copy(tempValue, aData, size);
       
   480 			Mem::Copy(tempValue+size, &KNullCharacter, sizeof(TUint8));
       
   481 			aData = tempValue;
       
   482 			size++;
       
   483 			aComponentCount++;
       
   484 			}
       
   485 		}
       
   486 	TInt err=KErrNone;
       
   487 	if(size > KSizeOfValueOffsetField)
       
   488 		{
       
   489 		// We have an Offset, so will set the actual value (i.e. that which the value/offset field points to).
       
   490 		err = SetActualData(aData, aComponentCount, bytes);
       
   491 		// Will not set the value/offset field now, as will be set later once the whole block of data is needed.
       
   492 		}
       
   493 	else
       
   494 		{
       
   495 		// We have an actual value, so will set this in the ValueOffset.		
       
   496 		SetComponentCount(aComponentCount);
       
   497 		SetValueOffset(aData);
       
   498 		// The actual value field will be left blank - no need to store the data twice.
       
   499 		}
       
   500 	User::Free(tempValue);
       
   501 	return err;
       
   502 	}
       
   503 	
       
   504 
       
   505 // Updates an integer value (including short, integer, long).
       
   506 TInt CIfdGeneralEntry::UpdateInteger(const TInt aIntegerValue)
       
   507 	{
       
   508 	// Need to check format type of object, to avoid calling this on an entry that is not an integer.
       
   509 	if(!IsIntegerFormat())
       
   510 		{
       
   511 		//first check if tag is 0xA002 or A003 - this could be short
       
   512 		//but when setting it we can set it as long
       
   513 		TUint16 tag = Tag();
       
   514 		if ((tag == KTagA002[ETagValue])||(tag == KTagA003[ETagValue]))
       
   515 			{
       
   516 			//tag is A002 or A003 and is short - set entry to long
       
   517 			SetFormat(EUnsignedLong);
       
   518 			}
       
   519 		else
       
   520 			{
       
   521 			// Cannot change non-integer entry.
       
   522 			return KErrArgument;
       
   523 			}
       
   524 		}
       
   525 	
       
   526 	// Check overflow.
       
   527 	TUint format = Format();
       
   528 	if(format == NULL)
       
   529 		{
       
   530 		return KErrCorrupt;
       
   531 		}
       
   532 	
       
   533 	if(format >= KDataFormatSizeLength)
       
   534 		{
       
   535 		return KErrNotSupported;
       
   536 		}
       
   537 	
       
   538 	// Determine if we have a value or an offset to a value.
       
   539 	TInt bytes = KDataFormatSize[format];
       
   540 	TUint size = ComponentCount() * bytes;
       
   541 	if(size > KSizeOfValueOffsetField)
       
   542 		{
       
   543 		// We have an Offset, so will set the actual value...
       
   544 		return SetActualData(&aIntegerValue, ComponentCount(), bytes);
       
   545 		// Will NOT set the value/offset field now, since it will no-doubt change.
       
   546 		}
       
   547 	else
       
   548 		{
       
   549 		// We have an actual value, so will set this in the ValueOffset.		
       
   550 		SetValueOffset(reinterpret_cast<const TUint8*>(&aIntegerValue));
       
   551 		return KErrNone;
       
   552 		// The actualvalue field will be left blank - no need to store the data twice.
       
   553 		}	
       
   554 	}
       
   555 	
       
   556 // Updates a short value.
       
   557 TInt CIfdGeneralEntry::UpdateShort(const TUint16 aShortValue)
       
   558 	{
       
   559 	// Need to check format type of object, to avoid calling this on an entry that is not a short.
       
   560 	if(!IsShortFormat())
       
   561 		{
       
   562 		// Cannot change non-short entry.
       
   563 		return KErrArgument;
       
   564 		}
       
   565 	
       
   566 	// Check overflow.
       
   567 	TUint format = Format();
       
   568 	if(format == NULL)
       
   569 		{
       
   570 		return KErrCorrupt;
       
   571 		}
       
   572 	
       
   573 	if(format >= KDataFormatSizeLength)
       
   574 		{
       
   575 		return KErrNotSupported;
       
   576 		}
       
   577 	
       
   578 	// Determine if we have a value or an offset to a value.
       
   579 	TInt bytes = KDataFormatSize[format]; // value is 2, since it is a short.
       
   580 	TUint size = ComponentCount() * bytes;
       
   581 	if(size > KSizeOfValueOffsetField)
       
   582 		{
       
   583 		// We have an Offset, so will set the actual value...
       
   584 		return SetActualData(&aShortValue, ComponentCount(), bytes);
       
   585 		// Will NOT set the value/offset field now, since it will no-doubt change.
       
   586 		}
       
   587 	else
       
   588 		{
       
   589 		// We have an actual value, so will set this in the ValueOffset.		
       
   590 		SetValueOffset(reinterpret_cast<const TUint8*>(&aShortValue));
       
   591 		return KErrNone;
       
   592 		// The actualvalue field will be left blank - no need to store the data twice.
       
   593 		}	
       
   594 	}
       
   595 
       
   596 // Returns the total size of this Ifd entry. The function should never return zero. 
       
   597 // The minimum value returned should be KMinimumIfdEntrySize, in case of any invalidity with
       
   598 // the entry such as invalid format.
       
   599 TInt CIfdGeneralEntry::TotalSize()
       
   600 	{
       
   601 	TUint16 format = Format();
       
   602 	TBool formatValidity = EFalse;
       
   603 	if(format <= KDataFormatSizeLength-1)
       
   604 		{
       
   605 		//formats - 0, 6, 8, are invalid, which will have size 0.
       
   606 		if(KDataFormatSize[format] != 0)
       
   607 			{
       
   608 			formatValidity = ETrue;
       
   609 			}
       
   610 		}
       
   611 	ASSERT(formatValidity);
       
   612 	//in case of invalid format, return minimum size
       
   613 	if (!formatValidity) 
       
   614 		{
       
   615 		return KMinimumIfdEntrySize;
       
   616 		}
       
   617 		
       
   618 	TUint size = (KDataFormatSize[format] * ComponentCount());
       
   619 	if(size > KSizeOfValueOffsetField)
       
   620 		{
       
   621 		// We have an offset value, so include extra data length (i.e. past the KMinimumIfdEntrySize byte limit).
       
   622 		if ((size%2)==1) 
       
   623 			{
       
   624 			size++;
       
   625 			}
       
   626 		return KMinimumIfdEntrySize + size;
       
   627 		}
       
   628 	return KMinimumIfdEntrySize;
       
   629 	}
       
   630 	
       
   631 // Does this entry contain rational data?
       
   632 TBool CIfdGeneralEntry::IsRationalFormat()
       
   633 	{
       
   634 	TUint format = Format();
       
   635 	return format == EUnsignedRational || 
       
   636 			format == ESignedRational;
       
   637 	}
       
   638 	
       
   639 // Does this entry contain string data?
       
   640 TBool CIfdGeneralEntry::IsStringFormat()
       
   641 	{
       
   642 	return Format() == EAscii;
       
   643 	}
       
   644 	
       
   645 // Does this entry contain 'undefined' data?
       
   646 TBool CIfdGeneralEntry::IsUndefinedFormat()
       
   647 	{
       
   648 	return Format() == EUndefined;
       
   649 	}
       
   650 
       
   651 // Does this entry contain integer data?
       
   652 TBool CIfdGeneralEntry::IsIntegerFormat()
       
   653 	{	
       
   654 	switch(Format())
       
   655 		{
       
   656 		case EByte:		
       
   657 		case EUnsignedLong:
       
   658 		case ESignedLong:
       
   659 			{
       
   660 			return ETrue;
       
   661 			}			
       
   662 		default:
       
   663 			{
       
   664 			return EFalse;	
       
   665 			}
       
   666 		}		
       
   667 	}
       
   668 	
       
   669 // Does this entry contain short data?
       
   670 TBool CIfdGeneralEntry::IsShortFormat()
       
   671 	{	
       
   672 	return Format() == EUnsignedShort;	
       
   673 	}
       
   674 	
       
   675 // Returns ETrue if the data is Unicode.
       
   676 TBool CIfdGeneralEntry::IsUnicodeData()
       
   677 	{
       
   678 	TUint tag = Tag();
       
   679 	//Only the following undefined tags may potentially be Unicode
       
   680 	TBool tagIsPotentiallyUnicode=(	KTag9286[ETagValue] == tag		|| 
       
   681 									KTagGPS001B[ETagValue] == tag 	||
       
   682 									KTagGPS001C[ETagValue] == tag		);
       
   683 								
       
   684 	// Need to ensure that the correct component count is returned for the unicode data.
       
   685 	if (tagIsPotentiallyUnicode && ExtraSize() >= KUnicode().Size())
       
   686 		{
       
   687 		return (0 == Mem::Compare(iActualData, KUnicode().Length() , KUnicode().Ptr(), KUnicode().Length()));
       
   688 		}
       
   689 	else
       
   690 		{
       
   691 		return EFalse;
       
   692 		}
       
   693 	}