genericservices/mimerecognitionfw/apmime/APMREC.CPP
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // Copyright (c) 1997-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 // Defines CApaDataRecognizerType the base class for concrete mime recognizers that
       
    15 // perform the actual mime type recognitionand the CApaDataRecognizer that provides
       
    16 // the interface to the collection of recognizers.
       
    17 // 
       
    18 //
       
    19 
       
    20 
       
    21 #include "APMSTD.H"
       
    22 #include "APMREC.H"
       
    23 #include "APMPAN.H"
       
    24 #include "APMFNDR.H"
       
    25 
       
    26 #ifdef USING_ECOM_RECOGS
       
    27 #include <ecom/ecom.h>
       
    28 #endif
       
    29 
       
    30 NONSHARABLE_CLASS(CDataRecognizerExtension) : public CBase
       
    31 	{
       
    32 public:
       
    33 	inline static CDataRecognizerExtension* NewL() {return new(ELeave) CDataRecognizerExtension;}
       
    34 	inline TUid DestructorUid() const {return iDtorKey;}
       
    35 	inline TUid& DestructorUidReference() {return iDtorKey;}
       
    36 	inline CApaDataRecognizer& DataRecognizer() {return *iDataRecognizer;}
       
    37 	inline void SetDataRecognizer(CApaDataRecognizer& aDataRecognizer) {iDataRecognizer=&aDataRecognizer;}
       
    38 private:
       
    39 	inline CDataRecognizerExtension() {}
       
    40 private:
       
    41 	CApaDataRecognizer* iDataRecognizer; // no ownership
       
    42 	TUid iDtorKey; // destructor key to track the instance of ECOM implementation class
       
    43 	};
       
    44 
       
    45 class TDataToRecognize
       
    46 	{
       
    47 public:
       
    48 	TDataToRecognize(const TDesC& aName, const TDesC8& aBuffer);
       
    49 	TDataToRecognize(CApaDataRecognizer& aDataRecognizer, RFile& aFile, TInt aPreferredBufSize);
       
    50 	void RecognizeL(CApaDataRecognizerType& aDataRecognizerType);
       
    51 	void PrepareForRecognizeLoopLC();
       
    52 	void PopOffCleanupStackAndResetAfterRecognizeLoopL();
       
    53 private:
       
    54 	enum
       
    55 		{
       
    56 		EFlagFilePositionStored	=0x00000001,
       
    57 		EFlagLeaveIfError		=0x00000002
       
    58 		};
       
    59 private:
       
    60 	static void ResetAfterRecognizeLoopL(TAny* aThis);
       
    61 	void ResetAfterRecognizeLoopL();
       
    62 private:
       
    63 	TUint iFlags;
       
    64 	const TDesC* iName; // owned if iFile!=NULL
       
    65 	const TDesC8* iBuffer; // owned if iFile!=NULL
       
    66 	CApaDataRecognizer* iDataRecognizer;
       
    67 	RFile* iFile;
       
    68 	TInt iFilePosition;
       
    69 	TInt iPreferredBufSize;
       
    70 	};
       
    71 
       
    72 //
       
    73 // class CApaDataRecognizer
       
    74 //
       
    75 
       
    76 EXPORT_C TDataRecognitionResult CApaDataRecognizer::RecognizeL(const TDesC& aName, const TDesC8& aBuffer)
       
    77 	{
       
    78 	TDataToRecognize dataToRecognize(aName, aBuffer);
       
    79 	return RecognizeL(dataToRecognize);
       
    80 	}
       
    81 
       
    82 EXPORT_C TDataRecognitionResult CApaDataRecognizer::RecognizeL(RFile& aFile, TInt aPreferredBufSize)
       
    83 	{
       
    84 	TDataToRecognize dataToRecognize(*this, aFile, aPreferredBufSize);
       
    85 	return RecognizeL(dataToRecognize);
       
    86 	}
       
    87 
       
    88 TDataRecognitionResult CApaDataRecognizer::RecognizeL(TDataToRecognize& aDataToRecognize)
       
    89 // attempt to recognize using all recognizers
       
    90 // keeps recognizing until either a recognizer's confidence meets or 
       
    91 // exceeds the currently acceptable confidence, or all recognizers 
       
    92 // have been used
       
    93 	{
       
    94 	iResult.Reset();
       
    95 	aDataToRecognize.PrepareForRecognizeLoopLC();
       
    96 	TInt storedErr=KErrNone;
       
    97 	TInt count=iDataRecognizerList.Count();
       
    98 	for (TInt i=0; i<count; i++)
       
    99 		{
       
   100 		if (DoRecognize(iDataRecognizerList[i], aDataToRecognize, TDataType(), storedErr))
       
   101 			{
       
   102 			break;
       
   103 			}
       
   104 		}
       
   105 	aDataToRecognize.PopOffCleanupStackAndResetAfterRecognizeLoopL();
       
   106 	// if we haven't recognized anything and there was a problem with a recognizer, propagate
       
   107 	// the error.  n.b. if several recognizers had errors, only propagate the first error we 
       
   108 	// encountered
       
   109 	if (iResult.iConfidence==CApaDataRecognizerType::ENotRecognized)
       
   110 		{
       
   111 		User::LeaveIfError(storedErr);
       
   112 		}
       
   113 	return iResult;
       
   114 	}
       
   115 
       
   116 EXPORT_C TBool CApaDataRecognizer::RecognizeL(const TDesC& aName, const TDesC8& aBuffer, const TDataType& aDataType)
       
   117 	{
       
   118 	TDataToRecognize dataToRecognize(aName, aBuffer);
       
   119 	return RecognizeL(dataToRecognize, aDataType);
       
   120 	}
       
   121 
       
   122 EXPORT_C TBool CApaDataRecognizer::RecognizeL(RFile& aFile, TInt aPreferredBufSize, const TDataType& aDataType)
       
   123 	{
       
   124 	TDataToRecognize dataToRecognize(*this, aFile, aPreferredBufSize);
       
   125 	return RecognizeL(dataToRecognize, aDataType);
       
   126 	}
       
   127 
       
   128 TBool CApaDataRecognizer::RecognizeL(TDataToRecognize& aDataToRecognize, const TDataType& aDataType)
       
   129 // recognize using only recognizers which supply the aDataType
       
   130 	{
       
   131 	iResult.Reset();
       
   132 	TInt count=iDataRecognizerList.Count();
       
   133 	TInt storedErr=KErrNone;
       
   134 	aDataToRecognize.PrepareForRecognizeLoopLC();
       
   135 	for (TInt i=0; i<count; i++)
       
   136 		{
       
   137 		CApaDataRecognizerType* rec=iDataRecognizerList[i];
       
   138 		TInt countMime=rec->MimeTypesCount();
       
   139 		for (TInt ii=0; ii<countMime; ii++)
       
   140 			{
       
   141 			TDataType supportedDataType;
       
   142 			TRAPD(err, supportedDataType=rec->SupportedDataTypeL(ii));
       
   143 			if (err == KErrNone)
       
   144 				{
       
   145 				if (supportedDataType == aDataType)
       
   146 					{
       
   147 					if (DoRecognize(rec, aDataToRecognize, aDataType, storedErr))
       
   148 						{
       
   149 						aDataToRecognize.PopOffCleanupStackAndResetAfterRecognizeLoopL();
       
   150 						return ETrue;
       
   151 						}
       
   152 					break;
       
   153 					}
       
   154 				}
       
   155 			else if (storedErr==KErrNone)
       
   156 				{
       
   157 				// this is the first time we've hit an error with SupportedDataType,
       
   158 				// so store it now and propagate later if we don't find a suitable 
       
   159 				// recognizer
       
   160 				storedErr=err;
       
   161 				}
       
   162 			}
       
   163 		}
       
   164 	aDataToRecognize.PopOffCleanupStackAndResetAfterRecognizeLoopL();
       
   165 	if (iResult.iConfidence==CApaDataRecognizerType::ENotRecognized)
       
   166 		{
       
   167 		// a suitable recognizer wasn't found, but we may have encountered an
       
   168 		// error with one of the recognizers we scanned n.b. only the first error
       
   169 		// encountered is propagated
       
   170 		User::LeaveIfError(storedErr);
       
   171 		}
       
   172 	return iResult.iConfidence!=CApaDataRecognizerType::ENotRecognized;
       
   173 	}
       
   174 
       
   175 TBool CApaDataRecognizer::DoRecognize(CApaDataRecognizerType* aDataRecognizerType, TDataToRecognize& aDataToRecognize, const TDataType& aDataType, TInt& aError)
       
   176 // do the recognition, if the recognizer is sufficiently confident, return ETrue
       
   177 	{
       
   178 	TDataRecognitionResult result;
       
   179 	TRAPD(err, result=aDataRecognizerType->RecognizeL(aDataToRecognize));
       
   180 	if (err != KErrNone)
       
   181 		{
       
   182 		// We only want to store the first error, it if is not KErrNone, it means
       
   183 		// we have set this error previously
       
   184 		if (aError==KErrNone)
       
   185 			{
       
   186 			aError=err;
       
   187 			}
       
   188 		return EFalse;
       
   189 		}
       
   190  
       
   191 	if (aDataType!=result.iDataType && aDataType!=TDataType())
       
   192 		{
       
   193 		return EFalse;
       
   194 		}
       
   195 	if (result.iConfidence>iResult.iConfidence)
       
   196 		{
       
   197 		iResult=result;
       
   198 		return (result.iConfidence>=iAcceptedConfidence);
       
   199 		}
       
   200 	return EFalse;
       
   201 	}
       
   202 
       
   203 EXPORT_C TInt CApaDataRecognizer::AcceptedConfidence() const
       
   204 	{
       
   205 	return iAcceptedConfidence;
       
   206 	}
       
   207 
       
   208 EXPORT_C void CApaDataRecognizer::SetAcceptedConfidence(TInt aConfidence)
       
   209 	{
       
   210 	iAcceptedConfidence=aConfidence;
       
   211 	}
       
   212 
       
   213 EXPORT_C CApaDataRecognizer::~CApaDataRecognizer()
       
   214 	{
       
   215 	iDataRecognizerList.ResetAndDestroy();
       
   216 	iDataArray.Reset();
       
   217 	}
       
   218 
       
   219 EXPORT_C CApaDataRecognizer::CApaDataRecognizer(RFs& aFs)
       
   220 	:iFs(aFs),
       
   221 	iMaxBufferSize(-1),
       
   222 	iDataRecognizerList(KDataArrayGranularity),
       
   223 	iDataArray(KDataArrayGranularity),
       
   224 	iAcceptedConfidence(CApaDataRecognizerType::ECertain)
       
   225 	{}
       
   226 
       
   227 EXPORT_C void CApaDataRecognizer::AddDataRecognizerTypeL(CApaDataRecognizerType* aDataRecognizerType)
       
   228 // add the concrete recognizer into the list at the appropriate priority
       
   229 	{
       
   230 #if defined(_DEBUG)
       
   231  	CApaDataRecognizerType* rec=NULL;
       
   232 	const TInt countDeb=iDataRecognizerList.Count();
       
   233 	for (TInt ii=0; ii<countDeb; ii++)
       
   234 		{
       
   235 		rec=iDataRecognizerList[ii];
       
   236  		__ASSERT_ALWAYS(rec->TypeUid()!=aDataRecognizerType->TypeUid(), Panic(EDPanicDuplicateRecognizer));
       
   237 		}
       
   238 #endif // _DEBUG
       
   239 
       
   240 	TInt priority=aDataRecognizerType->Priority();
       
   241 	TInt count=iDataRecognizerList.Count();
       
   242 	for (TInt i=0; i<count; i++)
       
   243 		{
       
   244 		if (iDataRecognizerList[i]->Priority()<priority)
       
   245 			{
       
   246 			iDataRecognizerList.InsertL(aDataRecognizerType, i);
       
   247 			aDataRecognizerType->DataRecognizerExtension()->SetDataRecognizer(*this);
       
   248 			return;
       
   249 			}
       
   250 		}
       
   251 	iDataRecognizerList.AppendL(aDataRecognizerType);
       
   252 	aDataRecognizerType->DataRecognizerExtension()->SetDataRecognizer(*this);
       
   253 	}
       
   254 
       
   255 EXPORT_C void CApaDataRecognizer::CApaDataRecognizer_Reserved_1()
       
   256 	{}
       
   257 
       
   258 EXPORT_C TInt CApaDataRecognizer::RemoveDataRecognizerType(const CApaDataRecognizerType* aDataRecognizerType)
       
   259 // remove the concrete recognizer from the list
       
   260 // if it is not locked, if it fails return an error code
       
   261 	{
       
   262 	// find the recognizer in the list
       
   263 	TInt count=iDataRecognizerList.Count();
       
   264 	TUid uid=aDataRecognizerType->TypeUid();
       
   265 	TInt i;
       
   266 	for (i=0; i<count; i++)
       
   267 		{
       
   268 		if (iDataRecognizerList[i]->TypeUid()==uid)
       
   269 			break;
       
   270 		}
       
   271 	// did we find a match
       
   272 	if (i==count)
       
   273 		return KErrNotFound;
       
   274 	// is the matching recognizer locked
       
   275 	CApaDataRecognizerType* rec=iDataRecognizerList[i];
       
   276 	if (rec->Locked())
       
   277 		return KErrLocked;
       
   278 	// remove the recognizer from the list, then delete it
       
   279 	delete rec;
       
   280 	iDataRecognizerList.Remove(i);
       
   281 	iDataRecognizerList.Compress();
       
   282 	return KErrNone;
       
   283 	}
       
   284 
       
   285 EXPORT_C void CApaDataRecognizer::DataTypeL(CDataTypeArray& aArray)
       
   286 	{
       
   287 	TInt count=iDataArray.Count();
       
   288 	for (TInt i=0; i<count; i++)
       
   289 		aArray.AppendL(iDataArray[i]);
       
   290 	}
       
   291 
       
   292 EXPORT_C void CApaDataRecognizer::UpdateDataTypesL()
       
   293 // rebuild the list of unique mime types
       
   294 	{
       
   295 	iDataArray.Reset();
       
   296 	TInt count=iDataRecognizerList.Count();
       
   297 	for (TInt i=0; i<count; i++)
       
   298 		{
       
   299 		CApaDataRecognizerType* rec=iDataRecognizerList[i];
       
   300 		TRAP_IGNORE(rec->UpdateDataTypesL());
       
   301 		TInt mimeCount=rec->MimeTypesCount();
       
   302 		for (TInt ii=0; ii<mimeCount; ii++)
       
   303 			{
       
   304 			TRAP_IGNORE(AddDataTypeL(rec->SupportedDataTypeL(ii)));
       
   305 			}
       
   306 		}
       
   307 	}
       
   308 
       
   309 EXPORT_C TInt CApaDataRecognizer::PreferredBufSize() const
       
   310 // return the maximum preferred buf size
       
   311 	{
       
   312 	if (iMaxBufferSize < 0)
       
   313 		{
       
   314 		// The recognizers have been (re)loaded, so calulate the maximum buffer size.
       
   315 		TInt count=iDataRecognizerList.Count();
       
   316 		for (TInt i=0; i<count; i++)
       
   317 			iMaxBufferSize=Max((TInt)iDataRecognizerList[i]->PreferredBufSize(), iMaxBufferSize);
       
   318 		}
       
   319 	return iMaxBufferSize;
       
   320 	}
       
   321 
       
   322 EXPORT_C void CApaDataRecognizer::DestroyRecognizerList()
       
   323 	{
       
   324 	iDataRecognizerList.ResetAndDestroy();
       
   325 	iDataArray.Reset();
       
   326 	}
       
   327 
       
   328 void CApaDataRecognizer::AddDataTypeL(const TDataType& aDataType)
       
   329 // add a mime type to the array if it's unique
       
   330 	{
       
   331 	TInt i=iDataArray.Count()-1;
       
   332 	for (; i>=0; i--)
       
   333 		{
       
   334 		if (aDataType==iDataArray[i])
       
   335 			return;
       
   336 		}
       
   337 	iDataArray.AppendL(aDataType);
       
   338 	}
       
   339 
       
   340 //
       
   341 // class CApaDataRecognizerType
       
   342 //
       
   343 
       
   344 EXPORT_C CApaDataRecognizerType::CApaDataRecognizerType(TUid aUid, TInt aPriority)
       
   345 	:iTypeUid(aUid),
       
   346 	iPriority(aPriority),iDataRecognizerExtn(NULL)
       
   347 /** Constructs the recognizer with a UID and a priority.
       
   348 
       
   349 Typically, a derived class constructor calls this constructor through a constructor 
       
   350 initialization list.
       
   351 
       
   352 The UID is the way that a recognizer is detected by the framework.
       
   353 
       
   354 @param aUid A UID that identifies the recognizer.
       
   355 @param aPriority A value that estimates the probability that the recognizer 
       
   356 will successfully identify data. This is one of the CApaDataRecognizerType::TRecognizerPriority 
       
   357 enumerators.
       
   358 @see CApaDataRecognizerType::TRecognizerPriority */
       
   359 	{}
       
   360 
       
   361 EXPORT_C CApaDataRecognizerType::~CApaDataRecognizerType()
       
   362 // Destructor.
       
   363 	{
       
   364 #ifdef USING_ECOM_RECOGS
       
   365 	//if ecom plugin is used destroy its implementation
       
   366 	if(iDataRecognizerExtn!=NULL)
       
   367 		{
       
   368 		REComSession::DestroyedImplementation(iDataRecognizerExtn->DestructorUid());
       
   369 		delete iDataRecognizerExtn;
       
   370 		}
       
   371 #endif
       
   372 	}
       
   373 
       
   374 EXPORT_C void CApaDataRecognizerType::Lock()
       
   375 /** Adds a lock to the recognizer.
       
   376 
       
   377 This may be called any number of times, but each call to this function must 
       
   378 be matched by a corresponding call to Unlock() to completely unlock the recognizer.
       
   379 
       
   380 This function is used to prevent the recognizer DLL from being unloaded.
       
   381 
       
   382 @see Unlock()
       
   383 @see Locked() */
       
   384 	{
       
   385 	iLock++;
       
   386 	}
       
   387 
       
   388 EXPORT_C void CApaDataRecognizerType::Unlock()
       
   389 /** Removes a lock from the recognizer.
       
   390 
       
   391 All calls to Lock() should be matched by a corresponding call to this function. 
       
   392 The recognizer is not unlocked until all calls to Lock() have been matched 
       
   393 by corresponding calls to this function.
       
   394 
       
   395 @see Lock()
       
   396 @see Locked() */
       
   397 	{
       
   398 	if (iLock>0)
       
   399 		iLock--;
       
   400 	}
       
   401 
       
   402 EXPORT_C TUint CApaDataRecognizerType::PreferredBufSize()
       
   403 /** Gets the size of buffer preferred for the purpose of recognizing the data type.
       
   404 
       
   405 Regardless of the preferred buffer size returned by an implementation of this 
       
   406 function, the actual size used is never greater than a maximum value as set 
       
   407 by the client of the Application Architecture server through a call to RApaLsSession::SetMaxDataBufSize().
       
   408 
       
   409 @return The preferred data size. The default implementation returns zero.
       
   410 @see RApaLsSession::SetMaxDataBufSize() */
       
   411 	{
       
   412 	return 0;	// default to no buffer
       
   413 				// name recognition only
       
   414 	}
       
   415 
       
   416 EXPORT_C void CApaDataRecognizerType::UpdateDataTypesL()
       
   417 /** Refreshes the list of data (MIME) types supported by this recognizer. */
       
   418 	{
       
   419 	}
       
   420 
       
   421 EXPORT_C void CApaDataRecognizerType::DoRecognizeL(const TDesC& aName, const TDesC8& aBuffer)
       
   422 /** Implements the attempt to recognize data.
       
   423 
       
   424 Recognizers should provide an implementation of this function in a derived 
       
   425 class. Note that, when the implementation recognizes data, it must put the 
       
   426 result of the operation in the iDataType and iConfidence data members.
       
   427 
       
   428 Note that if more data is required than is provided in aBuffer, then 
       
   429 CApaDataRecognizerType::FilePassedByHandleL should be called and the data 
       
   430 read from the returned RFile (if not NULL). If this returns NULL, it may be 
       
   431 possible to retrieve the data by calling RFile::Open() on aName, but only if 
       
   432 aName is a legal file-name. It may be something else, such as a URL.
       
   433 
       
   434 The default implementation does not recognize data.
       
   435 
       
   436 @param aName The name of the data; typically this is a file name containing 
       
   437 the data to be recognized. It is not necessarily a legal file-name though. It 
       
   438 may, for example, be a URL/URI.
       
   439 @param aBuffer A buffer containing data to be recognized; typically, this is 
       
   440 read from the start of the file containing the data.
       
   441 @see RecognizeL()
       
   442 @see FilePassedByHandleL()
       
   443 */
       
   444 	{
       
   445 	(void)aName;
       
   446 	(void)aBuffer;
       
   447 	iDataType=TDataType();
       
   448 	}
       
   449 
       
   450 EXPORT_C RFile* CApaDataRecognizerType::FilePassedByHandleL()
       
   451 /** Returns the RFile (if any) of file to be recognized.
       
   452 
       
   453 This function returns the file passed by handle from the client-side (i.e. from calls to the RFile-parameter overloads of RApaLsSession's RecognizeData, RecognizeSpecificData, AppForDocument and StartDocument). The function returns NULL if the file to be recognized was not passed by handle.
       
   454 
       
   455 It may only be called from implementations of DoRecognizeL - indeed the purpose of this function is logically to provide an extra parameter to the virtual DoRecognizeL function. All references/pointers to the 
       
   456 RFile object returned must be discarded when the implementation of DoRecognizeL returns.
       
   457 
       
   458 The RFile returned (if any) may be used by implementations of DoRecognizeL to retrieve more data than is provided in DoRecognizeL's aBuffer parameter.
       
   459 
       
   460 The current-position of the returned RFile is the start of the file.
       
   461 
       
   462 @return The file, passed by handle, to be recognized. Returns NULL if the data to be recognized was passed from the client-side by name/buffer rather than by file-handle. Ownership of the returned object is NOT transferred to the caller.
       
   463 @see DoRecognizeL()
       
   464 */
       
   465 	{
       
   466 	RFile* const filePassedByHandle=iDataRecognizerExtn->DataRecognizer().FilePassedByHandle();
       
   467 	if (filePassedByHandle!=NULL && (filePassedByHandle->SubSessionHandle()!=KNullHandle))
       
   468 		{
       
   469 		// set the current file-position to the start of the file
       
   470 		TInt filePosition=0;
       
   471 		User::LeaveIfError(filePassedByHandle->Seek(ESeekStart, filePosition));
       
   472 		}
       
   473 	return filePassedByHandle;
       
   474 	}
       
   475 
       
   476 EXPORT_C TDataRecognitionResult CApaDataRecognizerType::RecognizeL(const TDesC& aName, const TDesC8& aBuffer)
       
   477 /** Attempts to recognize data.
       
   478 
       
   479 This function is called by the Application Architecture server as a result 
       
   480 of client calls to the server through an instance of RApaLsSession.
       
   481 
       
   482 The function calls DoRecognizeL() which implements recognition behaviour.
       
   483 
       
   484 @param aName The name of the data; typically this is a file name containing 
       
   485 the data to be recognized.
       
   486 @param aBuffer A buffer containing data to be recognized; typically, this is 
       
   487 read from the start of the file containing the data. Implement PreferredBufSize() 
       
   488 to define the ideal size for this buffer. Note that failure to implement PreferredBufSize() 
       
   489 results in a default buffer size of zero.
       
   490 @return The result of the attempt to recognize the data.
       
   491 @see PreferredBufSize()
       
   492 @see RApaLsSession
       
   493 @see RApaLsSession::SetMaxDataBufSize() */
       
   494 	{
       
   495 	TDataToRecognize dataToRecognize(aName, aBuffer);
       
   496 	return RecognizeL(dataToRecognize);
       
   497 	}
       
   498 
       
   499 TDataRecognitionResult CApaDataRecognizerType::RecognizeL(TDataToRecognize& aDataToRecognize)
       
   500 /**
       
   501 @internalComponent
       
   502 */
       
   503 	{
       
   504 	iDataType=TDataType();
       
   505 	iConfidence=ENotRecognized;
       
   506 	aDataToRecognize.RecognizeL(*this);
       
   507 	TDataRecognitionResult rec;
       
   508 	rec.iDataType=iDataType;
       
   509 	rec.iConfidence=iConfidence;
       
   510 	return rec;
       
   511 	}
       
   512 
       
   513 EXPORT_C TDataType CApaDataRecognizerType::MimeType()
       
   514 /** Gets the data (MIME) type of the most recently recognized data.
       
   515 
       
   516 @return The data (MIME) type.
       
   517 @see iDataType */
       
   518 	{
       
   519 	return iDataType;
       
   520 	}
       
   521 
       
   522 EXPORT_C void CApaDataRecognizerType::Reserved_1()
       
   523 // a spare empty virtual function
       
   524 	{}
       
   525 
       
   526 // instantiate the ecom implementation class 
       
   527 EXPORT_C CApaDataRecognizerType* CApaDataRecognizerType::CreateDataRecognizerL(TUid aImplUid)
       
   528 	{
       
   529 #if !defined(USING_ECOM_RECOGS)
       
   530 	(void)aImplUid;
       
   531 	return NULL;
       
   532 #endif
       
   533 	CDataRecognizerExtension* const dataRecognizerExtn=CDataRecognizerExtension::NewL();
       
   534 	CleanupStack::PushL(dataRecognizerExtn);
       
   535 
       
   536 	CApaDataRecognizerType* const dataRecType=static_cast <CApaDataRecognizerType*>(REComSession::CreateImplementationL(aImplUid, dataRecognizerExtn->DestructorUidReference()));
       
   537 
       
   538 	dataRecType->iDataRecognizerExtn = dataRecognizerExtn;
       
   539 	CleanupStack::Pop(dataRecognizerExtn);
       
   540 
       
   541 	return dataRecType;
       
   542 	}
       
   543 
       
   544 CDataRecognizerExtension* CApaDataRecognizerType::DataRecognizerExtension()
       
   545 /** @internalComponent */
       
   546 	{
       
   547 	return iDataRecognizerExtn;
       
   548 	}
       
   549 
       
   550 //
       
   551 // class TDataRecognitionResult
       
   552 //
       
   553 
       
   554 EXPORT_C void TDataRecognitionResult::Reset()
       
   555 /** Resets the data type to the default data type and sets the confidence rating 
       
   556 to CApaDataRecognizerType::ENotRecognized.
       
   557 
       
   558 @see CApaDataRecognizerType::TRecognitionConfidence
       
   559 @see TDataType */
       
   560 	{
       
   561 	iDataType=TDataType();
       
   562 	iConfidence=CApaDataRecognizerType::ENotRecognized;
       
   563 	}
       
   564 
       
   565 //
       
   566 // class TDataToRecognize
       
   567 //
       
   568 
       
   569 TDataToRecognize::TDataToRecognize(const TDesC& aName, const TDesC8& aBuffer)
       
   570 	:iFlags(0),
       
   571 	 iName(&aName),
       
   572 	 iBuffer(&aBuffer),
       
   573 	 iDataRecognizer(NULL),
       
   574 	 iFile(NULL),
       
   575 	 iFilePosition(0),
       
   576 	 iPreferredBufSize(0)
       
   577 	{
       
   578 	__ASSERT_DEBUG(aName.Length()>0 || aBuffer.Length()>0, Panic(EDPanicInvalidData));
       
   579 	}
       
   580 
       
   581 TDataToRecognize::TDataToRecognize(CApaDataRecognizer& aDataRecognizer, RFile& aFile, TInt aPreferredBufSize)
       
   582 	:iFlags(0),
       
   583 	 iName(NULL),
       
   584 	 iBuffer(NULL),
       
   585 	 iDataRecognizer(&aDataRecognizer),
       
   586 	 iFile(&aFile),
       
   587 	 iFilePosition(0),
       
   588 	 iPreferredBufSize(aPreferredBufSize)
       
   589 	{
       
   590 	}
       
   591 
       
   592 void TDataToRecognize::RecognizeL(CApaDataRecognizerType& aDataRecognizerType)
       
   593 	{
       
   594 	__ASSERT_DEBUG(iName!=NULL, Panic(EDPanicNullPointer1));
       
   595 	__ASSERT_DEBUG(iBuffer!=NULL, Panic(EDPanicNullPointer2));
       
   596 	aDataRecognizerType.DoRecognizeL(*iName, *iBuffer);
       
   597 	}
       
   598 
       
   599 void TDataToRecognize::PrepareForRecognizeLoopLC()
       
   600 	{
       
   601 	CleanupStack::PushL(TCleanupItem(ResetAfterRecognizeLoopL, this));
       
   602 	if (iFile!=NULL)
       
   603 		{
       
   604 		// set the file-pointer returned by CApaDataRecognizerType::FilePassedByHandleL
       
   605 		iDataRecognizer->SetFilePassedByHandle(iFile);
       
   606 
       
   607 		// store current-position in iFilePosition
       
   608 		__ASSERT_DEBUG((iFlags&EFlagFilePositionStored)==0, Panic(EDPanicBadFlagState1));
       
   609 		iFlags|=EFlagFilePositionStored;
       
   610 		iFilePosition=0;
       
   611 		User::LeaveIfError(iFile->Seek(ESeekCurrent, iFilePosition));
       
   612 
       
   613 		// read a buffer of the appropriate length from the start of the file
       
   614 		__ASSERT_DEBUG(iBuffer==NULL, Panic(EDPanicNullPointerExpected1));
       
   615 		TInt filePosition=0;
       
   616 		User::LeaveIfError(iFile->Seek(ESeekStart, filePosition));
       
   617 		HBufC8* const buffer=HBufC8::NewL(iPreferredBufSize);
       
   618 		iBuffer=buffer; // iBuffer now "owns" this (as long as iFile!=NULL, which is true)
       
   619 		TPtr8 buffer_asWritable(buffer->Des());
       
   620 		User::LeaveIfError(iFile->Read(buffer_asWritable));
       
   621 
       
   622 		// prepend "::" to the file-name to be passed to DoRecognizeL to make it an illegal file-name - this
       
   623 		// is to prevent any behavioural break since implementers of DoRecognizeL may assume that if aName is
       
   624 		// *not* an illegal file-name they can pass it to RFile::Open, which will not be possible if we're
       
   625 		// recognizing by file-handle, both because of data-caging (the file may not live in a directory that
       
   626 		// the Apparc process has permission to open it from) and because aName does not contain the full path
       
   627 		__ASSERT_DEBUG(iName==NULL, Panic(EDPanicNullPointerExpected2));
       
   628 		TDes* const name=new(ELeave) TFileName;
       
   629 		iName=name; // iName now "owns" this (as long as iFile!=NULL, which is true)
       
   630 		User::LeaveIfError(iFile->Name(*name));
       
   631 		_LIT(KLitIllegalifier, "::");
       
   632 		name->Insert(0, KLitIllegalifier);
       
   633 		}
       
   634 	}
       
   635 
       
   636 void TDataToRecognize::PopOffCleanupStackAndResetAfterRecognizeLoopL()
       
   637 	{
       
   638 	iFlags|=EFlagLeaveIfError; // we don't want to leave from ResetAfterRecognizeLoopL if we're being cleaned up from the clean-up stack because of a leave, but if we're leaving because of a CleanupStack::PopAndDestroy then it's okay to leave
       
   639 	CleanupStack::PopAndDestroy(this); // calls ResetAfterRecognizeLoopL
       
   640 	}
       
   641 
       
   642 void TDataToRecognize::ResetAfterRecognizeLoopL(TAny* aThis)
       
   643 	{ // static
       
   644 	STATIC_CAST(TDataToRecognize*, aThis)->ResetAfterRecognizeLoopL();
       
   645 	}
       
   646 
       
   647 void TDataToRecognize::ResetAfterRecognizeLoopL()
       
   648 	{
       
   649 	TInt error=KErrNone;
       
   650 	if (iFile!=NULL)
       
   651 		{
       
   652 		// NULLify the file-pointer returned by CApaDataRecognizerType::FilePassedByHandleL
       
   653 		iDataRecognizer->SetFilePassedByHandle(NULL);
       
   654 
       
   655 		// reset the current-position of the file
       
   656 		__ASSERT_DEBUG(iFlags&EFlagFilePositionStored, Panic(EDPanicBadFlagState2));
       
   657 		error=iFile->Seek(ESeekStart, iFilePosition);
       
   658 		iFlags&=~EFlagFilePositionStored;
       
   659 
       
   660 		// delete the objects that are owned if iFile!=NULL (which is true)
       
   661 		delete iName;
       
   662 		delete iBuffer;
       
   663 		}
       
   664 	if (iFlags&EFlagLeaveIfError)
       
   665 		{
       
   666 		iFlags&=~EFlagLeaveIfError; // probably not necessary, just defensive programming
       
   667 		User::LeaveIfError(error);
       
   668 		}
       
   669 	}
       
   670