mtpfws/mtpfw/datatypes/src/cmtptypeobjectproplist.cpp
changeset 0 d0791faffa3f
child 17 dbd1c5e08735
equal deleted inserted replaced
-1:000000000000 0:d0791faffa3f
       
     1 // Copyright (c) 2006-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 /**
       
    17  @file
       
    18  @publishedPartner
       
    19 */
       
    20 
       
    21 #include <mtp/cmtptypeobjectpropdesc.h>
       
    22 #include <mtp/cmtptypearray.h>
       
    23 #include <mtp/cmtptypeobjectproplist.h>
       
    24 #include <mtp/mtpdatatypeconstants.h>
       
    25 #include <mtp/mtpprotocolconstants.h>
       
    26 #include <e32debug.h> 
       
    27 #include "mtpdatatypespanic.h"
       
    28 #include "e32cmn.h" 
       
    29 #include <utf.h>
       
    30 // Dataset constants
       
    31 
       
    32 const TInt KMTPPropListBufferPageSize(0x00010000); // 64kB
       
    33 const TInt KReservedTransportHeaderSize(32);
       
    34 const TInt KMaxStringSize(255);
       
    35 const TUint8 KPropElemHeaderSize(sizeof(TUint32) + sizeof(TUint16) + sizeof(TUint16));
       
    36 _LIT8(KMtpStringTerminator, "\0\0");
       
    37 
       
    38 /**
       
    39 MTP ObjectPropList dataset factory method. This method is used to create an 
       
    40 empty MTP ObjectPropList dataset. 
       
    41 @return A pointer to the MTP ObjectPropList dataset type. Ownership IS 
       
    42 transfered.
       
    43 @leave One of the system wide error codes, if unsuccessful.
       
    44 */ 
       
    45 EXPORT_C CMTPTypeObjectPropList* CMTPTypeObjectPropList::NewL()
       
    46     {
       
    47     CMTPTypeObjectPropList* self = CMTPTypeObjectPropList::NewLC(); 
       
    48     CleanupStack::Pop(self);
       
    49     return self;  
       
    50     }
       
    51 
       
    52 /**
       
    53 MTP ObjectPropList dataset factory method. This method is used to create an 
       
    54 empty MTP ObjectPropList dataset. A pointer to the data type is placed on the
       
    55 cleanup stack.
       
    56 @return A pointer to the MTP ObjectPropList dataset type. Ownership IS 
       
    57 transfered.
       
    58 @leave One of the system wide error codes, if unsuccessful.
       
    59 */ 
       
    60 EXPORT_C CMTPTypeObjectPropList* CMTPTypeObjectPropList::NewLC()
       
    61     {
       
    62     CMTPTypeObjectPropList* self = new(ELeave) CMTPTypeObjectPropList();
       
    63     CleanupStack::PushL(self);
       
    64     self->ConstructL();
       
    65     return self;
       
    66     }
       
    67 
       
    68 CMTPTypeObjectPropList::CMTPTypeObjectPropList()
       
    69     {
       
    70 	
       
    71     }
       
    72 
       
    73 /**
       
    74 Destructor.
       
    75 */
       
    76 EXPORT_C CMTPTypeObjectPropList::~CMTPTypeObjectPropList()
       
    77     {
       
    78     TInt pageCount = iIOPages.Count();
       
    79     for(TInt i =0; i< pageCount; i++)
       
    80     	{
       
    81 		iIOPages[i].Close();    	
       
    82     	}
       
    83 	iIOPages.Close();
       
    84 	delete iCurrentElement;
       
    85 	delete iReservedElement;
       
    86     }
       
    87 
       
    88 void CMTPTypeObjectPropList::ConstructL()
       
    89 {
       
    90     ReserveNewPage();
       
    91 	iNumberOfElements = 0;
       
    92 	memcpy(&(iIOPages[0][KReservedTransportHeaderSize]), &iNumberOfElements, sizeof(TUint32));
       
    93 	iTransportHeaderIndex = KReservedTransportHeaderSize;
       
    94 	iRevPageEnd = 0;
       
    95 	iRevDataEnd = KReservedTransportHeaderSize + 4;
       
    96 	iReservedElemCommitted = ETrue;
       
    97 }
       
    98 
       
    99 EXPORT_C CMTPTypeObjectPropListElement& CMTPTypeObjectPropList::ReservePropElemL(TUint32 aHandle, TUint16 aPropCode)
       
   100     {
       
   101     if (NULL == iReservedElement)
       
   102         {
       
   103         iReservedElement = CMTPTypeObjectPropListElement::NewL(this);
       
   104         }
       
   105     
       
   106     iReservedElement->iObjectHandle = aHandle;
       
   107     iReservedElement->iPropertyCode = aPropCode;
       
   108     iReservedElement->iDataType = 0x0000;
       
   109     iReservedElement->iPageIndex = iRevPageEnd;
       
   110     iReservedElement->iBufIndex = iRevDataEnd;
       
   111     iReservedElement->iArrayBuffered = EFalse;
       
   112     
       
   113     TUint pageIndex = iReservedElement->iPageIndex;
       
   114     TUint bufIndex = iReservedElement->iBufIndex;
       
   115     
       
   116     MemoryCopyL(pageIndex, bufIndex, &(iReservedElement->iObjectHandle), sizeof(TUint32));
       
   117     IncreaseIndexL(pageIndex, bufIndex, sizeof(TUint32), ETrue);
       
   118     MemoryCopyL(pageIndex, bufIndex, &(iReservedElement->iPropertyCode), sizeof(TUint16));
       
   119     IncreaseIndexL(pageIndex, bufIndex, sizeof(TUint16), ETrue);
       
   120     MemoryCopyL(pageIndex, bufIndex, &(iReservedElement->iDataType), sizeof(TUint16));
       
   121     IncreaseIndexL(pageIndex, bufIndex, sizeof(TUint16), ETrue);
       
   122     
       
   123     iReservedElement->iValueSize = 0;
       
   124     
       
   125     iReservedElemCommitted = EFalse;
       
   126     
       
   127     return *iReservedElement;
       
   128     }
       
   129 
       
   130 EXPORT_C void CMTPTypeObjectPropList::CommitPropElemL(CMTPTypeObjectPropListElement& aElem)
       
   131     {
       
   132     if (&aElem != iReservedElement || iReservedElemCommitted 
       
   133             || iReservedElement->iValueSize == 0)
       
   134         {
       
   135         __ASSERT_DEBUG(EFalse, User::Invariant());
       
   136         }
       
   137     TUint elemSize = iReservedElement->Size();
       
   138     // Update iRevDataEnd, reallocate new buffer page if need
       
   139     IncreaseIndexL(iRevPageEnd, iRevDataEnd, elemSize, ETrue);
       
   140     ++(iNumberOfElements);
       
   141     memcpy(&(iIOPages[0][KReservedTransportHeaderSize]), &iNumberOfElements, sizeof(TUint32));
       
   142     
       
   143     iReservedElemCommitted = ETrue;
       
   144     }
       
   145 
       
   146 
       
   147 EXPORT_C CMTPTypeObjectPropListElement& CMTPTypeObjectPropList::GetNextElementL() const
       
   148     {
       
   149     // Update the page index and buffer index of element
       
   150     if (NULL == iCurrentElement)
       
   151         {
       
   152         ResetCursor();
       
   153         }
       
   154     
       
   155     if (iResetCursor)
       
   156         {
       
   157         iResetCursor = EFalse;
       
   158         }
       
   159     else
       
   160         {
       
   161         TUint elemSize = iCurrentElement->Size();
       
   162         IncreaseIndexL(iCurrentElement->iPageIndex, iCurrentElement->iBufIndex, elemSize, EFalse);
       
   163         }
       
   164 
       
   165     iCurrentElement->iArrayBuffered = EFalse;
       
   166     
       
   167     // Copy value of handle/propcode/datatype from buffer to element
       
   168     TUint pageIndex = iCurrentElement->iPageIndex;
       
   169     TUint bufIndex = iCurrentElement->iBufIndex;
       
   170     MemoryCopyL(&(iCurrentElement->iObjectHandle), pageIndex, bufIndex, sizeof(TUint32));
       
   171     IncreaseIndexL(pageIndex, bufIndex, sizeof(TUint32), EFalse);
       
   172     MemoryCopyL(&(iCurrentElement->iPropertyCode), pageIndex, bufIndex, sizeof(TUint16));
       
   173     IncreaseIndexL(pageIndex, bufIndex, sizeof(TUint16), EFalse);
       
   174     MemoryCopyL(&(iCurrentElement->iDataType), pageIndex, bufIndex, sizeof(TUint16));
       
   175     IncreaseIndexL(pageIndex, bufIndex, sizeof(TUint16), EFalse);
       
   176 
       
   177     // Calculate value length
       
   178     switch(iCurrentElement->iDataType)
       
   179         {
       
   180         case EMTPTypeUINT8:
       
   181             iCurrentElement->iValueSize = sizeof(TUint8);
       
   182             break;
       
   183         case EMTPTypeUINT16:
       
   184             iCurrentElement->iValueSize = sizeof(TUint16);
       
   185             break;
       
   186         case EMTPTypeUINT32:
       
   187             iCurrentElement->iValueSize = sizeof(TUint32);
       
   188             break;
       
   189         case EMTPTypeUINT64:
       
   190             iCurrentElement->iValueSize = sizeof(TUint64);
       
   191             break;
       
   192         case EMTPTypeUINT128:
       
   193             iCurrentElement->iValueSize = 2 * sizeof(TUint64);
       
   194             break;
       
   195         case EMTPTypeString:
       
   196             {
       
   197             TUint8 arrayLen = 0;
       
   198             MemoryCopyL(&arrayLen, pageIndex, bufIndex, sizeof(TUint8));
       
   199             iCurrentElement->iValueSize = arrayLen * sizeof(TUint16) + sizeof(TUint8);
       
   200             break;
       
   201             }
       
   202         case EMTPTypeAUINT16:
       
   203         case EMTPTypeAUINT8:
       
   204         case EMTPTypeAUINT32:
       
   205         case EMTPTypeAUINT64:
       
   206         case EMTPTypeAUINT128:
       
   207             {
       
   208             TUint32 arrayLen = 0;
       
   209             TUint32 arrayWidth = ArrayElemWidth(iCurrentElement->iDataType);
       
   210             MemoryCopyL(&arrayLen, pageIndex, bufIndex, sizeof(TUint32));
       
   211             iCurrentElement->iValueSize = arrayLen * arrayWidth + sizeof(TUint32);
       
   212             break;
       
   213             }
       
   214         default:
       
   215             break;
       
   216         }
       
   217     
       
   218     return *iCurrentElement;
       
   219     }
       
   220 
       
   221 TBool CMTPTypeObjectPropList::ValueBufferConsistent(TUint /* aPageIdx */, TUint aBufferIdx, TUint aValueSize) const
       
   222     {
       
   223     if (aBufferIdx + aValueSize >= KMTPPropListBufferPageSize)
       
   224         {
       
   225         return EFalse;
       
   226         }
       
   227     
       
   228     return ETrue;
       
   229     }
       
   230 
       
   231 TBool CMTPTypeObjectPropList::ValueAddressAligned(TUint aPageIdx, TUint aBufferIdx) const
       
   232     {
       
   233     const TUint8* bufPtr = &(iIOPages[aPageIdx][aBufferIdx]);
       
   234     if (reinterpret_cast<TUint32>(bufPtr) & 1)
       
   235         {
       
   236         return EFalse;
       
   237         }
       
   238     
       
   239     return ETrue;
       
   240     }
       
   241 
       
   242 EXPORT_C TUint64 CMTPTypeObjectPropList::Size() const
       
   243 {
       
   244     TInt pageCount = iIOPages.Count();
       
   245     TUint64 totalSize = 0;
       
   246     totalSize = KMTPPropListBufferPageSize - KReservedTransportHeaderSize  
       
   247                 + KMTPPropListBufferPageSize * (iRevPageEnd - 1) + iRevDataEnd;
       
   248 
       
   249     return totalSize;
       
   250 }
       
   251 
       
   252 
       
   253 EXPORT_C TUint32 CMTPTypeObjectPropList::NumberOfElements() const
       
   254 	{
       
   255     return iNumberOfElements;
       
   256 	}
       
   257 
       
   258 EXPORT_C void CMTPTypeObjectPropList::ResetCursor() const
       
   259     {
       
   260     if (NULL == iCurrentElement)
       
   261         {
       
   262         CMTPTypeObjectPropList* propList = const_cast<CMTPTypeObjectPropList*>(this);
       
   263         iCurrentElement = CMTPTypeObjectPropListElement::NewL(propList);
       
   264         }
       
   265     iCurrentElement->iPageIndex = 0;
       
   266     iCurrentElement->iBufIndex = KReservedTransportHeaderSize + sizeof(TUint32);
       
   267     iResetCursor = ETrue;
       
   268     }
       
   269 
       
   270 EXPORT_C void CMTPTypeObjectPropList::AppendObjectPropListL(const CMTPTypeObjectPropList& aSource)
       
   271     {
       
   272     TInt chunkStatus = 0;
       
   273     TBool copyFirstChunk = ETrue;
       
   274     TUint srcElemNum = aSource.NumberOfElements();
       
   275     
       
   276     while (chunkStatus != KMTPChunkSequenceCompletion)
       
   277         {
       
   278         TPtrC8 tmpPtrRawData;
       
   279         if (copyFirstChunk)
       
   280             {
       
   281             chunkStatus = aSource.FirstReadChunk(tmpPtrRawData);
       
   282             tmpPtrRawData.Set(tmpPtrRawData.Ptr() + sizeof(TUint32), tmpPtrRawData.Length() - sizeof(TUint32));
       
   283             copyFirstChunk = EFalse;
       
   284             }
       
   285         else
       
   286             {
       
   287             chunkStatus = aSource.NextReadChunk(tmpPtrRawData);
       
   288             }
       
   289         
       
   290         const TUint8* srcPtr = tmpPtrRawData.Ptr();
       
   291         MemoryCopyL(iRevPageEnd, iRevDataEnd, srcPtr, tmpPtrRawData.Length());
       
   292         IncreaseIndexL(iRevPageEnd, iRevDataEnd, tmpPtrRawData.Length(), ETrue);
       
   293         }
       
   294     
       
   295     iNumberOfElements += srcElemNum;
       
   296     memcpy(&(iIOPages[0][KReservedTransportHeaderSize]), &iNumberOfElements, sizeof(TUint32));
       
   297     }
       
   298 
       
   299 EXPORT_C TInt CMTPTypeObjectPropList::FirstReadChunk(TPtrC8& aChunk) const
       
   300     {
       
   301     TInt ret = KMTPDataTypeInvalid;
       
   302     iChunkIndex = 0;
       
   303     if (iRevPageEnd == 0)
       
   304         {
       
   305         aChunk.Set(&(iIOPages[0][iTransportHeaderIndex]), iRevDataEnd - iTransportHeaderIndex);
       
   306         ret = KMTPChunkSequenceCompletion;
       
   307         }
       
   308     else
       
   309         {
       
   310         aChunk.Set(&(iIOPages[0][iTransportHeaderIndex]), KMTPPropListBufferPageSize - iTransportHeaderIndex);
       
   311         ret = KErrNone;
       
   312         }
       
   313     return ret;
       
   314     }
       
   315 
       
   316 EXPORT_C TInt CMTPTypeObjectPropList::NextReadChunk(TPtrC8& aChunk) const
       
   317 	{
       
   318 	TInt ret = KMTPDataTypeInvalid;
       
   319 	++iChunkIndex;
       
   320 	if (iChunkIndex < iRevPageEnd)
       
   321 	    {
       
   322         aChunk.Set(&(iIOPages[iChunkIndex][0]), KMTPPropListBufferPageSize);
       
   323         ret = KErrNone;
       
   324 	    }
       
   325 	else if (iChunkIndex == iRevPageEnd)
       
   326 	    {
       
   327         aChunk.Set(&(iIOPages[iChunkIndex][0]), iRevDataEnd);
       
   328         ret = KMTPChunkSequenceCompletion;
       
   329 	    }
       
   330 	
       
   331 	
       
   332 	return ret;
       
   333 	}
       
   334 
       
   335 EXPORT_C TInt CMTPTypeObjectPropList::FirstWriteChunk(TPtr8& aChunk)
       
   336 	{
       
   337     aChunk.Set(&(iIOPages[0][iTransportHeaderIndex]), 0, KMTPPropListBufferPageSize - iTransportHeaderIndex);
       
   338     return KErrNone;
       
   339 	}
       
   340 
       
   341 EXPORT_C TInt CMTPTypeObjectPropList::NextWriteChunk(TPtr8& aChunk)
       
   342 	{
       
   343 	ReserveNewPage();
       
   344 	aChunk.Set(&(iIOPages[iIOPages.Count()-1][0]), 0, KMTPPropListBufferPageSize);
       
   345     return KErrNone;
       
   346 	}
       
   347 
       
   348 EXPORT_C TInt CMTPTypeObjectPropList::FirstWriteChunk(TPtr8& aChunk, TUint aDataLength)
       
   349     {
       
   350     TInt ret = KMTPDataTypeInvalid;
       
   351     if (aDataLength <= KMTPPropListBufferPageSize - iTransportHeaderIndex)
       
   352         {
       
   353         aChunk.Set(&(iIOPages[0][iTransportHeaderIndex]), 0, aDataLength);
       
   354         ret = KMTPChunkSequenceCompletion;
       
   355         }
       
   356     else
       
   357         {
       
   358         aChunk.Set(&(iIOPages[0][iTransportHeaderIndex]), 0, KMTPPropListBufferPageSize - iTransportHeaderIndex);
       
   359         ret = KErrNone;
       
   360         }
       
   361     
       
   362     return ret;
       
   363     }
       
   364 
       
   365 EXPORT_C TInt CMTPTypeObjectPropList::NextWriteChunk(TPtr8& aChunk, TUint aDataLength)
       
   366     {
       
   367     TInt ret = KMTPDataTypeInvalid;
       
   368     ReserveNewPage();
       
   369     if (aDataLength <= KMTPPropListBufferPageSize)
       
   370         {
       
   371         aChunk.Set(&(iIOPages[iIOPages.Count()-1][0]), 0, aDataLength);
       
   372         ret = KMTPChunkSequenceCompletion;
       
   373         }
       
   374     else
       
   375         {
       
   376         aChunk.Set(&(iIOPages[iIOPages.Count()-1][0]), 0, KMTPPropListBufferPageSize);
       
   377         ret = KErrNone;
       
   378         }
       
   379     
       
   380     return ret;    
       
   381     }
       
   382 
       
   383 EXPORT_C TUint CMTPTypeObjectPropList::Type() const
       
   384 	{
       
   385     return EMTPTypeObjectPropListDataset;
       
   386 	}
       
   387 
       
   388 EXPORT_C TBool CMTPTypeObjectPropList::CommitRequired() const
       
   389 	{
       
   390 	return ETrue;
       
   391 	}
       
   392 
       
   393 EXPORT_C MMTPType* CMTPTypeObjectPropList::CommitChunkL(TPtr8& aChunk)
       
   394 	{
       
   395 	iRevPageEnd = iIOPages.Count() - 1;
       
   396 	if (iRevPageEnd == 0)
       
   397 	    {
       
   398 	    iRevDataEnd = aChunk.Length() + KReservedTransportHeaderSize;
       
   399 	    
       
   400 	    if (aChunk.Length() >= sizeof(TUint32))
       
   401 	        {
       
   402 	        memcpy(&iNumberOfElements, &(iIOPages[0][KReservedTransportHeaderSize]), sizeof(TUint32));
       
   403 	        }	    
       
   404 	    }
       
   405 	else
       
   406 	    {
       
   407 	    iRevDataEnd = aChunk.Length();
       
   408 	    }
       
   409 
       
   410 	return NULL;
       
   411 	}
       
   412 
       
   413 EXPORT_C TBool CMTPTypeObjectPropList::ReserveTransportHeader(TUint aHeaderLength, TPtr8& aHeader)
       
   414 	{
       
   415     if (aHeaderLength > KReservedTransportHeaderSize)
       
   416         {
       
   417         return EFalse;
       
   418         }
       
   419     
       
   420     iTransportHeaderIndex = KReservedTransportHeaderSize - aHeaderLength;
       
   421     
       
   422     aHeader.Set(&(iIOPages[0][iTransportHeaderIndex]), aHeaderLength, aHeaderLength);
       
   423     return ETrue;
       
   424 	}
       
   425 
       
   426 EXPORT_C TInt CMTPTypeObjectPropList::Validate() const
       
   427     {
       
   428     TInt relValue(KErrNone);
       
   429 	TUint32 num = NumberOfElements();
       
   430 	ResetCursor();
       
   431 	for(TUint32 i = 0; i< num;i++)
       
   432 		{
       
   433 		TRAPD(err, GetNextElementL())
       
   434 		if(KErrNone != err)
       
   435 			{
       
   436 			relValue = KMTPDataTypeInvalid;
       
   437 			break;
       
   438 			}
       
   439 		}	
       
   440 	
       
   441 	ResetCursor();
       
   442 	return relValue;
       
   443 	}
       
   444 
       
   445 TUint CMTPTypeObjectPropList::ArrayElemWidth(TUint16& aDataType) const
       
   446 	{
       
   447 	TUint width(0);
       
   448 	switch(aDataType)
       
   449 		{
       
   450 		case EMTPTypeAUINT8:
       
   451 			width = 1;
       
   452 			break;
       
   453 	    case EMTPTypeAUINT16:
       
   454 			width = 2;
       
   455 			break;			
       
   456 	    case EMTPTypeAUINT32:
       
   457 			width = 4;
       
   458 			break;			
       
   459 	    case EMTPTypeAUINT64:
       
   460 			width = 8;
       
   461 			break;			
       
   462 	    case EMTPTypeAUINT128:
       
   463 			width = 16;
       
   464 			break;			
       
   465 		default:
       
   466 			break;
       
   467 		}
       
   468 	return width;
       
   469 	}
       
   470 
       
   471 void CMTPTypeObjectPropList::IncreaseIndexL(TUint& aPageIndex, TUint& aBufIndex, TUint aLength, TBool aReserveNewPage) const
       
   472     {
       
   473     aBufIndex += aLength;
       
   474     while (aBufIndex >= KMTPPropListBufferPageSize)
       
   475         {
       
   476         aBufIndex -= KMTPPropListBufferPageSize;
       
   477         ++aPageIndex;
       
   478         if (aPageIndex >= iIOPages.Count())
       
   479             {
       
   480             if (aReserveNewPage)
       
   481                 {
       
   482                 const_cast<CMTPTypeObjectPropList*>(this)->ReserveNewPage();
       
   483                 }
       
   484             else
       
   485                 {
       
   486                 User::Leave(KErrOverflow);
       
   487                 }
       
   488             }
       
   489         }
       
   490     }
       
   491 
       
   492 void CMTPTypeObjectPropList::ReserveNewPage()
       
   493     {
       
   494     RBuf8 tmpBuffer;
       
   495     iIOPages.AppendL(tmpBuffer);
       
   496     iIOPages[iIOPages.Count() - 1].CreateMaxL(KMTPPropListBufferPageSize);
       
   497     }
       
   498 
       
   499 void CMTPTypeObjectPropList::MemoryCopyL(TAny* aTrg, TUint aSrcPageIndex, TUint aSrcBufIndex, TUint aLength) const
       
   500     {
       
   501     TUint bytesLeft = aLength;
       
   502     TUint curPageIdx = aSrcPageIndex;
       
   503     TUint curSrcBufIdx = aSrcBufIndex;
       
   504     TUint8* copyTo = reinterpret_cast<TUint8*>(aTrg);
       
   505     while (bytesLeft > 0)
       
   506         {
       
   507         const TUint8* srcBuf = &(iIOPages[curPageIdx][curSrcBufIdx]);
       
   508         TUint copySize = bytesLeft;
       
   509         if (curSrcBufIdx + bytesLeft > KMTPPropListBufferPageSize)
       
   510             {
       
   511             copySize = KMTPPropListBufferPageSize - curSrcBufIdx;
       
   512             ++curPageIdx;
       
   513             curSrcBufIdx = 0;
       
   514             }
       
   515         
       
   516         if (curPageIdx >= iIOPages.Count())
       
   517             {
       
   518             User::Leave(KErrOverflow);
       
   519             }
       
   520         else if ((curPageIdx == iIOPages.Count() - 1) && curSrcBufIdx + bytesLeft - copySize > iRevDataEnd)
       
   521             {
       
   522             User::Leave(KErrOverflow);
       
   523             }
       
   524         
       
   525         memcpy(copyTo, srcBuf, copySize);
       
   526         bytesLeft -= copySize;
       
   527         copyTo += copySize;
       
   528         }
       
   529     }
       
   530 
       
   531 void CMTPTypeObjectPropList::MemoryCopyL(TUint aTrgPageIndex, TUint aTrgBufIndex, const TAny* aSrc, TUint aLength)
       
   532     {
       
   533     TUint bytesLeft = aLength;
       
   534     TUint curPageIdx = aTrgPageIndex;
       
   535     TUint curSrcBufIdx = aTrgBufIndex;
       
   536     const TUint8* copyFrom = reinterpret_cast<const TUint8*>(aSrc);
       
   537     while (bytesLeft > 0)
       
   538         {
       
   539         if (curPageIdx == iIOPages.Count())
       
   540             {
       
   541             ReserveNewPage();
       
   542             }        
       
   543         TUint8* trgBuf = &(iIOPages[curPageIdx][curSrcBufIdx]);
       
   544         TUint copySize = bytesLeft;
       
   545         if (curSrcBufIdx + bytesLeft > KMTPPropListBufferPageSize)
       
   546             {
       
   547             copySize = KMTPPropListBufferPageSize - curSrcBufIdx;
       
   548             ++curPageIdx;
       
   549             curSrcBufIdx = 0;
       
   550             }
       
   551         memcpy(trgBuf, copyFrom, copySize);
       
   552         bytesLeft -= copySize;
       
   553         copyFrom += copySize;
       
   554         }
       
   555     }
       
   556 
       
   557 CMTPTypeObjectPropListElement* CMTPTypeObjectPropListElement::NewL(CMTPTypeObjectPropList* propList)
       
   558 	{
       
   559 	CMTPTypeObjectPropListElement* self = NewLC(propList);
       
   560 	CleanupStack::Pop(self);
       
   561 	return self;
       
   562 	}
       
   563 
       
   564 CMTPTypeObjectPropListElement* CMTPTypeObjectPropListElement::NewLC(CMTPTypeObjectPropList* propList)
       
   565     {
       
   566     CMTPTypeObjectPropListElement* self = new(ELeave) CMTPTypeObjectPropListElement();
       
   567     CleanupStack::PushL(self);
       
   568     self->ConstructL(propList);
       
   569     return self;
       
   570     }
       
   571 
       
   572 CMTPTypeObjectPropListElement::CMTPTypeObjectPropListElement()
       
   573 	{
       
   574 
       
   575 	}
       
   576 
       
   577 EXPORT_C CMTPTypeObjectPropListElement::~CMTPTypeObjectPropListElement()
       
   578 	{
       
   579 	iStringHolder.Close();
       
   580 	}
       
   581 
       
   582 void CMTPTypeObjectPropListElement::ConstructL(CMTPTypeObjectPropList* propList)
       
   583 	{
       
   584 	iArrayBuffered = EFalse;
       
   585     iPropList = propList;
       
   586 	iStringHolder.CreateL(KMaxStringSize);
       
   587 	}
       
   588 
       
   589 EXPORT_C TUint8 CMTPTypeObjectPropListElement::Uint8L(TInt aElementId) const
       
   590 	{
       
   591 	if(EValue != aElementId || EMTPTypeUINT8 != iDataType)
       
   592 	    User::Leave(KErrArgument);
       
   593 	TUint8 retValue = 0;
       
   594 	GetValueL(&retValue, sizeof(TUint8));
       
   595 
       
   596 	return retValue;
       
   597 	}
       
   598 
       
   599 EXPORT_C TUint16 CMTPTypeObjectPropListElement::Uint16L(TInt aElementId) const
       
   600 	{
       
   601 	switch(aElementId)
       
   602 		{
       
   603 		case EPropertyCode:
       
   604 			return iPropertyCode;
       
   605 		case EDatatype:
       
   606 			return iDataType;
       
   607 		case EValue:
       
   608             if(EMTPTypeUINT16 != iDataType)
       
   609                 {
       
   610                   User::Leave(KErrArgument);
       
   611                 }
       
   612             TUint16 retValue;
       
   613             GetValueL(&retValue, sizeof(TUint16));
       
   614 			return retValue;
       
   615 		default:
       
   616 			User::Leave(KErrArgument);
       
   617 		}	
       
   618 	return 0;
       
   619 	}
       
   620 
       
   621 EXPORT_C TUint32 CMTPTypeObjectPropListElement::Uint32L(TInt aElementId) const
       
   622 	{
       
   623 	switch(aElementId)
       
   624 		{
       
   625 		case EObjectHandle:
       
   626 			return iObjectHandle;
       
   627 		case EValue:
       
   628 		    if(EMTPTypeUINT32 != iDataType)
       
   629 		        {
       
   630 		          User::Leave(KErrArgument);
       
   631 		        }
       
   632 		    TUint32 retValue;
       
   633 		    GetValueL(&retValue, sizeof(TUint32));
       
   634 		    return retValue;
       
   635 		default:
       
   636 			User::Leave(KErrArgument);	
       
   637 		}
       
   638 	return 0;
       
   639 	}
       
   640 
       
   641 EXPORT_C TUint64 CMTPTypeObjectPropListElement::Uint64L(TInt aElementId) const
       
   642 	{
       
   643 	if(EValue != aElementId || EMTPTypeUINT64 != iDataType)
       
   644 	    {
       
   645 	    User::Leave(KErrArgument);
       
   646 	    }
       
   647 	
       
   648 	TUint64 retValue;
       
   649 	GetValueL(&retValue, sizeof(TUint64));	
       
   650 	return retValue;
       
   651 	}
       
   652 
       
   653 EXPORT_C void CMTPTypeObjectPropListElement::Uint128L(TInt aElementId,TUint64& high, TUint64& low) const
       
   654 	{
       
   655 	if(EValue != aElementId || EMTPTypeUINT128 != iDataType)
       
   656 	    {
       
   657 	    User::Leave(KErrArgument);
       
   658 	    }
       
   659     TUint pageIndex = iPageIndex;
       
   660     TUint bufIndex = iBufIndex;
       
   661     iPropList->IncreaseIndexL(pageIndex, bufIndex, KPropElemHeaderSize, EFalse);
       
   662     iPropList->MemoryCopyL(&low, pageIndex, bufIndex, sizeof(TUint64));
       
   663     iPropList->IncreaseIndexL(pageIndex, bufIndex, sizeof(TUint64), EFalse);
       
   664     iPropList->MemoryCopyL(&high, pageIndex, bufIndex, sizeof(TUint64));
       
   665 	}
       
   666 
       
   667 EXPORT_C const TDesC& CMTPTypeObjectPropListElement::StringL(TInt aElementId) const
       
   668 	{
       
   669 	if(EValue != aElementId || EMTPTypeString != iDataType)
       
   670 	    {
       
   671 	    User::Leave(KErrArgument);
       
   672 	    }
       
   673 	
       
   674 	if (!iArrayBuffered)
       
   675 	    {
       
   676         TUint arrayLen = 0;
       
   677         TUint pageIndex = iPageIndex;
       
   678         TUint bufIndex = iBufIndex;
       
   679         iPropList->IncreaseIndexL(pageIndex, bufIndex, KPropElemHeaderSize, EFalse);
       
   680         iPropList->MemoryCopyL(&arrayLen, pageIndex, bufIndex, sizeof(TUint8));
       
   681         iPropList->IncreaseIndexL(pageIndex, bufIndex, sizeof(TUint8), EFalse);
       
   682         
       
   683         if (arrayLen == 0)
       
   684             {
       
   685             // Empty string
       
   686             iStringValue.Set(iStringHolder.Ptr(), 0);
       
   687             }
       
   688         else if (iPropList->ValueBufferConsistent(pageIndex, bufIndex, (arrayLen - 1) * sizeof(TUint16))
       
   689                 && iPropList->ValueAddressAligned(pageIndex, bufIndex))
       
   690             {
       
   691             //No need to copy data
       
   692             const TUint8* srcPtr = &(iPropList->iIOPages[pageIndex][bufIndex]);            
       
   693             iStringValue.Set(reinterpret_cast<const TUint16*>(srcPtr), arrayLen - 1);
       
   694             }
       
   695         else
       
   696             {
       
   697             // The address of srcPtr is not aligned, can't pass the address to TPtr16::Set() 
       
   698             // Copy the string data in buffer to iStringHolder
       
   699             TUint16* dstPtr = const_cast<TUint16*>(iStringHolder.Ptr());
       
   700             iPropList->MemoryCopyL(dstPtr, pageIndex, bufIndex, (arrayLen - 1) * sizeof(TUint16));
       
   701             iStringValue.Set(dstPtr, arrayLen - 1);
       
   702             }
       
   703         
       
   704 	    iArrayBuffered = ETrue;
       
   705 	    }
       
   706 
       
   707 	return iStringValue;
       
   708 	}
       
   709 
       
   710 EXPORT_C const TDesC8& CMTPTypeObjectPropListElement::ArrayL(TInt aElementId) const
       
   711 	{
       
   712 	if(EValue != aElementId || iDataType < EMTPTypeFirstSimpleArrayType 
       
   713 	        || iDataType > EMTPTypeLastSimpleArrayType)
       
   714 	    {
       
   715 	    User::Leave(KErrArgument);
       
   716 	    }
       
   717 	
       
   718    if (!iArrayBuffered)
       
   719         {
       
   720         TUint32 arrayLen = 0;
       
   721         TUint32 arrayWidth = iPropList->ArrayElemWidth(iDataType);
       
   722         
       
   723         TUint pageIndex = iPageIndex;
       
   724         TUint bufIndex = iBufIndex;
       
   725         iPropList->IncreaseIndexL(pageIndex, bufIndex, KPropElemHeaderSize, EFalse);
       
   726         iPropList->MemoryCopyL(&arrayLen, pageIndex, bufIndex, sizeof(TUint32));
       
   727         iPropList->IncreaseIndexL(pageIndex, bufIndex, sizeof(TUint32), EFalse);
       
   728         
       
   729         if (arrayLen == 0)
       
   730             {
       
   731             // Empty array
       
   732             iArrayValue.Set(reinterpret_cast<const TUint8*>(iStringHolder.Ptr()), 0);
       
   733             }
       
   734         // if iDataType == EMTPTypeAINT16 or iDataType == EMTPTypeAUINT16, the array maybe be converted to TDes16 by the user, the address should be aligned
       
   735         else if (iPropList->ValueBufferConsistent(pageIndex, bufIndex, arrayLen * arrayWidth)
       
   736                 && ((iDataType != EMTPTypeAINT16 && iDataType != EMTPTypeAUINT16) || iPropList->ValueAddressAligned(pageIndex, bufIndex)))
       
   737             {
       
   738             //No need to copy data
       
   739             const TUint8* srcPtr = &(iPropList->iIOPages[pageIndex][bufIndex]);
       
   740             iArrayValue.Set(srcPtr, arrayLen * arrayWidth);
       
   741             }
       
   742         else
       
   743             {
       
   744             // The address of srcPtr is not aligned, can't pass the address to TPtr16::Set() 
       
   745             // Copy the array data in buffer to iStringHolder
       
   746             if (iStringHolder.MaxLength() * sizeof(TUint16) < arrayLen * arrayWidth)
       
   747                 {
       
   748                 iStringHolder.Zero();
       
   749                 iStringHolder.ReAllocL((arrayLen * arrayWidth + 1) / sizeof(TUint16));
       
   750                 }
       
   751             TUint16* dstPtr = const_cast<TUint16*>(iStringHolder.Ptr());
       
   752             iPropList->MemoryCopyL(dstPtr, pageIndex, bufIndex, arrayLen * arrayWidth);
       
   753             iArrayValue.Set(reinterpret_cast<const TUint8*>(dstPtr), arrayLen * arrayWidth);
       
   754             }
       
   755         iArrayBuffered = ETrue;
       
   756         }
       
   757    
       
   758 	return iArrayValue;
       
   759 	}
       
   760 
       
   761 
       
   762 EXPORT_C void CMTPTypeObjectPropListElement::SetUint8L(TInt aElementId, TUint8 aData)
       
   763     {
       
   764     if(EValue != aElementId)
       
   765         {
       
   766         User::Leave(KErrArgument);
       
   767         }
       
   768     
       
   769     SetDataType(EMTPTypeUINT8);
       
   770     SetValueL(&aData, sizeof(TUint8));
       
   771     }
       
   772 
       
   773 EXPORT_C void CMTPTypeObjectPropListElement::SetUint16L(TInt aElementId, TUint16 aData)
       
   774     {
       
   775     switch(aElementId)
       
   776         {
       
   777         case EPropertyCode:
       
   778             {
       
   779             iPropertyCode = aData;
       
   780             // Copy PropertyCode to page buffer
       
   781             TUint pageIndex = iPageIndex;
       
   782             TUint bufIndex = iBufIndex;
       
   783             iPropList->IncreaseIndexL(pageIndex, bufIndex, sizeof(TUint32), ETrue);
       
   784             iPropList->MemoryCopyL(pageIndex, bufIndex, &aData, sizeof(TUint16));
       
   785             }
       
   786             break;
       
   787         case EDatatype:
       
   788             SetDataType(aData);
       
   789             break;
       
   790         case EValue:
       
   791             SetDataType(EMTPTypeUINT16);
       
   792             SetValueL(&aData, sizeof(TUint16));
       
   793             break;
       
   794         default:
       
   795             User::Leave(KErrArgument);
       
   796         }   
       
   797     }
       
   798 
       
   799 EXPORT_C void CMTPTypeObjectPropListElement::SetUint32L(TInt aElementId, TUint32 aData)
       
   800     {
       
   801     switch(aElementId)
       
   802         {
       
   803         case EObjectHandle:
       
   804             iObjectHandle = aData;
       
   805             iPropList->MemoryCopyL(iPageIndex, iBufIndex, &aData, sizeof(TUint32));
       
   806             break;
       
   807         case EValue:
       
   808             SetDataType(EMTPTypeUINT32);
       
   809             SetValueL(&aData, sizeof(TUint32));
       
   810             break;
       
   811         default:
       
   812             User::Leave(KErrArgument);
       
   813         }
       
   814     }
       
   815 
       
   816 EXPORT_C void CMTPTypeObjectPropListElement::SetUint64L(TInt aElementId, TUint64 aData)
       
   817     {
       
   818     if(EValue != aElementId)
       
   819         User::Leave(KErrArgument);
       
   820     
       
   821     SetDataType(EMTPTypeUINT64);
       
   822     SetValueL(&aData, sizeof(TUint64));
       
   823     }
       
   824 
       
   825 EXPORT_C void CMTPTypeObjectPropListElement::SetUint128L(TInt aElementId, TUint64 high, TUint64 low)
       
   826     {
       
   827     if(EValue != aElementId)
       
   828         {
       
   829         User::Leave(KErrArgument);
       
   830         }
       
   831     
       
   832     SetDataType(EMTPTypeUINT128);
       
   833     TUint pageIndex = iPageIndex;
       
   834     TUint bufIndex = iBufIndex;
       
   835     iPropList->IncreaseIndexL(pageIndex, bufIndex, KPropElemHeaderSize, ETrue);
       
   836     iPropList->MemoryCopyL(pageIndex, bufIndex, &low, sizeof(TUint64));
       
   837     iPropList->IncreaseIndexL(pageIndex, bufIndex, sizeof(TUint64), ETrue);
       
   838     iPropList->MemoryCopyL(pageIndex, bufIndex, &high, sizeof(TUint64));
       
   839     iValueSize = sizeof(TUint64) * 2;
       
   840     }
       
   841 
       
   842 EXPORT_C void CMTPTypeObjectPropListElement::SetStringL(TInt aElementId, const TDesC& aString)
       
   843     {
       
   844     if(EValue != aElementId || aString.Length() > KMaxStringSize)
       
   845         {
       
   846         User::Leave(KErrArgument);
       
   847         }
       
   848     
       
   849     TUint8 len = aString.Length() + 1;
       
   850 
       
   851     // For string which length is 255, truncate the last character to handle the file name of 255
       
   852     if (aString.Length() == KMaxStringSize)
       
   853         {
       
   854         len = KMaxStringSize;
       
   855         }
       
   856     
       
   857     SetDataType(EMTPTypeString);
       
   858 
       
   859 
       
   860     iValueSize = 1 + len * sizeof(TUint16);
       
   861     TUint pageIndex = iPageIndex;
       
   862     TUint bufIndex = iBufIndex;
       
   863     // Copy string length
       
   864     iPropList->IncreaseIndexL(pageIndex, bufIndex, KPropElemHeaderSize, ETrue);
       
   865     iPropList->MemoryCopyL(pageIndex, bufIndex, &len, sizeof(TUint8));
       
   866     // Copy string data
       
   867     iPropList->IncreaseIndexL(pageIndex, bufIndex, sizeof(TUint8), ETrue);
       
   868     iPropList->MemoryCopyL(pageIndex, bufIndex, aString.Ptr(), (len - 1) * sizeof(TUint16));
       
   869     // Append terminator
       
   870     iPropList->IncreaseIndexL(pageIndex, bufIndex, (len - 1) * sizeof(TUint16), ETrue);
       
   871     iPropList->MemoryCopyL(pageIndex, bufIndex, KMtpStringTerminator().Ptr(), 2);
       
   872         
       
   873     iArrayBuffered = EFalse;
       
   874     }
       
   875 
       
   876 EXPORT_C void CMTPTypeObjectPropListElement::SetArrayL(TInt aElementId, const CMTPTypeArray& aArray)
       
   877     {
       
   878     if(EValue != aElementId)
       
   879         {
       
   880         User::Leave(KErrArgument);
       
   881         }
       
   882     
       
   883     SetDataType(aArray.Type());
       
   884     TUint32 num = aArray.NumElements();
       
   885     
       
   886     
       
   887     TUint pageIndex = iPageIndex;
       
   888     TUint bufIndex = iBufIndex;
       
   889     
       
   890     // Set number of array elements
       
   891     iPropList->IncreaseIndexL(pageIndex, bufIndex, KPropElemHeaderSize, ETrue);
       
   892     iPropList->MemoryCopyL(pageIndex, bufIndex, &num, sizeof(TUint32));
       
   893 
       
   894     TPtrC8 srcPtr;
       
   895     aArray.FirstReadChunk(srcPtr);
       
   896     srcPtr.Set(srcPtr.Ptr() + sizeof(TUint32), srcPtr.Length() - sizeof(TUint32));
       
   897     
       
   898     iPropList->IncreaseIndexL(pageIndex, bufIndex, sizeof(TUint32), ETrue);
       
   899     TUint arrayWidth = iPropList->ArrayElemWidth(iDataType);
       
   900     iValueSize = sizeof(TUint32) + num * arrayWidth;
       
   901     iPropList->MemoryCopyL(pageIndex, bufIndex, srcPtr.Ptr(), num * arrayWidth);
       
   902     iArrayBuffered = EFalse;
       
   903     }
       
   904 
       
   905 EXPORT_C void CMTPTypeObjectPropListElement::SetArrayL(TInt aElementId, const TDesC& aString)
       
   906     {
       
   907     if(EValue != aElementId)
       
   908         {
       
   909         User::Leave(KErrArgument);
       
   910         }
       
   911     
       
   912     TUint32 len = aString.Length() + 1;
       
   913     
       
   914     SetDataType(EMTPTypeAUINT16);
       
   915 
       
   916     iValueSize = sizeof(TUint32) + len * sizeof(TUint16);
       
   917     
       
   918     TUint pageIndex = iPageIndex;
       
   919     TUint bufIndex = iBufIndex;
       
   920     // Copy string length
       
   921     iPropList->IncreaseIndexL(pageIndex, bufIndex, KPropElemHeaderSize, ETrue);
       
   922     iPropList->MemoryCopyL(pageIndex, bufIndex, &len, sizeof(TUint32));
       
   923     // Copy string data
       
   924     iPropList->IncreaseIndexL(pageIndex, bufIndex, sizeof(TUint32), ETrue);
       
   925     iPropList->MemoryCopyL(pageIndex, bufIndex, aString.Ptr(), (len - 1) * sizeof(TUint16));
       
   926     // Append terminator
       
   927     iPropList->IncreaseIndexL(pageIndex, bufIndex, (len - 1) * sizeof(TUint16), ETrue);
       
   928     iPropList->MemoryCopyL(pageIndex, bufIndex, KMtpStringTerminator().Ptr(), 2);
       
   929         
       
   930     iArrayBuffered = EFalse;
       
   931      }
       
   932 
       
   933 EXPORT_C TUint32 CMTPTypeObjectPropListElement::CMTPTypeObjectPropListElement::Size() const
       
   934     {
       
   935     return iValueSize + KPropElemHeaderSize;
       
   936     }
       
   937 
       
   938 void CMTPTypeObjectPropListElement::SetDataType(TUint16 aDataType)
       
   939     {
       
   940     iDataType = aDataType;
       
   941     TUint pageIndex = iPageIndex;
       
   942     TUint bufIndex = iBufIndex;    
       
   943     iPropList->IncreaseIndexL(pageIndex, bufIndex, sizeof(TUint32) + sizeof(TUint16), ETrue);
       
   944     iPropList->MemoryCopyL(pageIndex, bufIndex, &iDataType, sizeof(TUint16));
       
   945     }
       
   946 
       
   947 void CMTPTypeObjectPropListElement::GetValueL(TAny* aTrg, TUint aLength) const
       
   948     {
       
   949     TUint pageIndex = iPageIndex;
       
   950     TUint bufIndex = iBufIndex;
       
   951     iPropList->IncreaseIndexL(pageIndex, bufIndex, KPropElemHeaderSize, EFalse);
       
   952     iPropList->MemoryCopyL(aTrg, pageIndex, bufIndex, aLength);
       
   953     }
       
   954 
       
   955 void CMTPTypeObjectPropListElement::SetValueL(const TAny* aSrc, TUint aLength)
       
   956     {
       
   957     TUint pageIndex = iPageIndex;
       
   958     TUint bufIndex = iBufIndex;
       
   959     iPropList->IncreaseIndexL(pageIndex, bufIndex, KPropElemHeaderSize, ETrue);
       
   960     iPropList->MemoryCopyL(pageIndex, bufIndex, aSrc, aLength);
       
   961     iValueSize = aLength;
       
   962     }
       
   963 
       
   964