/*
* Copyright (c) 2007-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: Common utilities for the Metadata System.
*
*/
#ifndef MDSUTILS_H
#define MDSUTILS_H
#include <ecom/implementationinformation.h>
#include <e32math.h>
const TInt KMdEErrHarvestingFailed = 300; // Error occured while harvesting - retry in case of this error
const TInt KMdEErrHarvestingFailedPermanent = 301; // Error occured while harvesting - do not retry harvesting
const TInt KMdEErrHarvestingFailedUnknown = 302; // Unknown error occurred - do not retry harvesting
namespace MdsUtils
{
/**
* CleanupPtrArray function is used for cleanup support of locally declared arrays.
*
* @param aArray An array to cleanup
*/
template<typename T> inline void CleanupPtrArray( TAny* aArray )
{
static_cast<RPointerArray<T>*>(aArray)->ResetAndDestroy();
static_cast<RPointerArray<T>*>(aArray)->Close();
}
/**
* CleanupEComArray function is used for cleanup support of locally declared arrays.
*
* @param aArray An array to cleanup
*/
inline void CleanupEComArray( TAny* aArray )
{
CleanupPtrArray<CImplementationInformation>( aArray );
}
/**
* Get file volume info from the file system.
* @param aUri File URI.
* @param aVolumeInfo Reference to the object where volume info is stored to.
*/
inline TInt GetVolumeInfo(const RFs& aFs, const TDesC& aUri, TVolumeInfo& aVolumeInfo )
{
if ( aUri.Size() <= 0 )
{
return KErrArgument;
}
TInt driveNumber( 0 );
TInt error( 0 );
error = aFs.CharToDrive( aUri[0], driveNumber );
if ( error != KErrNone )
{
return error;
}
error = aFs.Volume( aVolumeInfo, driveNumber );
return error;
}
/**
* Returns a 32-bit unsigned integer from the location pointed by
* the parameter.
* @param aPointer Memory pointer (input).
* @return Converted integer.
*/
inline TUint32 ToUInt32L( TUint8* aPointer )
{
if ( !aPointer )
{
User::Leave( KErrGeneral );
}
TUint32 ret = *( aPointer + 3 );
ret = ( ret << 8 ) + *( aPointer + 2 );
ret = ( ret << 8 ) + *( aPointer + 1 );
ret = ( ret << 8 ) + *aPointer;
return ret;
}
/**
* Returns a 16-bit unsigned integer from the location pointed by
* the parameter.
* @param aPointer Memory pointer (input).
* @return Converted integer.
*/
inline TUint16 ToUInt16L( TUint8* aPointer )
{
if ( !aPointer )
{
User::Leave( KErrGeneral );
}
TUint16 ret = *( aPointer + 1 );
ret = STATIC_CAST( TUint16, ( ret << 8 ) + *aPointer );
return ret;
}
/**
* Converts GPS coordinates from Exif degrees to decimal representation.
* @param aSourceDes Source descriptor.
* @param aCoordinate Output coordinate (latitude or longitude).
*/
inline void ConvertFromDegreesToDecimalL( const TDes8& aSourceDes, TReal64& aCoordinate )
{
if ( aSourceDes.MaxSize() < 24 )
{
User::Leave( KErrArgument );
}
TUint8* ptr = CONST_CAST( TUint8*, aSourceDes.Ptr() );
TUint32 degrees = ToUInt32L( ptr );
TUint32 deg_denominator = ToUInt32L( ptr + 4 );
TUint32 minutes = ToUInt32L( ptr + 8 );
TUint32 min_denominator = ToUInt32L( ptr + 12 );
TUint32 seconds = ToUInt32L( ptr + 16 );
TUint32 sec_denominator = ToUInt32L( ptr + 20 );
// check that coordinate doesn't contain division by zero
// in those numerators which are not 0
if ( ( deg_denominator == 0 && degrees ) ||
( min_denominator == 0 && minutes ) ||
( sec_denominator == 0 && seconds ) )
{
User::Leave( KErrCorrupt );
}
aCoordinate = 0.0;
if( degrees )
{
TReal64 degreesReal = degrees;
TReal64 deg_denominatorReal = deg_denominator;
aCoordinate += degreesReal / deg_denominatorReal;
}
if( minutes )
{
TReal64 minutesReal = minutes;
TReal64 min_denominatorReal = min_denominator;
aCoordinate += minutesReal / (min_denominatorReal * 60.0);
}
if( seconds )
{
TReal64 secondsReal = seconds;
TReal64 sec_denominatorReal = sec_denominator;
aCoordinate += secondsReal / (sec_denominatorReal * 3600.0);
}
}
/**
* Converts GPS coordinates from decimal to degree representation used by Exif.
* Method leaves with KErrArgument if max size of aTgtDes < 24.
* @param aCoordinate Input coordinate (latitude or longitude).
* @param aTgtDes Output descriptor.
*/
inline void ConvertFromDecimalToDegreesL( TReal64 aCoordinate, TDes8& aTgtDes )
{
if ( aTgtDes.MaxSize() < 24 )
{
User::Leave( KErrArgument );
}
const TUint32 KDenominator1 = 1;
const TUint32 KDenominator10M = 10000000;
const TReal64 KDenominator10MReal = KDenominator10M;
TReal64 degs64 = aCoordinate;
TReal64 mins64 = 0.0;
Math::Frac( mins64, degs64 );
mins64 *= 60.0;
TReal64 secs64 = 0.0;
Math::Frac( secs64, mins64 );
secs64 *= 60.0 * KDenominator10MReal;
TUint32 degrees = (TUint32)( degs64 );
TUint32 minutes = (TUint32)( mins64 );
TUint32 seconds = (TUint32)( secs64 );
aTgtDes.Append( (TUint8*) °rees, 4 );
aTgtDes.Append( (TUint8*) &KDenominator1, 4 );
aTgtDes.Append( (TUint8*) &minutes, 4 );
aTgtDes.Append( (TUint8*) &KDenominator1, 4 );
aTgtDes.Append( (TUint8*) &seconds, 4 );
aTgtDes.Append( (TUint8*) &KDenominator10M, 4 );
}
inline TBool IsValidProcessId( const TUid aUid )
{
const TUint32 KMinProcessId = 0x10000000;
const TUint32 KMaxProcessId = 0xFFFFFFFF;
if ( aUid.iUid < KMinProcessId || aUid.iUid > KMaxProcessId )
{
return EFalse;
}
return ETrue;
}
/**
* Converts trap errors to harvesting errors.
* @param aTrapError Trapped error to convert
* @param aPluginError Output error
*/
inline void ConvertTrapError( TInt aTrapError, TInt &aPluginError )
{
aPluginError = KErrNone;
if ( aTrapError == KErrArgument || // -6
aTrapError == KErrCorrupt || // -20
aTrapError == KErrAccessDenied || // -21
aTrapError == KErrPermissionDenied || // -46
aTrapError == KErrNotFound || // -1
aTrapError == KErrNotSupported ) // -5
{
aPluginError = KMdEErrHarvestingFailedPermanent;
}
else if ( aTrapError == KErrGeneral || // -2
aTrapError == KErrNoMemory || //-4
aTrapError == KErrInUse || // -14
aTrapError == KErrServerBusy || // -16
aTrapError == KErrLocked || // -22
aTrapError == KErrCouldNotConnect ) // -34
{
aPluginError = KMdEErrHarvestingFailed;
}
else
{
aPluginError = KMdEErrHarvestingFailedUnknown;
}
}
/**
* Compare descriptors locale-independent
*
* @param aDes1 first descriptor to compare
* @param aDes2 second descriptor to compare
*
* @return Positive, if this descriptor is greater than the specified
* descriptor. Negative, if this descriptor is less than the
* specified descriptor. Zero, if both descriptors have the same
* length and the their contents are the same.
*/
inline TInt Compare(const TDesC& aDes1, const TDesC& aDes2)
{
return aDes1.CompareF( aDes2 );
}
/**
* Find descriptor locale-independent
*
* @param aWhereDes descriptor where to search
* @param aWhatDes descriptor what to search
*
* @return The offset of the data sequence from the beginning of this
* descriptor's data. KErrNotFound, if the data sequence cannot be
* found. Zero, if the length of the search data sequence is zero.
*/
inline TInt Find(const TDesC& aWhereDes, const TDesC& aWhatDes)
{
return aWhereDes.FindF( aWhatDes );
}
/**
* Check if file exist in file system. Requires AllFiles capability.
*
* @param aFs handle to file server session
* @param aFilename filename
*
* @return Does file exist
*/
inline TBool FileExists(RFs& aFs, const TDesC& aFilename)
{
TUint fileAttributes;
// Att method is used instead of Entry method
// because smaller stack memory usage (4 bytes vs. 548 bytes).
// There is no performance difference between methods Att and Entry.
return KErrNone == aFs.Att( aFilename, fileAttributes );
}
/**
* Get name from filename. For example 'Test' is returned from
* 'C:\Data\Test.jpg'. aFilename must contain drive letter, path and
* filename (file extension is not required).
*
* @param aFilename filename
* @param aName returned name
*
* @return Does name exist (if true, lenght of aName is > 0)
*/
inline TBool GetName(const TDesC& aFilename, TPtrC& aName)
{
// find name (everything after last back slash)
TInt pos = aFilename.LocateReverseF( '\\' );
if( pos >= 0 )
{
aName.Set( aFilename.Mid( pos + 1 ) );
// remove extension
TInt pos = aName.LocateReverseF( '.' );
if( pos >= 0 )
{
aName.Set( aName.Left( pos ) );
}
if( aName.Length() > 0 )
{
return ETrue;
}
}
return EFalse;
}
/**
* Get name and extension from filename. For example 'Test.jpg' is
* returned from 'C:\Data\Test.jpg'. aFilename must contain drive letter,
* path and filename (file extension is not required).
*
* @param aFilename filename
* @param aNameExt returned name and extension
*
* @return Does name and extension exist (if true, lenght of aNameExt is > 0)
*/
inline TBool GetNameExt(const TDesC& aFilename, TPtrC& aNameExt)
{
// find name (everything after last back slash)
TInt pos = aFilename.LocateReverseF( '\\' );
if( pos >= 0 )
{
aNameExt.Set( aFilename.Mid( pos + 1 ) );
if( aNameExt.Length() > 0 )
{
return ETrue;
}
}
return EFalse;
}
/**
* Get extension from filename. For example 'jpg' is returned from
* 'C:\Data\Test.jpg'. aFilename must contain drive letter, path and
* filename (file extension is not required).
*
* @param aFilename filename
* @param aExt returned extension
*
* @return Does extension exist (if true, lenght of aExt is > 0)
*/
inline TBool GetExt(const TDesC& aFilename, TPtrC& aExt)
{
// find extension (everything after last dot)
TInt pos = aFilename.LocateReverseF( '.' );
if( pos >= 0 )
{
aExt.Set( aFilename.Mid( pos + 1 ) );
if( aExt.Length() > 0 )
{
return ETrue;
}
}
return EFalse;
}
/**
* Get path from filename. For example 'C:\Data\' is returned from
* 'C:\Data\Test.jpg'. aFilename must contain drive letter, path and
* filename (file extension is not required).
*
* @param aFilename filename
* @param aPath returned path
*
* @return Does path exist (if true, lenght of aPath is > 0)
*/
inline TBool GetPath(const TDesC& aFilename, TPtrC& aPath)
{
// find path (everything before last back slash)
TInt pos = aFilename.LocateReverseF( '\\' );
if( pos >= 0 )
{
aPath.Set( aFilename.Left( pos + 1 ) );
if( aPath.Length() > 0 )
{
return ETrue;
}
}
return EFalse;
}
}
/**
* Serialize an array to a newly created descriptor buffer.
* Leaves on error.
* @param aArray Array to serialize.
* @return A new output descriptor pointer. Ownership is transferred.
*/
template<typename T>
HBufC8* SerializeArrayL( const RArray<T>& aArray )
{
const TInt KItemCount = aArray.Count();
if ( KItemCount <= 0 )
{
return NULL;
}
const TInt KItemSizeInBytes = sizeof( T );
const TInt KBufferLength = KItemSizeInBytes * KItemCount;
HBufC8* buf = HBufC8::NewL( KBufferLength );
void* ptr = NULL;
for ( TInt i = 0; i < KBufferLength; i += KItemSizeInBytes )
{
const T& item = aArray[ i / KItemSizeInBytes ];
ptr = (void*)( buf->Ptr() + i );
Mem::Copy( ptr, &item, KItemSizeInBytes );
}
buf->Des().SetLength( KBufferLength );
return buf; // ownership is transferred
}
/**
* Deserialize an array from a descriptor buffer.
* Leaves on error.
* @param aDesc Descriptor containing the serialized array.
* @param aArray Target array.
*/
template<typename T>
void DeserializeArrayL( const TDesC8& aDesc, RArray<T>& aArray )
{
aArray.Reset();
const TInt KItemSizeInBytes = sizeof( T );
const TInt KBufferLength = aDesc.Size();
const TInt KItemCount = KBufferLength / KItemSizeInBytes;
aArray.Reserve( KItemCount );
for ( TInt i = 0; i < KItemCount; ++i )
{
T item;
void* ptr = (void*)( aDesc.Ptr() + i * KItemSizeInBytes );
Mem::Copy( &item, ptr, KItemSizeInBytes );
aArray.Append( item );
}
}
/**
* Serialize a pointer array to a newly created descriptor buffer.
* Leaves on error.
* @param aArray Pointer Array to serialize.
* @return A new output descriptor pointer. Ownership is transferred.
*/
template<typename T>
HBufC8* SerializePointerArrayL( const RPointerArray<T>& aArray )
{
const TInt KItemCount = aArray.Count();
if ( KItemCount <= 0 )
{
return NULL;
}
const TInt KItemSizeInBytes = sizeof( T );
const TInt KBufferLength = KItemSizeInBytes * KItemCount;
HBufC8* buf = HBufC8::NewL( KBufferLength );
void* ptr = NULL;
for ( TInt i = 0; i < KBufferLength; i += KItemSizeInBytes )
{
const T* item = aArray[ i / KItemSizeInBytes ]; // alkup. oli const T&
ptr = (void*)( buf->Ptr() + i );
Mem::Copy( ptr, &item, KItemSizeInBytes );
}
buf->Des().SetLength( KBufferLength );
return buf; // ownership is transferred
}
/**
* Deserialize a pointer array from a descriptor buffer.
* Leaves on error.
* @param aDesc Descriptor containing the serialized array.
* @param aArray Target Pointer Array.
*/
template<typename T>
void DeserializePointerArrayL( const TDesC8& aDesc, RPointerArray<T>& aArray )
{
aArray.Reset();
const TInt KItemSizeInBytes = sizeof( T );
const TInt KBufferLength = aDesc.Size();
const TInt KItemCount = KBufferLength / KItemSizeInBytes;
aArray.Reserve( KItemCount );
for ( TInt i = 0; i < KItemCount; ++i )
{
T* item; // alkup. oli pelkkä T ilman pointteria
void* ptr = (void*)( aDesc.Ptr() + i * KItemSizeInBytes );
Mem::Copy( &item, ptr, KItemSizeInBytes );
aArray.Append( item );
}
}
#endif // MDSUTILS_H