mtpfws/mtpfw/datatypes/src/cmtptypelist.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/cmtptypelist.h>

#include "mtpdatatypespanic.h"
#include <mtp/tmtptypedatapair.h>

const TUint CMTPTypeList::KChunkNumberofElements(0);


const TUint CMTPTypeList::KChunckNumberOfHeader(1);

EXPORT_C CMTPTypeList* CMTPTypeList::NewL(TMTPTypeIds aListType, TMTPTypeIds aElementType)
    {
    CMTPTypeList* self = CMTPTypeList::NewLC(aListType, aElementType); 
    CleanupStack::Pop(self);
    return self;  
    }

EXPORT_C CMTPTypeList* CMTPTypeList::NewLC(TMTPTypeIds aListType, TMTPTypeIds aElementType)
    {
    CMTPTypeList* self = new(ELeave) CMTPTypeList(aListType, aElementType);
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
    }

EXPORT_C  CMTPTypeList::~CMTPTypeList()
    {
    ResetAndDestroy();
    }

CMTPTypeList::CMTPTypeList(TInt aListType, TInt aElementType):
    CMTPTypeCompoundBase(KJustInTimeConstruction, KVariableChunkCount),
    iListType(aListType),
    iElementType(aElementType),
    iChunkNumberOfElements(KChunkNumberofElements)
    {
    const CMTPTypeCompoundBase::TElementInfo KDefaultInfo = {0, EMTPTypeUndefined, {EMTPTypeUndefined, KMTPNotApplicable,  KMTPNotApplicable}};
    iInfoNumberOfElements       = KDefaultInfo; 
    iInfoNumberOfElements.iType = EMTPTypeUINT32;
    iInfoElement                = KDefaultInfo; 
    iInfoElement.iType          = aElementType;
    }

void CMTPTypeList::InitListL()
    {
    ChunkAppendL(iChunkNumberOfElements);
    }

void CMTPTypeList::ConstructL()
    {
    InitListL();
    }


EXPORT_C void CMTPTypeList::AppendL(const MMTPType* aElement)
    {
    if (aElement == NULL)
        {
        User::Leave(KMTPDataTypeInvalid);
        }
             
    // Append the element.
    AppendElementChunkL(aElement);
    
    // Increment NumberOfElements.
    const TUint index(iChunkNumberOfElements.Value());
    iChunkNumberOfElements.Set(index + 1);
    }

EXPORT_C void CMTPTypeList::Remove(const TInt aIndex)
    {
        
    MMTPType* tmp = iChunksElement[aIndex];
    iChunksElement.Remove(aIndex);
    ChunkRemove(aIndex + 1);
    RMTPType::Destroy(iElementType,tmp );
    
    const TUint index(iChunkNumberOfElements.Value());
    iChunkNumberOfElements.Set(index - 1);
    }

EXPORT_C TInt CMTPTypeList::ElementType() const
    {
    return iElementType;
    }

EXPORT_C TUint32 CMTPTypeList::NumberOfElements() const
    {
    return iChunkNumberOfElements.Value();
    }

EXPORT_C MMTPType& CMTPTypeList::ElementL(const TInt aIndex) const
	{
	__ASSERT_ALWAYS(( aIndex < NumberOfElements() ), User::Leave(EMTPTypeBoundsError));

	return *iChunksElement[aIndex];
	}

EXPORT_C TInt CMTPTypeList::FirstWriteChunk(TPtr8& aChunk)
    {
    ResetAndDestroy();
    
    // Setup the write chunk pointer.
    TInt err(UpdateWriteSequenceErr(CMTPTypeCompoundBase::FirstWriteChunk(aChunk)));
    switch (err)
        {
    case KMTPChunkSequenceCompletion:
        err = KErrNone;
        // Don't break, fall through to set the write sequence state.
        
    case KErrNone:
        // Set the write sequence state.
        iWriteSequenceState = EElementChunks;
        break;
        
    default:
        break;
        }
        
    return  err;
    }

EXPORT_C TInt CMTPTypeList::NextWriteChunk(TPtr8& aChunk)
    {
    TInt err(KMTPChunkSequenceCompletion);
    if (iWriteSequenceState != EIdle)
        {
        err = UpdateWriteSequenceErr(CMTPTypeCompoundBase::NextWriteChunk(aChunk));
        if ((iWriteSequenceErr == KMTPChunkSequenceCompletion) && (iWriteSequenceState != EIdle))
            {
            err = KErrNone;
            }   
        }    
    return err;
    }

EXPORT_C TInt CMTPTypeList::NextWriteChunk(TPtr8& aChunk, TUint /*aDataLength*/)
	{
	return NextWriteChunk(aChunk);
	}

EXPORT_C TUint CMTPTypeList::Type() const
    {
    return iListType;
    }

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

EXPORT_C MMTPType* CMTPTypeList::CommitChunkL(TPtr8& aChunk)
    {
    if (iWriteSequenceErr == KMTPChunkSequenceCompletion)
        {
        switch (iWriteSequenceState)
            {
        case EElementChunks:
            if ((iChunkNumberOfElements.Value()) && 
                (iChunksElement.Count() < iChunkNumberOfElements.Value()))
                {
                MMTPType* element = RMTPType::AllocL(iElementType);
                CleanupStack::PushL(element);
                AppendElementChunkL(element);
                CleanupStack::Pop(element); 
                }
            else
                {
                iWriteSequenceState = EIdle;
                }
            break;
            
        case EIdle:
            // Completing the last chunk in the write sequence.
            break;
            
        default:
            Panic(EMTPTypeBadStorage);
            break;
            }
        }
        
    if (CMTPTypeCompoundBase::CommitRequired())
        {
        CMTPTypeCompoundBase::CommitChunkL(aChunk);
        }     
    return NULL;
    }


const CMTPTypeCompoundBase::TElementInfo& CMTPTypeList::ElementInfo(TInt aElementId) const
    {
    if (aElementId == KChunkNumberofElements)
        {
        return iInfoNumberOfElements;
        }
    else
        {
        __ASSERT_ALWAYS(((aElementId - KChunckNumberOfHeader) < iChunkNumberOfElements.Value()), Panic(EMTPTypeBoundsError));
        iInfoElement.iChunkId = aElementId;
        return iInfoElement; 
        }
    }


TInt CMTPTypeList::ValidateChunkCount() const
    {
    if (NumberOfElements() != (ChunkCount() - 1))
        {
        return KMTPDataTypeInvalid;
        }
    
    return KErrNone;
    }

TInt CMTPTypeList::UpdateWriteSequenceErr(TInt aErr)
    {
    iWriteSequenceErr = aErr;
    return iWriteSequenceErr;        
    }


void CMTPTypeList::AppendElementChunkL(const MMTPType* aElement)
    {
    iChunksElement.AppendL(aElement);
    ChunkAppendL(*aElement);
    }

EXPORT_C void CMTPTypeList::ResetAndDestroy()
    {
    const TUint num = iChunksElement.Count();
    for(TInt i = num -1  ; i  >= 0 ; i-- )
        {
        Remove(i);
        }
    
    iChunksElement.Close();
    }