mtpfws/mtpfw/datatypes/src/cmtptypeinterdependentpropdesc.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/cmtptypeobjectpropdesc.h>
#include <mtp/cmtptypeinterdependentpropdesc.h>
#include <mtp/mtpdatatypeconstants.h>

#include "mtpdatatypespanic.h"

// Dataset constants    
const TUint CMTPTypeInterdependentPropDesc::KNumberOfInterdependenciesChunk(0);
const TUint CMTPTypeInterdependentPropDesc::KInterdependentPropertiesChunks(1);

const TUint CMTPTypeInterdependentProperties::KNumberOfPropDescsChunk(0);
const TUint CMTPTypeInterdependentProperties::KObjectPropDescChunks(1);

/**
MTP InterdependentPropDesc dataset factory method. This method is used to create an 
empty MTP InterdependentPropDesc dataset. 
@return A pointer to the MTP InterdependentPropDesc dataset type. Ownership IS 
transfered.
@leave One of the system wide error codes, if unsuccessful.
*/ 
EXPORT_C CMTPTypeInterdependentPropDesc* CMTPTypeInterdependentPropDesc::NewL()
    {
    CMTPTypeInterdependentPropDesc* self = CMTPTypeInterdependentPropDesc::NewLC(); 
    CleanupStack::Pop(self); 
    return self;  
    }

/**
MTP InterdependentPropDesc dataset factory method. This method is used to create an 
empty MTP InterdependentPropDesc dataset. A pointer to the data type is placed on the
cleanup stack.
@return A pointer to the MTP InterdependentPropDesc dataset type. Ownership IS 
transfered.
@leave One of the system wide error codes, if unsuccessful.
*/ 
EXPORT_C CMTPTypeInterdependentPropDesc* CMTPTypeInterdependentPropDesc::NewLC()
    {
    CMTPTypeInterdependentPropDesc* self = new(ELeave) CMTPTypeInterdependentPropDesc();
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
    }

/**
Destructor.
*/
EXPORT_C CMTPTypeInterdependentPropDesc::~CMTPTypeInterdependentPropDesc()
    {
    iChunksInterdependentProperties.ResetAndDestroy();
    }

/**
Appends the specified InterdependentPropDesc value quadruple to the InterdependentPropDesc. 
Ownership of the specified InterdependentPropDesc value quadruple is passed to the 
InterdependentPropDesc.
@param aElement The InterdependentPropDesc value quadruple to append. Ownership IS
transferred.
@leave One of the system wide error codes, if unsuccessful.
*/
EXPORT_C void CMTPTypeInterdependentPropDesc::AppendL(CMTPTypeInterdependentProperties* aInterdependentProperties)
    {
    // Increment NumberOfElements.
    const TUint index(iChunkNumberOfInterdependencies.Value());
    iChunkNumberOfInterdependencies.Set(index + 1);
    
    // Append the element.
    AppendElementChunkL(aInterdependentProperties);
    }

/**
Provides the NumberOfElements element value.
*/
EXPORT_C TUint32 CMTPTypeInterdependentPropDesc::NumberOfInterdependencies() const
    {
    return iChunkNumberOfInterdependencies.Value();
    }

/**
Provides a non-const reference to the InterdependentPropDesc value quadruple element at
the specified index.
@param aIndex The index of the required element.
@param aValue On successful completion, a non-const reference to the requested
element.
@leave One of the system wide error codes, if unsuccessful.
*/
EXPORT_C CMTPTypeInterdependentProperties& CMTPTypeInterdependentPropDesc::InterdependentProperties(TUint aIndex) const
    {
    return *iChunksInterdependentProperties[aIndex];
    }

EXPORT_C TInt CMTPTypeInterdependentPropDesc::FirstWriteChunk(TPtr8& aChunk)
    {   
    /* 
    Reset the type in preparation for the data stream, by deleting all
    except the first chunk.
    */
    for (TUint i(ChunkCount() - 1); (i >= (KNumberOfInterdependenciesChunk + 1)); i--)
        {
        ChunkRemove(i);
        }
    iChunksInterdependentProperties.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 = EInProgress;
        break;
        
    default:
        break;
        }
        
    return  err;
    }
    
EXPORT_C TInt CMTPTypeInterdependentPropDesc::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 TUint CMTPTypeInterdependentPropDesc::Type() const
    {
    return EMTPTypeInterdependentPropDescDataset;
    }

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

EXPORT_C MMTPType* CMTPTypeInterdependentPropDesc::CommitChunkL(TPtr8& aChunk)
    {
    if (iWriteSequenceErr == KMTPChunkSequenceCompletion)
        {
        switch (iWriteSequenceState)
            {
        case EInProgress:
            if ((iChunkNumberOfInterdependencies.Value()) && 
                (iChunksInterdependentProperties.Count() < iChunkNumberOfInterdependencies.Value()))
                {
                // Allocate the next element chunk.
                CMTPTypeInterdependentProperties* element = CMTPTypeInterdependentProperties::NewLC();
                AppendElementChunkL(element);
                CleanupStack::Pop(element);
                }
            else
                {
                iWriteSequenceState = EIdle;
                }
            break;
            
        case EIdle:
            // Completing the last element in the write sequence.
            break;
            
        default:
            Panic(EMTPTypeBadStorage);
            break;
            }
        }
        
    if (CMTPTypeCompoundBase::CommitRequired())
        {
        CMTPTypeCompoundBase::CommitChunkL(aChunk);
        }     
    return NULL;
    }
 
const CMTPTypeCompoundBase::TElementInfo& CMTPTypeInterdependentPropDesc::ElementInfo(TInt aElementId) const
    {
    if (aElementId == KNumberOfInterdependenciesChunk)
        {
        return iInfoNumberOfInterdependencies;
        }
    else
        {
        __ASSERT_ALWAYS(((aElementId - KInterdependentPropertiesChunks) < iChunkNumberOfInterdependencies.Value()), Panic(EMTPTypeBoundsError));
        iInfoInterdependentProperties.iChunkId = aElementId;
        return iInfoInterdependentProperties; 
        }
    }

TInt CMTPTypeInterdependentPropDesc::ValidateChunkCount() const
    {
    TInt ret(KErrNone);
    if (NumberOfInterdependencies() != (ChunkCount() - 1))
        {
        ret = KMTPDataTypeInvalid;
        }
    return ret;
    }

CMTPTypeInterdependentPropDesc::CMTPTypeInterdependentPropDesc() :
    CMTPTypeCompoundBase(KJustInTimeConstruction, KVariableChunkCount)
    {
    const CMTPTypeCompoundBase::TElementInfo KDefaultInfo = {0, EMTPTypeUndefined, {EMTPTypeUndefined, KMTPNotApplicable,  KMTPNotApplicable}};
    iInfoNumberOfInterdependencies          = KDefaultInfo; 
    iInfoNumberOfInterdependencies.iType    = EMTPTypeUINT32;
    iInfoInterdependentProperties           = KDefaultInfo; 
    iInfoInterdependentProperties.iType     = EMTPTypeInterdependentPropDescElementDataset;
    }

void CMTPTypeInterdependentPropDesc::ConstructL()
    {
    ChunkAppendL(iChunkNumberOfInterdependencies);
    }
    
void CMTPTypeInterdependentPropDesc::AppendElementChunkL(CMTPTypeInterdependentProperties* aElement)
    {
    iChunksInterdependentProperties.AppendL(aElement);
    ChunkAppendL(*aElement);
    }
    
TInt CMTPTypeInterdependentPropDesc::UpdateWriteSequenceErr(TInt aErr)
    {
    iWriteSequenceErr = aErr;
    return iWriteSequenceErr;        
    }

/**
MTP InterdependentPropDesc array element dataset factory method. This method is
used to create an empty MTP InterdependentPropDesc array element dataset. 
@return A pointer to the MTP InterdependentPropDesc array element dataset type.
Ownership IS transfered.
@leave One of the system wide error codes, if unsuccessful.
*/ 
EXPORT_C CMTPTypeInterdependentProperties* CMTPTypeInterdependentProperties::NewL()
    {
    CMTPTypeInterdependentProperties* self = CMTPTypeInterdependentProperties::NewLC(); 
    CleanupStack::Pop(self);
    return self;  
    }

/**
MTP InterdependentPropDesc array element dataset factory method. This method is
used to create an empty MTP InterdependentPropDesc array element dataset. A 
pointer to the data type is placed on the cleanup stack.
@return A pointer to the MTP InterdependentPropDesc array element dataset type. 
Ownership IS transfered.
@leave One of the system wide error codes, if unsuccessful.
*/ 
EXPORT_C CMTPTypeInterdependentProperties* CMTPTypeInterdependentProperties::NewLC()
    {
    CMTPTypeInterdependentProperties* self = new(ELeave) CMTPTypeInterdependentProperties();
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
    }

/**
Destructor.
*/
EXPORT_C CMTPTypeInterdependentProperties::~CMTPTypeInterdependentProperties()
    {
    iChunksObjectPropDesc.ResetAndDestroy();
    }

/**
Appends the specified ObjectPropDesc dataset to the InterdependentPropDesc 
array element array. Ownership of the specified ObjectPropDesc dataset is 
passed to the InterdependentPropDesc array element array.
@param aElement The ObjectPropDesc dataset to append. Ownership IS transferred.
@leave One of the system wide error codes, if unsuccessful.
*/
EXPORT_C void CMTPTypeInterdependentProperties::AppendL(CMTPTypeObjectPropDesc* aElement)
    {
    // Increment NumberOfElements.
    const TUint index(iChunkNumberOfPropDescs.Value());
    iChunkNumberOfPropDescs.Set(index + 1);
    
    // Append the element.
    AppendElementChunkL(aElement);
    }

/**
Provides the NumberOfPropDescs element value.
*/
EXPORT_C TUint32 CMTPTypeInterdependentProperties::NumberOfPropDescs() const
    {
    return iChunkNumberOfPropDescs.Value();
    }

/**
Provides a non-const reference to the InterdependentPropDesc value quadruple element at
the specified index.
@param aIndex The index of the required element.
@param aValue On successful completion, a non-const reference to the requested
element.
@leave One of the system wide error codes, if unsuccessful.
*/
EXPORT_C CMTPTypeObjectPropDesc& CMTPTypeInterdependentProperties::ObjectPropDesc(TUint aIndex) const
    {
    return *iChunksObjectPropDesc[aIndex];
    }

EXPORT_C TInt CMTPTypeInterdependentProperties::FirstWriteChunk(TPtr8& aChunk)
    {   
    /* 
    Reset the type in preparation for the data stream, by deleting all
    except the first chunk.
    */
    for (TUint i(ChunkCount() - 1); (i >= (KNumberOfPropDescsChunk + 1)); i--)
        {
        ChunkRemove(i);
        }
    iChunksObjectPropDesc.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 = EInProgress;
        break;
        
    default:
        break;
        }
        
    return  err;
    }
    
EXPORT_C TInt CMTPTypeInterdependentProperties::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 TUint CMTPTypeInterdependentProperties::Type() const
    {
    return EMTPTypeInterdependentPropDescElementDataset;
    }

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

EXPORT_C MMTPType* CMTPTypeInterdependentProperties::CommitChunkL(TPtr8& aChunk)
    {
    if (iWriteSequenceErr == KMTPChunkSequenceCompletion)
        {
        switch (iWriteSequenceState)
            {
        case EInProgress:
            if ( ( iChunkNumberOfPropDescs.Value() ) &&
            (iChunksObjectPropDesc.Count() < iChunkNumberOfPropDescs.Value()))
                {
                // Allocate the next element chunk.
                CMTPTypeObjectPropDesc* element = CMTPTypeObjectPropDesc::NewLC();
                AppendElementChunkL(element);
                CleanupStack::Pop(element); 
                }
            else
                {
                iWriteSequenceState = EIdle;
                }
            break;
            
        case EIdle:
            // Completing the last element in the write sequence.
            break;
            
        default:
            Panic(EMTPTypeBadStorage);
            break;
            }
        }
        
    if (CMTPTypeCompoundBase::CommitRequired())
        {
        CMTPTypeCompoundBase::CommitChunkL(aChunk);
        }     
    return NULL;
    }
 
const CMTPTypeCompoundBase::TElementInfo& CMTPTypeInterdependentProperties::ElementInfo(TInt aElementId) const
    {
    if (aElementId == KNumberOfPropDescsChunk)
        {
        return iInfoNumberOfPropDescs;
        }
    else
        {
        __ASSERT_ALWAYS(((aElementId - KObjectPropDescChunks) < iChunkNumberOfPropDescs.Value()), Panic(EMTPTypeBoundsError));
        iInfoObjectPropDesc.iChunkId = aElementId;
        return iInfoObjectPropDesc; 
        }
    }

TInt CMTPTypeInterdependentProperties::ValidateChunkCount() const
    {
    TInt ret(KErrNone);
    if (NumberOfPropDescs() != (ChunkCount() - 1))
        {
        ret = KMTPDataTypeInvalid;
        }
    return ret;
    }

CMTPTypeInterdependentProperties::CMTPTypeInterdependentProperties() :
    CMTPTypeCompoundBase(KJustInTimeConstruction, KVariableChunkCount)
    {
    const CMTPTypeCompoundBase::TElementInfo KDefaultInfo = {0, EMTPTypeUndefined, {EMTPTypeUndefined, KMTPNotApplicable,  KMTPNotApplicable}};
    iInfoNumberOfPropDescs          = KDefaultInfo; 
    iInfoNumberOfPropDescs.iType    = EMTPTypeUINT32;
    iInfoObjectPropDesc             = KDefaultInfo; 
    iInfoObjectPropDesc.iType       = EMTPTypeInterdependentPropDescElementDataset;
    }

void CMTPTypeInterdependentProperties::ConstructL()
    {
    ChunkAppendL(iChunkNumberOfPropDescs);
    }
    
void CMTPTypeInterdependentProperties::AppendElementChunkL(CMTPTypeObjectPropDesc* aElement)
    {
    iChunksObjectPropDesc.AppendL(aElement);
    ChunkAppendL(*aElement);
    }
    
TInt CMTPTypeInterdependentProperties::UpdateWriteSequenceErr(TInt aErr)
    {
    iWriteSequenceErr = aErr;
    return iWriteSequenceErr;        
    }