mtpfws/mtpfw/datatypes/src/cmtptypearray.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:11:40 +0200
changeset 0 d0791faffa3f
permissions -rw-r--r--
Revision: 201003 Kit: 201005

// Copyright (c) 2006-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:
//

/**
 @file
 @publishedPartner
*/

#include <mtp/cmtptypearray.h>
#include <mtp/mtpdatatypeconstants.h>
#include "mtpdatatypespanic.h"

// Array type constants.
const TUint KMTPNumElementsLen(sizeof(TUint32));
const TUint KMTPNumElementsOffset(0);
const TUint KMTPFirstElementOffset(KMTPNumElementsLen);
const TUint KMTPGranularity(8);

/**
MTP array data type factory method. This method is used to create an empty MTP
array.
@param aElementType The MTP type identifier of the elements contained in the 
array.
@param aElementSize The size (in bytes) of the elements contained in the array.
@return A pointer to an empty MTP array data type. Ownership IS transfered.
@leave One of the system wide error codes, if a processing failure occurs.
*/   
EXPORT_C CMTPTypeArray* CMTPTypeArray::NewL(TInt aElementType, TUint aElementSize)
    {
    return NewL(EMTPTypeArray, aElementType, aElementSize);
    }

/**
MTP array data type factory method. This method is used to create an empty MTP
array. A pointer to the MTP array data type is placed on the cleanup stack.
@param aElementType The MTP type identifier of the elements contained in the 
array.
@param aElementSize The size (in bytes) of the elements which contained in 
array.
@return A pointer to an empty MTP array data type. Ownership IS transfered.
@leave One of the system wide error codes, if a processing failure occurs.
*/  
EXPORT_C CMTPTypeArray* CMTPTypeArray::NewLC(TInt aElementType, TUint aElementSize)
    {
    return CMTPTypeArray::NewLC(EMTPTypeArray, aElementType, aElementSize);
    }

/**
MTP array data type factory method. This method is used to create an empty MTP
array of the specified MTP array type.
@param aArrayType The MTP type identifier to be assigned to the array.
@param aElementType The MTP type identifier of the elements contained in the 
array.
@param aElementSize The size (in bytes) of the elements contained in the array.
@return A pointer to an empty MTP array data type. Ownership IS transfered.
@leave One of the system wide error codes, if a processing failure occurs.
*/   
EXPORT_C CMTPTypeArray* CMTPTypeArray::NewL(TInt aArrayType, TInt aElementType, TUint aElementSize)
    {
    CMTPTypeArray* self = NewLC(aArrayType, aElementType, aElementSize);
    CleanupStack::Pop(self);
    return self;
    }

/**
MTP array data type factory method. This method is used to create an empty MTP
array of the specified MTP array type. A pointer to the MTP array data type is 
placed on the cleanup stack.
@param aArrayType The MTP type identifier to be assigned to the array.
@param aElementType The MTP type identifier of the elements contained in the 
array.
@param aElementSize The size (in bytes) of the elements which contained in 
array.
@return A pointer to an empty MTP array data type. Ownership IS transfered.
@leave One of the system wide error codes, if a processing failure occurs.
*/  
EXPORT_C CMTPTypeArray* CMTPTypeArray::NewLC(TInt aArrayType, TInt aElementType, TUint aElementSize)
    {
    CMTPTypeArray* self = new(ELeave) CMTPTypeArray(aArrayType, aElementType, aElementSize);
    CleanupStack::PushL(self);
    self->ConstructL(KMTPGranularity);
    return self;
    }
    
/**
MTP simple data type array factory method. This method is used to create
an empty MTP array of the specified MTP simple data type.
@param aArrayType The array data type indentifier datacode. This must be in 
the range EMTPTypeFirstSimpleArrayType ... EMTPTypeLastSimpleArrayType.
@return A pointer to an empty MTP array data type. Ownership IS transfered.
@leave KErrArgument, if aArrayType is not in the range 
EMTPTypeFirstSimpleArrayType ... EMTPTypeLastSimpleArrayType.
@leave One of the system wide error codes, if a processing failure occurs.
*/ 
EXPORT_C CMTPTypeArray* CMTPTypeArray::NewL(TInt aArrayType)
    {
    CMTPTypeArray* self = NewLC(aArrayType);
    CleanupStack::Pop(self);
    return self;   
    } 

/**
MTP simple data type array factory method. This method is used to create
an MTP array of the specified MTP simple data type with the specified element 
content.
@param aArrayType The array data type indentifier datacode. This must be in 
the range EMTPTypeFirstSimpleArrayType ... EMTPTypeLastSimpleArrayType.
@param aElements The initial set of element values.
@return A pointer to an empty MTP array data type. Ownership IS transfered.
@leave KErrArgument, if aArrayType is not in the range 
EMTPTypeFirstSimpleArrayType ... EMTPTypeLastSimpleArrayType.
@leave One of the system wide error codes, if a processing failure occurs.
*/ 
EXPORT_C CMTPTypeArray* CMTPTypeArray::NewL(TInt aArrayType, const RArray<TInt>& aElements)
    {
    CMTPTypeArray* self = NewLC(aArrayType, aElements);
    CleanupStack::Pop(self);
    return self; 
    }

/**
MTP simple data type array factory method. This method is used to create
an MTP array of the specified MTP simple data type with the specified element 
content.
@param aArrayType The array data type indentifier datacode. This must be in 
the range EMTPTypeFirstSimpleArrayType ... EMTPTypeLastSimpleArrayType.
@param aElements The initial set of element values.
@return A pointer to an empty MTP array data type. Ownership IS transfered.
@leave KErrArgument, if aArrayType is not in the range 
EMTPTypeFirstSimpleArrayType ... EMTPTypeLastSimpleArrayType.
@leave One of the system wide error codes, if a processing failure occurs.
*/ 
EXPORT_C CMTPTypeArray* CMTPTypeArray::NewL(TInt aArrayType, const RArray<TUint>& aElements)
    {
    CMTPTypeArray* self = NewLC(aArrayType, aElements);
    CleanupStack::Pop(self);
    return self; 
    }

/**
MTP AINT64 array factory method. This method is used to create an MTP AINT64 
array with the specified element content.
@param aElements The initial set of element values.
@return A pointer to an empty MTP array data type. Ownership IS transfered.
@leave KErrArgument, if aArrayType is not in the range 
EMTPTypeFirstSimpleArrayType ... EMTPTypeLastSimpleArrayType.
@leave One of the system wide error codes, if a processing failure occurs.
*/ 
EXPORT_C CMTPTypeArray* CMTPTypeArray::NewL(const RArray<TInt64>& aElements)
    {
    CMTPTypeArray* self = NewLC(aElements);
    CleanupStack::Pop(self); 
    return self; 
    }

/**
MTP AUINT64 array factory method. This method is used to create an MTP AINT64 
array with the specified element content.
@param aElements The initial set of element values.
@return A pointer to an empty MTP array data type. Ownership IS transfered.
@leave KErrArgument, if aArrayType is not in the range 
EMTPTypeFirstSimpleArrayType ... EMTPTypeLastSimpleArrayType.
@leave One of the system wide error codes, if a processing failure occurs.
*/ 
EXPORT_C CMTPTypeArray* CMTPTypeArray::NewL(const RArray<TUint64>& aElements)
    {
    CMTPTypeArray* self = NewLC(aElements);
    CleanupStack::Pop(self);
    return self; 
    }
    
/**
MTP simple data type array factory method. This method is used to create
an empty MTP array of the specified MTP simple data type. A pointer to the MTP 
array data type is placed on the cleanup stack.
@param aArrayType The array data type indentifier datacode. This must be in 
the range EMTPTypeFirstSimpleArrayType ... EMTPTypeLastSimpleArrayType.
@return A pointer to an empty MTP array data type. Ownership IS transfered.
@leave KErrArgument, if aArrayType is not in the range 
EMTPTypeFirstSimpleArrayType ... EMTPTypeLastSimpleArrayType.
@leave One of the system wide error codes, if a processing failure occurs.
*/ 
EXPORT_C CMTPTypeArray* CMTPTypeArray::NewLC(TInt aArrayType)
    {
    TInt    type(aArrayType);
    TUint   size(0);
    SimpleArrayTypeMetaDataL(aArrayType, type, size);
    CMTPTypeArray* self = new(ELeave) CMTPTypeArray(aArrayType, type, size);
    CleanupStack::PushL(self);
    self->ConstructL(KMTPGranularity);
    return self;   
    }

/**
MTP simple data type array factory method. This method is used to create
an MTP array of the specified MTP simple data type with the specified element 
content. A pointer to the MTP array data type is placed on the cleanup stack.
@param aArrayType The array data type indentifier datacode. This must be in 
the range EMTPTypeFirstSimpleArrayType ... EMTPTypeLastSimpleArrayType.
@param aElements The initial set of element values.
@return A pointer to an empty MTP array data type. Ownership IS transfered.
@leave KErrArgument, if aArrayType is not in the range 
EMTPTypeFirstSimpleArrayType ... EMTPTypeLastSimpleArrayType.
@leave One of the system wide error codes, if a processing failure occurs.
*/ 
EXPORT_C CMTPTypeArray* CMTPTypeArray::NewLC(TInt aArrayType, const RArray<TInt>& aElements)
    {
    TInt    type(aArrayType);
    TUint   size(0);
    SimpleArrayTypeMetaDataL(aArrayType, type, size);
    CMTPTypeArray* self = new(ELeave) CMTPTypeArray(aArrayType, type, size);
    CleanupStack::PushL(self);
    
    TUint count(aElements.Count());
    self->ConstructL(count);
    
    for (TUint i(0); (i < count); i++)
        {
        self->AppendIntL(aElements[i]);
        }
    
    return self; 
    }

/**
MTP simple data type array factory method. This method is used to create
an MTP array of the specified MTP simple data type with the specified element 
content. A pointer to the MTP array data type is placed on the cleanup stack.
@param aArrayType The array data type indentifier datacode. This must be in 
the range EMTPTypeFirstSimpleArrayType ... EMTPTypeLastSimpleArrayType.
@param aElements The initial set of element values.
@return A pointer to an empty MTP array data type. Ownership IS transfered.
@leave KErrArgument, if aArrayType is not in the range 
EMTPTypeFirstSimpleArrayType ... EMTPTypeLastSimpleArrayType.
@leave One of the system wide error codes, if a processing failure occurs.
*/ 
EXPORT_C CMTPTypeArray* CMTPTypeArray::NewLC(TInt aArrayType, const RArray<TUint>& aElements)
    {
    TInt    type(aArrayType);
    TUint   size(0);
    SimpleArrayTypeMetaDataL(aArrayType, type, size);
    CMTPTypeArray* self = new(ELeave) CMTPTypeArray(aArrayType, type, size);
    CleanupStack::PushL(self);
    
    TUint count(aElements.Count());
    self->ConstructL(count);
    
    for (TUint i(0); (i < count); i++)
        {
        self->AppendUintL(aElements[i]);
        }
    
    return self; 
    }

/**
MTP AINT64 array factory method. This method is used to create an MTP AINT64 
array with the specified element content. A pointer to the MTP array data type 
is placed on the cleanup stack.
@param aElements The initial set of element values.
@return A pointer to an empty MTP array data type. Ownership IS transfered.
@leave KErrArgument, if aArrayType is not in the range 
EMTPTypeFirstSimpleArrayType ... EMTPTypeLastSimpleArrayType.
@leave One of the system wide error codes, if a processing failure occurs.
*/ 
EXPORT_C CMTPTypeArray* CMTPTypeArray::NewLC(const RArray<TInt64>& aElements)
    {
    TInt    type(EMTPTypeINT64);
    TUint   size(0);
    SimpleArrayTypeMetaDataL(EMTPTypeAINT64, type, size);
    CMTPTypeArray* self = new(ELeave) CMTPTypeArray(EMTPTypeAINT64, type, size);
    CleanupStack::PushL(self);
    
    TUint count(aElements.Count());
    self->ConstructL(count);
    
    for (TUint i(0); (i < count); i++)
        {
        self->AppendInt64L(aElements[i]);
        }
    
    return self; 
    }

/**
MTP AUINT64 array factory method. This method is used to create an MTP AUINT64 
array with the specified element content. A pointer to the MTP array data type 
is placed on the cleanup stack.
@param aElements The initial set of element values.
@return A pointer to an empty MTP array data type. Ownership IS transfered.
@leave KErrArgument, if aArrayType is not in the range 
EMTPTypeFirstSimpleArrayType ... EMTPTypeLastSimpleArrayType.
@leave One of the system wide error codes, if a processing failure occurs.
*/ 
EXPORT_C CMTPTypeArray* CMTPTypeArray::NewLC(const RArray<TUint64>& aElements)
    {
    TInt    type(EMTPTypeUINT64);
    TUint   size(0);
    SimpleArrayTypeMetaDataL(EMTPTypeAUINT64, type, size);
    CMTPTypeArray* self = new(ELeave) CMTPTypeArray(EMTPTypeAUINT64, type, size);
    CleanupStack::PushL(self);
    
    TUint count(aElements.Count());
    self->ConstructL(count);
    
    for (TUint i(0); (i < count); i++)
        {
        self->AppendUint64L(aElements[i]);
        }
    
    return self; 
    }

/**
Destructor
*/
EXPORT_C CMTPTypeArray::~CMTPTypeArray()
    {
    iBuffer.Close();    
    }
    
/**
Provides the MTP identifier of the elements contained in the array.
@return The MTP identifier of the elements contained in the array.
*/ 
EXPORT_C TInt CMTPTypeArray::ElementType() const
    {
    return iElementType;    
    }
    
/**
Provides the number of elements contained in the MTP array.
@return The number of elements contained in the MTP array.
*/ 
EXPORT_C TUint32 CMTPTypeArray::NumElements() const
    {
    return *(reinterpret_cast<const TUint32*>(&iBuffer[KMTPNumElementsOffset]));
    }

/**
Appends the specified element to the end of the MTP array.
@param aElement The element to be appended to the MTP array.
@leave One of the system wide error codes, if a processing failure occurs.
@panic MTPDataTypes 3, if aElement does not match the MTP type of the elements
contained in the array.
*/
EXPORT_C void CMTPTypeArray::AppendL(const MMTPType& aElement)
    {    
    __ASSERT_ALWAYS((aElement.Type() == iElementType), Panic(EMTPTypeIdMismatch));
    const TUint index(NumElements());
    TUint32 numElements(index + 1);
    
    if (iBuffer.MaxLength() < BufferSize(numElements))
        {
        ReAllocBufferL(numElements);
        }
        
    TBool complete(EFalse);
    TUint offset(Offset(index));
    TPtrC8 src;
    const TUint startOffset(offset);
    
    TInt err(aElement.FirstReadChunk(src));
    while (((err == KMTPChunkSequenceCompletion) || (err == KErrNone)) && (!complete))
        {
        __ASSERT_ALWAYS(((offset - startOffset) <= iElementSize), Panic(EMTPTypeSizeMismatch));
        memcpy(&iBuffer[offset], src.Ptr(), src.Length());
        offset += src.Length();
        
        complete = (err == KMTPChunkSequenceCompletion);
        if (!complete)
            {
            err = aElement.NextReadChunk(src);                
            } 
        }
        
    if (err != KMTPChunkSequenceCompletion)
        {
        User::Leave(err);            
        }
        
    SetNumElements(numElements);
    }

/**
Appends the specified elements to the end of the MTP array. The array 
element type MUST be one of the MTP INT8, INT16, or INT32 types.
@param aElements The elements to be appended to the MTP array.
@leave One of the system wide error codes, if a processing failure occurs.
@panic MTPDataTypes 3, if aElement does not match the MTP array's element type.
*/   
EXPORT_C void CMTPTypeArray::AppendL(const RArray<TInt>& aElements)
    {
    TUint count(aElements.Count());
    for (TUint i(0); (i < count); i++)
        {
        AppendIntL(aElements[i]);
        }
    }

/**
Appends the specified elements to the end of the MTP array. The array 
element type MUST be one of the MTP UINT8, UINT16, or UINT32 types.
@param aElements The elements to be appended to the MTP array.
@leave One of the system wide error codes, if a processing failure occurs.
@panic MTPDataTypes 3, if aElement does not match the MTP array's element type.
*/    
EXPORT_C void CMTPTypeArray::AppendL(const RArray<TUint>& aElements)
    {
    TUint count(aElements.Count());
    for (TUint i(0); (i < count); i++)
        {
        AppendUintL(aElements[i]);
        }
    }

/**
Appends the specified elements to the end of the MTP array. The array 
element type MUST be of the MTP INT64 type.
@param aElements The elements to be appended to the MTP array.
@leave One of the system wide error codes, if a processing failure occurs.
@panic MTPDataTypes 3, if aElement does not match the MTP array's element type.
*/   
EXPORT_C void CMTPTypeArray::AppendL(const RArray<TInt64>& aElements)
    {
    TUint count(aElements.Count());
    for (TUint i(0); (i < count); i++)
        {
        AppendInt64L(aElements[i]);
        }
    }

/**
Appends the specified elements to the end of the MTP array. The array 
element type MUST be of the MTP UINT64 type.
@param aElements The elements to be appended to the MTP array.
@leave One of the system wide error codes, if a processing failure occurs.
@panic MTPDataTypes 3, if aElement does not match the MTP array's element type.
*/
EXPORT_C void CMTPTypeArray::AppendL(const RArray<TUint64>& aElements)
    {
    TUint count(aElements.Count());
    for (TUint i(0); (i < count); i++)
        {
        AppendUint64L(aElements[i]);
        }
    }

/**
Appends the specified element to the end of the MTP array. The array 
element type MUST be one of the MTP INT8, INT16, or INT32 types.
@param aElement The element to be appended to the MTP array.
@leave One of the system wide error codes, if a processing failure occurs.
@panic MTPDataTypes 3, if aElement does not match the MTP array's element type.
*/
EXPORT_C void CMTPTypeArray::AppendIntL(TInt aElement)
    {
    __ASSERT_ALWAYS(((iElementType == EMTPTypeINT8) || (iElementType == EMTPTypeINT16) || (iElementType == EMTPTypeINT32)), Panic(EMTPTypeIdMismatch));
    // Relies on Symbian OS little-endianess.
    AppendL(&aElement);
    }

/**
Appends the specified element to the end of the MTP array. The array 
element type MUST be one of the MTP UINT8, UINT16, or UINT32 types.
@param aElement The element to be appended to the MTP array.
@leave One of the system wide error codes, if a processing failure occurs.
@panic MTPDataTypes 3, if aElement does not match the MTP array's element type.
*/
EXPORT_C void CMTPTypeArray::AppendUintL(TUint aElement)
    {  
    __ASSERT_ALWAYS(((iElementType == EMTPTypeUINT8) || (iElementType == EMTPTypeUINT16) || (iElementType == EMTPTypeUINT32)), Panic(EMTPTypeIdMismatch));
    // Relies on Symbian OS little-endianess.
    AppendL(&aElement);  
    }

/**
Appends the specified element to the end of the MTP array. The array 
element type MUST be of the MTP INT64 type.
@param aElement The element to be appended to the MTP array.
@leave One of the system wide error codes, if a processing failure occurs.
@panic MTPDataTypes 3, if aElement does not match the MTP array's element type.
*/
EXPORT_C void CMTPTypeArray::AppendInt64L(TInt64 aElement)
    {    
    __ASSERT_ALWAYS((iElementType == EMTPTypeINT64) ,Panic(EMTPTypeIdMismatch));
    AppendL(&aElement);
    }

/**
Appends the specified element to the end of the MTP array. The array 
element type MUST be of the MTP UINT64 type.
@param aElement The element to be appended to the MTP array.
@leave One of the system wide error codes, if a processing failure occurs.
@panic MTPDataTypes 3, if aElement does not match the MTP array's element type.
*/
EXPORT_C void CMTPTypeArray::AppendUint64L(TUint64 aElement)
    {    
    __ASSERT_ALWAYS((iElementType == EMTPTypeUINT64) ,Panic(EMTPTypeIdMismatch));
    AppendL(&aElement);
    }

/**
Provides a copy of the MTP element at the specified array index.
@param aIndex The index in the MTP array of the required element.
@param aElement On completion, a copy of the required element.
@leave One of the system wide error codes, if a processing failure occurs.
@panic MTPDataTypes 2, if aIndex is greater than or equal to the number of 
objects currently contained in the array.
@panic MTPDataTypes 3, if aElement does not match the MTP type of the elements
contained in the array.
@panic MTPDataTypes 4, if aElement's size does not match that of the elements
contained in the array.
*/
EXPORT_C void CMTPTypeArray::ElementL(TUint aIndex, MMTPType& aElement) const
    {
    __ASSERT_ALWAYS((aIndex < NumElements()), Panic(EMTPTypeBoundsError));
    __ASSERT_ALWAYS((aElement.Type() == iElementType), Panic(EMTPTypeIdMismatch));
    __ASSERT_ALWAYS((aElement.Size() == iElementSize), Panic(EMTPTypeSizeMismatch));
    
    TBool commit(aElement.CommitRequired());
    TBool complete(EFalse);
    TPtr8 dest(NULL, 0);
    TInt err(aElement.FirstWriteChunk(dest));
    TUint offset(Offset(aIndex));
    
    while (((err == KMTPChunkSequenceCompletion) || (err == KErrNone)) && (!complete))
        {
        dest.Copy(&iBuffer[offset], dest.MaxLength());
        offset += dest.MaxLength();
        
        if (commit)
            {
            aElement.CommitChunkL(dest);
            }
        
        complete = (err == KMTPChunkSequenceCompletion);
        if (!complete)
            {
            err = aElement.NextWriteChunk(dest);
            }
        }
        
    if (err != KMTPChunkSequenceCompletion)
        {
        User::Leave(err);            
        }
    }

/**
Provides a copy of the MTP element at the specified array index. The array 
element type MUST be one of the MTP INT8, INT16, or INT32 types.
@param aIndex The index in the MTP array of the required element.
@panic MTPDataTypes 2, if aIndex is greater than or equal to the number of 
objects currently contained in the array.
@panic MTPDataTypes 3, if aElement does not match the MTP array's element type.
@return aElement On completion, a copy of the required element.
*/
EXPORT_C TInt CMTPTypeArray::ElementInt(TUint aIndex) const
    {
    __ASSERT_ALWAYS(((iElementType == EMTPTypeINT8) || (iElementType == EMTPTypeINT16) || (iElementType == EMTPTypeINT32)), Panic(EMTPTypeIdMismatch));
    // Relies on Symbian OS little-endianess.
    TInt ret(0);
    Element(aIndex, &ret);
    return ret;
    }

/**
Provides a copy of the MTP element at the specified array index. The array 
element type MUST be one of the MTP UINT8, UINT16, or UINT32 types.
@param aIndex The index in the MTP array of the required element.
@panic MTPDataTypes 2, if aIndex is greater than or equal to the number of 
objects currently contained in the array.
@panic MTPDataTypes 3, if aElement does not match the MTP array's element type.
@return aElement On completion, a copy of the required element.
*/
EXPORT_C TUint CMTPTypeArray::ElementUint(TUint aIndex) const
    {
    __ASSERT_ALWAYS(((iElementType == EMTPTypeUINT8) || (iElementType == EMTPTypeUINT16) || (iElementType == EMTPTypeUINT32)), Panic(EMTPTypeIdMismatch));
    // Relies on Symbian OS little-endianess.
    TUint ret(0);
    Element(aIndex, &ret);
    return ret;
    }

/**
Provides a copy of the MTP element at the specified array index. The array 
element type MUST be of the MTP INT64 type.
@param aIndex The index in the MTP array of the required element.
@panic MTPDataTypes 2, if aIndex is greater than or equal to the number of 
objects currently contained in the array.
@panic MTPDataTypes 3, if aElement does not match the MTP array's element type.
@return aElement On completion, a copy of the required element.
*/
EXPORT_C TInt64 CMTPTypeArray::ElementInt64(TUint aIndex) const
    {
    __ASSERT_ALWAYS((iElementType == EMTPTypeINT64) ,Panic(EMTPTypeIdMismatch));
    TInt64 ret(0);
    Element(aIndex, &ret);
    return ret;
    }

/**
Provides a copy of the MTP element at the specified array index. The array 
element type MUST be of the MTP UINT64 type.
@param aIndex The index in the MTP array of the required element.
@panic MTPDataTypes 2, if aIndex is greater than or equal to the number of 
objects currently contained in the array.
@panic MTPDataTypes 3, if aElement does not match the MTP array's element type.
@return aElement On completion, a copy of the required element.
*/
EXPORT_C TUint64 CMTPTypeArray::ElementUint64(TUint aIndex) const
    {
    __ASSERT_ALWAYS((iElementType == EMTPTypeUINT64) ,Panic(EMTPTypeIdMismatch));
    TUint64 ret(0);
    Element(aIndex, &ret);
    return ret;
    }

/**
Provides a copy of the MTP array's element content. The array element type MUST
be one of the MTP INT8, INT16, or INT32 types.
@param aElements On completion, a copy of the MTP array's element content.
@panic MTPDataTypes 3, if aElement does not match the MTP array's element type.
*/
EXPORT_C void CMTPTypeArray::Array(RArray<TInt>& aElements) const
    {
    // Clear the array    
    aElements.Close();

    TUint numElements(NumElements());
    for (TUint i(0); (i < numElements); i++)
        {
        aElements.Append(ElementInt(i));
        }
    }

/**
Provides a copy of the MTP array's element content. The array element type MUST
be one of the MTP UINT8, UINT16, or UINT32 types.
@param aElements On completion, a copy of the MTP array's element content.
@panic MTPDataTypes 3, if aElement does not match the MTP array's element type.
*/
EXPORT_C void CMTPTypeArray::Array(RArray<TUint>& aElements) const
    {
    // Clear the array    
    aElements.Close();

    TUint numElements(NumElements());
    for (TUint i(0); (i < numElements); i++)
        {
        aElements.Append(ElementUint(i));
        }
    }

/**
Provides a copy of the MTP array's element content. The array element type MUST
be of the MTP INT64 type.
@param aElements On completion, a copy of the MTP array's element content.
@panic MTPDataTypes 3, if aElement does not match the MTP array's element type.
*/
EXPORT_C void CMTPTypeArray::Array(RArray<TInt64>& aElements) const
    {
    // Clear the array    
    aElements.Close();

    TUint numElements(NumElements());
    for (TUint i(0); (i < numElements); i++)
        {
        aElements.Append(ElementInt64(i));
        }
    }

/**
Provides a copy of the MTP array's element content. The array element type MUST
be of the MTP UINT64 type.
@param aElements On completion, a copy of the MTP array's element content.
@panic MTPDataTypes 3, if aElement does not match the MTP array's element type.
*/
EXPORT_C void CMTPTypeArray::Array(RArray<TUint64>& aElements) const
    {
    // Clear the array    
    aElements.Close();

    TUint numElements(NumElements());
    for (TUint i(0); (i < numElements); i++)
        {
        aElements.Append(ElementUint64(i));
        }
    }

EXPORT_C void CMTPTypeArray::ToDes( TDes8& aRetDes ) const
    {  
    TInt retSize = aRetDes.MaxSize();
    if( 0 == retSize )
       {
       return ;
       }
    
    TInt length = NumElements() * iElementSize ;
    if(retSize < length)
        length = retSize;
    
    TPtrC8 ptrL = iBuffer.Left( length + KMTPNumElementsLen );
    TPtrC8 ptr = ptrL.Right(length);
    aRetDes.Copy(ptr);
    }


EXPORT_C void CMTPTypeArray::SetByDesL( const TDesC8& aDesc ) 
    {
    TUint32 num = (aDesc.Length() / iElementSize);
    SetNumElements( num );
    if ( num > 0 )
    	{
    	ReAllocBufferL( num );
    	memcpy(&iBuffer[KMTPFirstElementOffset], aDesc.Ptr(), aDesc.Length());
    	}
    }

EXPORT_C TInt CMTPTypeArray::FirstReadChunk(TPtrC8& aChunk) const
    {
    aChunk.Set(&iBuffer[KMTPNumElementsOffset], Size());
    return KMTPChunkSequenceCompletion;
    }

EXPORT_C TInt CMTPTypeArray::NextReadChunk(TPtrC8& aChunk) const
    {
    aChunk.Set(NULL, 0);
    return KErrNotReady;
    }

EXPORT_C TInt CMTPTypeArray::FirstWriteChunk(TPtr8& aChunk)
    {    
    TInt ret(KErrNone);
    aChunk.Set(&iBuffer[KMTPNumElementsOffset], 0, KMTPNumElementsLen);
    iWriteSequenceState = ENumElements;
    return ret;
    }

EXPORT_C TInt CMTPTypeArray::NextWriteChunk(TPtr8& aChunk)
    {
    TInt ret(KMTPChunkSequenceCompletion);
    
    if (iWriteSequenceState != ENumElements)
        {
        ret = KErrNotReady;
        }
    else
        {
        const TUint capacity(iBuffer.MaxLength() - KMTPNumElementsLen);
        if (capacity > 0)
            {
            aChunk.Set(&iBuffer[KMTPFirstElementOffset], 0, capacity);
            }
        else
            {
            aChunk.Set(NULL, 0, 0);
            }
            
        iWriteSequenceState = EElements;
        }
        
    return ret;
    }

EXPORT_C TUint64 CMTPTypeArray::Size() const
    {
    return (KMTPNumElementsLen + (NumElements() * iElementSize));
    }

EXPORT_C TUint CMTPTypeArray::Type() const
    {
    return iArrayType;
    }

EXPORT_C TBool CMTPTypeArray::CommitRequired() const
    {
    return ETrue;
    }

EXPORT_C MMTPType* CMTPTypeArray::CommitChunkL(TPtr8& aChunk)
    {
    switch (iWriteSequenceState)
        {
    case ENumElements:
        /* 
        The first chunk specifies the NumElements field, and is used to re-size 
        the array buffer.
        */
        ReAllocBufferL(NumElements());
        break;
        
    case EElements:
        // Check that the correct number of array elements has been received.
        {            
        TUint count(aChunk.Length() / iElementSize);
        if (count != NumElements())
            {
            SetInvalidL();
            }
        iWriteSequenceState = EIdle;
        }
        break;
        
    case EIdle:
    default:
        User::Leave(KErrNotReady);
        break;
        }
    return NULL;
    }
    
EXPORT_C TInt CMTPTypeArray::Validate() const
    {
    return iValidationState;
    }
    
CMTPTypeArray::CMTPTypeArray(TInt aArrayType, TInt aElementType, TUint aElementSize) :
    iArrayType(aArrayType),
    iElementSize(aElementSize),
    iElementType(aElementType)
    {
        
    }
    
void CMTPTypeArray::ConstructL(TUint32 aNumElements)
    {
    ReAllocBufferL(aNumElements);
    SetNumElements(0);
    }

void CMTPTypeArray::ConstructL(const RPointerArray<MMTPType>& aElements)
    {
    TUint count(aElements.Count());
    ConstructL(count);
    
    for (TUint i(0); (i < count); i++)
        {
        AppendL(aElements[i]);
        }
    }
    
void CMTPTypeArray::AppendL(const TAny* aElement)
    {    
    const TUint index(NumElements());
    TUint32 numElements(index + 1);
    
    if (iBuffer.MaxLength() < BufferSize(numElements))
        {
        ReAllocBufferL(numElements);
        }

    memcpy(&iBuffer[Offset(index)], aElement, iElementSize);
    SetNumElements(numElements);
    }
    
void CMTPTypeArray::Element(TUint aIndex, TAny* aElement) const
    {
    __ASSERT_ALWAYS((aIndex < NumElements()), Panic(EMTPTypeBoundsError));
    memcpy(aElement, &iBuffer[Offset(aIndex)], iElementSize);
    }
    
void CMTPTypeArray::ReAllocBufferL(TUint32 aNumElements)
    {
    TInt currentSize(iBuffer.MaxLength());
    TUint64 newSize(BufferSize(aNumElements));
    
    if (newSize != currentSize)
        {
        if (newSize > KMaxTInt)
            {
            SetInvalidL();
            }
        else
            {
            if (newSize < currentSize)
                {
                // Buffer is shrinking.
                iBuffer.Close();   
                }
            iBuffer.ReAllocL(newSize);
            iBuffer.SetMax();
            SetNumElements(aNumElements);   
            }
        }
    }

void CMTPTypeArray::SetNumElements(TUint32 aNumElements)
    {
    memcpy(&iBuffer[KMTPNumElementsOffset], &aNumElements, KMTPNumElementsLen);
    }

TUint64 CMTPTypeArray::BufferSize(TUint32 aNumElements) const
    {
    return ((iElementSize * aNumElements) + KMTPNumElementsLen);
    }
    
TUint CMTPTypeArray::Offset(TUint aIndex) const
    {
    return (KMTPFirstElementOffset + (aIndex * iElementSize));
    }
    
void CMTPTypeArray::SetInvalidL()
    {
    iValidationState = KMTPDataTypeInvalid;
    User::Leave(iValidationState);
    }
    
void CMTPTypeArray::SimpleArrayTypeMetaDataL(TInt aArrayType, TInt& aElementType, TUint& aElementSize)
    {            
    switch (aArrayType)
        {
    case EMTPTypeAINT8:
        aElementType    = EMTPTypeINT8;
        aElementSize    = KMTPTypeINT8Size;
        break; 
        
    case EMTPTypeAUINT8:
        aElementType    = EMTPTypeUINT8;
        aElementSize    = KMTPTypeUINT8Size;
        break; 
        
    case EMTPTypeAINT16:
        aElementType    = EMTPTypeINT16;
        aElementSize    = KMTPTypeINT16Size;
        break; 
        
    case EMTPTypeAUINT16:
        aElementType    = EMTPTypeUINT16;
        aElementSize    = KMTPTypeUINT16Size;
        break; 
        
    case EMTPTypeAINT32:
        aElementType    = EMTPTypeINT32;
        aElementSize    = KMTPTypeINT32Size;
        break; 
        
    case EMTPTypeAUINT32:
        aElementType    = EMTPTypeUINT32;
        aElementSize    = KMTPTypeUINT32Size;
        break; 
        
    case EMTPTypeAINT64:
        aElementType    = EMTPTypeINT64;
        aElementSize    = KMTPTypeINT64Size;
        break; 
        
    case EMTPTypeAUINT64:
        aElementType    = EMTPTypeUINT64;
        aElementSize    = KMTPTypeUINT64Size;
        break; 
        
    case EMTPTypeAINT128:
        aElementType    = EMTPTypeINT128;
        aElementSize    = KMTPTypeINT128Size;
        break; 
        
    case EMTPTypeAUINT128:
        aElementType    = EMTPTypeUINT128;
        aElementSize    = KMTPTypeUINT128Size;
        break; 
        
    default:
        User::Leave(KErrArgument);
        } 
    }