diff -r 000000000000 -r 40261b775718 imagingandcamerafws/imagingfws/src/ImageConvResolvrUtils.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imagingandcamerafws/imagingfws/src/ImageConvResolvrUtils.cpp Tue Feb 02 01:56:55 2010 +0200 @@ -0,0 +1,437 @@ +// Copyright (c) 1997-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: +// + +#include "ImageConvResolvrUtils.h" +#include + +// +// COpaqueDataParse +// Class for reading and processing opaque data from the ECOM resource file +// Note that the opaque data can not exceed 255 bytes. +// We store this as follows: +// Version (1 byte) +// Optional flags (2 bytes) if Version >= 1 +// Main Uid (4 bytes) +// Sub Uid (4 bytes) +// Number extensions (1 byte) +// { ".XXX" \r } (x number extensions) +// Number mime types (1 byte) +// [ "mimetype" \r ] (for each mimetype) +// Number of binary properties (1 byte) +// List of the binary properties uids (4 bytes each) +// + +// Note to avoid overhead, we only read the extensions, mime types and binary properties on demand +// Until EnsureExtnsReadL() is called, ExtnsCount() and Extn is invalid. Similarly +// for mime types and plugin binary properties. + +COpaqueDataParse* COpaqueDataParse::NewL(const TDesC8& aOpaqueData) + { + COpaqueDataParse* result = COpaqueDataParse::NewLC(aOpaqueData); + CleanupStack::Pop(result); + return result; + } + +COpaqueDataParse* COpaqueDataParse::NewLC(const TDesC8& aOpaqueData) + { + COpaqueDataParse* result = new (ELeave) COpaqueDataParse(aOpaqueData); + CleanupStack::PushL(result); + result->ConstructL(); + return result; + } + +COpaqueDataParse::COpaqueDataParse(const TDesC8& aOpaqueData): + iOpaqueData(aOpaqueData) + { + } + +void COpaqueDataParse::ConstructL() + { + ReadVersion(); + if (iVersion > KIclPluginFrameworkVersionMax) + { + User::Leave(KErrNotSupported); + } + ReadFlags(); + ReadUids(); + } + +COpaqueDataParse::~COpaqueDataParse() + { + iArray.Close(); + iBinaryPropertiesArray.Close(); + } + +// Extract the Version number +void COpaqueDataParse::ReadVersion() + { + ASSERT(iState<=EVersionProcessed); // should only call this on construction + ASSERT(iOpaqueData.Length() >= KIndexForVersion + 1); + //The version is one byte + iVersion = iOpaqueData[KIndexForVersion]; + iState = EVersionProcessed; + } + + +// Extract the (optional) flags +void COpaqueDataParse::ReadFlags() + { + ASSERT(iState= KIndexForFlags + 2); // opaque data not valid otherwise + iFlags = (iOpaqueData[KIndexForFlags+0] << 8) | (iOpaqueData[KIndexForFlags+1]); + iLenOfFlags = 2; + iLenOfUids = 8; + break; + case KIclPluginFrameworkVersionTwo: + ASSERT(iOpaqueData.Length() >= KIndexForFlags + 2); // opaque data not valid otherwise + iFlags = (iOpaqueData[KIndexForFlags+0] << 8) | (iOpaqueData[KIndexForFlags+1]); + iLenOfFlags = 2; + iLenOfUids = 12; + break; + } + + iStartOfUids = 1 + iLenOfFlags; + iStartOfNumberOfExtns = 1 + iLenOfFlags + iLenOfUids; + + iState = EFlagsProcessed; + } + +// Extract the two Uids +void COpaqueDataParse::ReadUids() + { + ASSERT(iState= iStartOfUids + 4); // opaque data not valid otherwise + // A given OpaqueData should either contain one Uid, in 4 bytes, + // highest to lowest, with an implied second Uid set to KNullUid, + // or two consecutive Uids, in 4 bytes each - 8 in all - main type followed by sub-type. + // The 8 bytes may be followed, for basic types, by info on the file extensions + // and MIME typesassociated with this plugin but this info is ignored here. + iImageTypeUid.iUid = (iOpaqueData[iStartOfUids] << 24) | (iOpaqueData[iStartOfUids+1] << 16) | (iOpaqueData[iStartOfUids+2] << 8) | (iOpaqueData[iStartOfUids+3]); + + // In versions 0 and 1, we allow omission of the sub-type, but this is mandatory in + // versions 2 and greater + if ( (iVersion < 2) && (iOpaqueData.Length() == iStartOfUids + 4) ) + { + iImageSubTypeUid = KNullUid; + } + else + { + ASSERT(iOpaqueData.Length() >= iStartOfUids + 8); + iImageSubTypeUid.iUid = (iOpaqueData[iStartOfUids+4] << 24) | (iOpaqueData[iStartOfUids+5] << 16) + (iOpaqueData[iStartOfUids+6] << 8) + (iOpaqueData[iStartOfUids+7]); + + // In version 2 and greater, the plugin class Uid can be supplied + if (iVersion == 2) + { + if (iOpaqueData.Length() == iStartOfUids + 8) + { + iPluginClassUid = KNullUid; + } + else + { + ASSERT(iOpaqueData.Length() >= iStartOfUids + 12); + iPluginClassUid.iUid = (iOpaqueData[iStartOfUids+8] << 24) | (iOpaqueData[iStartOfUids+9] << 16) + (iOpaqueData[iStartOfUids+10] << 8) + (iOpaqueData[iStartOfUids+11]); + } + } + } + iState = EUidsProcessed; + } + +// read in the Extns from the opaque data +void COpaqueDataParse::EnsureExtnsReadL() + { + // if we've already read in the extensions, is a NOP + if (iState>=EExtnsProcessed) + return; + + ASSERT(iArray.Count()==0); // assume nothing in there at the moment + + iExtnCount = iOpaqueData[iStartOfNumberOfExtns]; + TInt pos = iStartOfNumberOfExtns+1; // start just after the extn count byte + + for (TInt index=0; index0); // if we have -1, would not have found the CR + TPtrC8 extn = restOfData.Left(endPos); + User::LeaveIfError(iArray.Append(extn)); + pos += endPos + 1; // skip over the CR + } + iStartOfMimeTypes = pos; + iState = EExtnsProcessed; + ASSERT(iArray.Count()==iExtnCount); + } + +void COpaqueDataParse::EnsureMIMETypesReadL() + { + // if we've already read in the mime types, is a NOP + if (iState>=EMIMETypesProcessed) + return; + + EnsureExtnsReadL(); + ASSERT(iState==EExtnsProcessed); + + TInt pos = iStartOfMimeTypes; + const TInt numMimeTypes = iOpaqueData[pos]; + pos += 1; + + for (TInt index=0; index0); // if we have -1, would not have found the CR + TPtrC8 mimeType = restOfData.Left(endPos); + User::LeaveIfError(iArray.Append(mimeType)); + pos += endPos + 1; // skip over the CR + } + iStartOfNumberOfBinProperties = pos; + iState = EMIMETypesProcessed; + ASSERT(iArray.Count()==iExtnCount+numMimeTypes); + } + +// Read in the binary properties from the opaque data. +void COpaqueDataParse::EnsureBinaryPropertiesReadL() + { + // If we've already read in the binary properties or if + if (iState >= EBinPropertiesProcessed || iVersion < KIclPluginFrameworkVersionTwo) + { + return; + } + + EnsureMIMETypesReadL(); + ASSERT(iState == EMIMETypesProcessed); + ASSERT(iBinaryPropertiesArray.Count() == 0); + + //If we have a field for the binary properties + if(iStartOfNumberOfBinProperties < iOpaqueData.Length()) + { + TInt binPropertiesCount = iOpaqueData[iStartOfNumberOfBinProperties]; + + TInt pos = iStartOfNumberOfBinProperties + 1; // start just after the binary properties count byte + + if(binPropertiesCount > 0) + { + // The lentgh of the binary properties field sould be a multiple of the size of TUid + if(((iOpaqueData.Length() - pos )/binPropertiesCount) != sizeof(TUid)) + { + User::Leave(KErrNotSupported); + } + } + + TUid tempUid; + for (TInt index = 0; (index < binPropertiesCount) && ( (pos + sizeof(TUid)) <= iOpaqueData.Length()) ; index++) + { + // Real uids cannot have first byte in range 0x01 through 0x0f. + if(0x01 <= iOpaqueData[pos] && iOpaqueData[pos] <= 0x0f) + { + User::Leave(KErrNotSupported); + } + tempUid.iUid = (iOpaqueData[pos] << 24) | (iOpaqueData[pos+1] << 16) | (iOpaqueData[pos+2] << 8) | (iOpaqueData[pos+3]); + User::LeaveIfError(iBinaryPropertiesArray.Append(tempUid)); + pos = pos + sizeof(TUid); + } + + iState = EBinPropertiesProcessed; + ASSERT(iBinaryPropertiesArray.Count() == binPropertiesCount); + } + } + +TBool COpaqueDataParse::CompareMIMETypes(const TDesC8& aMimeType1, const TDesC8& aMimeType2) + { + if (aMimeType1.Length() != aMimeType2.Length()) + return EFalse; + return aMimeType1.CompareF(aMimeType2)==0; // true if exactly the same, if we ignore the case + } + +TBool COpaqueDataParse::CompareFileSuffixL(const TDesC& aFileSuffix1, const TDesC8& aFileSuffix2) + { + //First do a quick compare + if (aFileSuffix1.Length() != aFileSuffix2.Length()) + return EFalse; + + //Change aFileSuffix2 from TDesC8 to TDesC + HBufC* fileSuffix = HBufC::NewL(aFileSuffix2.Length()); //Not on CleanupStack since nothing can leave + TPtr fileSuffixPtr(fileSuffix->Des()); + fileSuffixPtr.Copy(aFileSuffix2); + + const TBool result = aFileSuffix1.CompareF(*fileSuffix)==0; // true if exactly the same, if we ignore the case + delete fileSuffix; + + return result; + } + +void COpaqueDataParse::GetBinaryPropertiesArrayL(RUidDataArray& aBinaryPropertiesArray) const + { + aBinaryPropertiesArray.Reset(); + for(TInt index = 0 ; index < iBinaryPropertiesArray.Count() ; index++) + { + User::LeaveIfError(aBinaryPropertiesArray.Append(iBinaryPropertiesArray[index])); + } + } + +TBool COpaqueDataParse::CheckRequiredUids(const RUidDataArray& aRequiredUids) + { + //First do a quick compare: we can't require more uids than provided, + if(aRequiredUids.Count() > (iBinaryPropertiesArray.Count() + 3)) // 3 for the image-type, image-subtype and class plugin UIDs. + { + return EFalse; + } + + for(TInt index = 0 ; index < aRequiredUids.Count() ; index++) + { + if( + (iBinaryPropertiesArray.Find(aRequiredUids[index]) == KErrNotFound) + && ( aRequiredUids[index]!=iImageTypeUid ) + && ( aRequiredUids[index]!=iImageSubTypeUid ) + && ( aRequiredUids[index]!=iPluginClassUid ) + ) + { + return EFalse; + } + } + + return ETrue; + } + +TBool COpaqueDataParse::CheckOptionsUids(const RUidDataArray& aOptionsUids) + { + //First do a quick compare: we can't require more uids than provided, + if(aOptionsUids.Count() > (iBinaryPropertiesArray.Count() + 3)) // 3 for the image-type, image-subtype and class plugin UIDs. + { + return EFalse; + } + + for(TInt index = 0 ; index < aOptionsUids.Count() ; index++) + { + if(iBinaryPropertiesArray.Find(aOptionsUids[index]) == KErrNotFound) + { + return EFalse; + } + } + + return ETrue; + } + +TBool COpaqueDataParse::IsDefaultCodec() const + { + return (iBinaryPropertiesArray.Find(KUidDefaultCodec) != KErrNotFound); + } + + +/* + * Checks opaque data for the pair KUidICLExtension where all + * bits set in aRequiredExtensions are also set in . + * This signifies that the extension interfaces required are supported by the codec. + * + * Note that there may be more than one KUidICLExtension pair set in the opaque data. + * + * @return TBool + * ETrue indicates that the extensions are supported (interoperably) + */ +TBool COpaqueDataParse::SupportsExtensionsL(TUint aRequiredExtensions) + { + if (!aRequiredExtensions) + { + return ETrue; + } + + EnsureBinaryPropertiesReadL(); + + // Search through the iBinaryPropertiesArray looking for KUidICLExtension. + // The next entry should be the flags. + + TInt count = iBinaryPropertiesArray.Count(); + for (TInt i = 0; i < (count - 1); i++) + { + TUid uid = iBinaryPropertiesArray[i]; + if (uid == KUidICLExtension) + { + // It's stored in the array as a TUid but is really a TUint. + TUint codecCaps = static_cast(iBinaryPropertiesArray[++i].iUid); + if ((codecCaps & aRequiredExtensions) == aRequiredExtensions) + { + return ETrue; + } + } + } + + return EFalse; + } + + +/* + * + * Searches for a match of aPluginString in aClientString. Match returns ETrue + * if aPluginString is found within aImplementationType according to the + * following rules: + * 1) All bytes in aClientString are exact but instances of '?' (0x3F) in + * aPluginString are treated as wildcards - matching any byte value at that + * position in aClientString. + * 2) If aClientString is longer than aPluginString, ignore any excess bytes. + * 3) aClientString is treated as a single descriptor - the '||' delimiters + * are not recognised. + * 4) ETrue is returned if aPluginString matches the start of aClientString + * exactly, subject to wildcards. + * 5) aBytesMatched will be filled in with the number of non-wildcard bytes in + * aPluginString. This is used to rank matches. + * + * @param "const TDesC8& aClientString" + * The string from the client to search for a match + * @param "const TDesC8& aPluginString" + * The data to search for from the plugin + * @param "TInt& aBytesMatched" + * The number of non-wildcard bytes matched + * @return "TBool" + * ETrue if a match was found, EFalse otherwise + */ +TBool CImageConversionResolverUtils::Match(const TDesC8& aClientString, const TDesC8& aPluginString, TInt& aBytesMatched) + { + TInt pluginStringLength = aPluginString.Length(); + while (pluginStringLength>0 && (aPluginString[pluginStringLength - 1] == '?')) + { // Clip extraneous '?' wildcards off the end of the plugin match string + pluginStringLength--; + } + if (pluginStringLength == 0) + { // Plugin has no match string (or just '?') + return EFalse; + } + if (aClientString.Length() == 0) + { // Client string too short - can't match + return EFalse; + } + // Now let's run along the string + aBytesMatched = 0; + TUint matchLength = Min(pluginStringLength, aClientString.Length()); + for (TInt index = 0; index < matchLength; index++) + { + const TUint8 pluginChar = aPluginString[index]; + if (pluginChar=='?') // just ignore a wildchar + continue; + if (aClientString[index] != pluginChar) + return EFalse; + // else we've matched expected byte, so keep going + aBytesMatched += 1; + } + return aBytesMatched != 0; + } +