diff -r 000000000000 -r 2f259fa3e83a lafagnosticuifoundation/cone/inc/CoeDynamicStorage.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lafagnosticuifoundation/cone/inc/CoeDynamicStorage.inl Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,408 @@ +// Copyright (c) 1997-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: +// + +// #define PROFILE_MEMORY // Uncomment to profile ammount of saved memory. + +#ifdef PROFILE_MEMORY +static TInt MEMORY_SAVED = 0; // In bytes +const TInt KCurrentNumberOfOptionalVaraiblesInCCoeControl = 13; +#endif + +/** +This class implements a container for (in most cases, pointers to) optional +CCoeControl members. + +The size of the class is 12 bytes: one 32-bit pointer to a C-style array +of 32-bit data, and one long long (64 bits) variable used as an array of 4-bit +indices into said C-style array. + +Each optional CCoeControl data is assigned an index into the long long member, +used to look up the variables actual index in the C-style array. This way, the +first time a new optional CCoeControl variable is set it is appended to the C-style +array, and the index of the new item is recorded in the variable's assigned +4-bit slot in the long long. + +The 4-bits used for each index allows for 16 indices to be stored in the long long. +However, one value (say 0xF) is required to signal that the optional variable has +not yet been added to the C-style array, so this leaves 15 optional CCoeControl members. + +This also leaves the last 4 bits in the long long unused. Now, we also need a way +to record the current size of the C-style array. As the size range from 0 to 15, +4-bit is enough, which means that we can use the last 4 spare bits in the long long +instead of adding another variable to the RCoeDynamicDataStorage! + +Thus, each first time an optional member is set, we need to re-allocate the C-style +array, and this operation might of course fail. All of the data kept in the +RCoeDynamicDataStorage must therefore be optional, and the code able to cope +with this. To minimize the number of re-allocations, the RCoeDynamicDataStorage +allows pre-allocation of the maximum amount needed. Currently, pre-allocation is +attempted at CCoeControl construction (in the c'tor), and compression is attempted +when the control is activated. The RCoeDynamicDataStorage will still work if either +fails. + +@internalComponent */ +class RCoeDynamicDataStorage + { +public: + RCoeDynamicDataStorage(); + void Open(); + void Close(); + TInt Count() const; + void ResetCount(); + void IncCount(); + TInt ReserveData(); + TBool HasReservedData() const; + void AttemptCompress(); + inline TAny* Data(TInt aSlotIndex, TAny* aDefaultValue) const; //mm Will this method be expanded inline when used inside coecntrl.cpp? + TInt SetData(TInt aSlotIndex, TAny* aAny); + inline TInt DataIndex(TInt aSlotIndex) const; + void SetDataIndex(TInt aSlotIndex, TInt aDataIndex); + +private: + static const TInt KMaxDataItems; + static const TInt KCounterSlotIndex; + static const TInt KIndexSlotSize; + static const Uint64 KIndexSlotMask; + static const TInt KUndefinedIndex; + +private: + TInt Append(TAny* aAny); + +private: + Uint64 iIndices; // array of slots containing indices into the data array + TAny** iDynamicData; // dynamic array of 32-bit data (mostly pointers) + }; + + +const TInt RCoeDynamicDataStorage::KMaxDataItems = 15; +const TInt RCoeDynamicDataStorage::KCounterSlotIndex = 0xF; +const TInt RCoeDynamicDataStorage::KIndexSlotSize = 4; +const Uint64 RCoeDynamicDataStorage::KIndexSlotMask = 0xFLL; //long long +const TInt RCoeDynamicDataStorage::KUndefinedIndex = 0xF; + +RCoeDynamicDataStorage::RCoeDynamicDataStorage() +: iIndices(~0x0), iDynamicData(NULL) // Set iIndices to all ones + { + ResetCount(); + } + +void RCoeDynamicDataStorage::Open() + { + ASSERT(!iDynamicData); + ReserveData(); + +#ifdef PROFILE_MEMORY + MEMORY_SAVED += KCurrentNumberOfOptionalVaraiblesInCCoeControl*sizeof(TAny*); + MEMORY_SAVED -= sizeof(RCoeDynamicDataStorage); +#endif + } + +void RCoeDynamicDataStorage::Close() + { +#ifdef PROFILE_MEMORY + MEMORY_SAVED += sizeof(RCoeDynamicDataStorage); + if(HasReservedData()) + MEMORY_SAVED += KMaxDataItems*sizeof(TAny*); + else + MEMORY_SAVED += Count()*sizeof(TAny*); + + MEMORY_SAVED -= KCurrentNumberOfOptionalVaraiblesInCCoeControl*sizeof(TAny*); +#endif + delete [] iDynamicData; + } + +TInt RCoeDynamicDataStorage::Count() const + { + if(HasReservedData()) + { + TInt count = 0; + for(TInt i = 0; i < KMaxDataItems; i++) + { + if(DataIndex(i) != KUndefinedIndex) + count++; + } + return count; + } + else + return DataIndex(KCounterSlotIndex); + } + +void RCoeDynamicDataStorage::ResetCount() + { + SetDataIndex(KCounterSlotIndex, 0); + } + +void RCoeDynamicDataStorage::IncCount() + { + TInt count = Count(); + count++; + SetDataIndex(KCounterSlotIndex, count); + ASSERT(count <= KMaxDataItems); + } + +TInt RCoeDynamicDataStorage::SetData(TInt aSlotIndex, TAny* aAny) + { + if(!this) + return KErrNoMemory; + + const TInt dataIndex = DataIndex(aSlotIndex); + + if(dataIndex != KUndefinedIndex) + iDynamicData[dataIndex] = aAny; + else if(HasReservedData()) + { + const TInt count = Count(); + iDynamicData[count] = aAny; + SetDataIndex(aSlotIndex, count); + } + else + { + const TInt err = Append(aAny); + if(err) + return err; + else + SetDataIndex(aSlotIndex, Count()-1); + } + ASSERT(Data(aSlotIndex, NULL) == aAny); + return KErrNone; + } + +inline TAny* RCoeDynamicDataStorage::Data(TInt aSlotIndex, TAny* aDefaultValue) const + { + if(!this) + return aDefaultValue; + + const TInt dataIndex = DataIndex(aSlotIndex); + if(dataIndex != KUndefinedIndex) + return iDynamicData[dataIndex]; + else + return aDefaultValue; + } + +inline TInt RCoeDynamicDataStorage::DataIndex(TInt aSlotIndex) const + { + const Uint64 mask = KIndexSlotMask << KIndexSlotSize*aSlotIndex; + return ((iIndices&mask) >> KIndexSlotSize*aSlotIndex); + } + +void RCoeDynamicDataStorage::SetDataIndex(TInt aSlotIndex, TInt aDataIndex) + { + const Uint64 mask = KIndexSlotMask << KIndexSlotSize*aSlotIndex; + const Uint64 dataIndex = Uint64(aDataIndex) << KIndexSlotSize*aSlotIndex; + iIndices &= ~mask; // clear the old index + iIndices |= dataIndex; // set the new index + } + +TInt RCoeDynamicDataStorage::Append(TAny* aAny) + { + ASSERT(!HasReservedData()); // Should never have reserved data if we get here + + const TInt count = Count(); + TAny** newData = new TAny*[count+1]; + if(!newData) + return KErrNoMemory; + + memcpy(newData, iDynamicData, count * sizeof(TAny*)); + + newData[count] = aAny; + IncCount(); +#ifdef PROFILE_MEMORY + MEMORY_SAVED -= (1 * sizeof(TAny*)); +#endif + + delete [] iDynamicData; + iDynamicData = newData; + return KErrNone; + } + + +TInt RCoeDynamicDataStorage::ReserveData() + { + ASSERT(!iDynamicData); + iDynamicData = new TAny*[KMaxDataItems]; // Attempt to pre-alloc data + if(!iDynamicData) + return KErrNoMemory; + +#ifdef PROFILE_MEMORY + MEMORY_SAVED -= KMaxDataItems*sizeof(TAny*); +#endif + return KErrNone; + } + +TBool RCoeDynamicDataStorage::HasReservedData() const + { + return (iDynamicData && DataIndex(KCounterSlotIndex) == 0); + } + +void RCoeDynamicDataStorage::AttemptCompress() + { + if(!HasReservedData()) + return; + + const TInt count = Count(); + if(!count) // "new TAny*[0]" gives undefined result! + { + delete [] iDynamicData; + iDynamicData = NULL; + } + else + { + TAny** newData = new TAny*[count]; + if(!newData) + return; + + memcpy(newData, iDynamicData, count * sizeof(TAny*)); + + delete [] iDynamicData; + iDynamicData = newData; + SetDataIndex(KCounterSlotIndex, count); + } + +#ifdef PROFILE_MEMORY + MEMORY_SAVED += (sizeof(TAny*) * (0xF - count)); +#endif + } + +// +// class TCoeZoomWithType +// + +class TCoeZoomWithType + { +public: + TInt iZoomFactor; + CCoeControl::TZoomType iZoomType; + }; + +// +// class SColorOverride +// + +struct SColorOverride + { + TRgb iColor; + TInt iLogicalColor; + }; + +enum TData + { + ECoeControlParent = 0x0, + ECoeControlObserver = 0x1, + ECoeComponentArray = 0x2, + ECoeLayoutManager = 0x3, + ECoeControlBackground = 0x4, + EMaximumWidthTInt = 0x5, + EUniqueHandleTInt = 0x6, + EColorOverrides = 0x7, + EFocusObserverNotificationIdentifier = 0x8, + ECoeControlHitTest = 0x9, + EZoomWithType = 0xA, + ECustomGc = 0xB, + EFontProvider = 0xC, + + EMaxOptionlData = 0xF + }; + +// CoeControlParent +inline CCoeControl* DoGetParent(const RCoeDynamicDataStorage& aData) + { return static_cast(aData.Data(ECoeControlParent, NULL)); } + +inline TInt DoSetParent(RCoeDynamicDataStorage& aData, CCoeControl* aParent) + { return aData.SetData(ECoeControlParent, aParent); } + +// Observer +inline MCoeControlObserver* DoGetObserver(const RCoeDynamicDataStorage& aData) + { return static_cast(aData.Data(ECoeControlObserver, NULL)); } + +inline TInt DoSetObserver(RCoeDynamicDataStorage& aData, MCoeControlObserver* aObserver) + { return aData.SetData(ECoeControlObserver, aObserver); } + +// ComponentArray +inline CCoeControlArray* DoGetComponentArray(const RCoeDynamicDataStorage& aData) + { return static_cast(aData.Data(ECoeComponentArray, NULL)); } + +inline TInt DoSetComponentArray(RCoeDynamicDataStorage& aData, CCoeControlArray* aComponentArray) + { return aData.SetData(ECoeComponentArray, aComponentArray); } + +// LayoutManager +inline MCoeLayoutManager* DoGetLayoutManager(const RCoeDynamicDataStorage& aData) + { return static_cast(aData.Data(ECoeLayoutManager, NULL)); } + +inline TInt DoSetLayoutManager(RCoeDynamicDataStorage& aData, MCoeLayoutManager* aLayoutManager) + { return aData.SetData(ECoeLayoutManager, aLayoutManager); } + +// Background +inline const MCoeControlBackground* DoGetBackground(const RCoeDynamicDataStorage& aData) + { return reinterpret_cast(aData.Data(ECoeControlBackground, NULL)); } + +inline TInt DoSetBackground(RCoeDynamicDataStorage& aData, const MCoeControlBackground* aBackground) + { return aData.SetData(ECoeControlBackground, const_cast(aBackground)); } + +// Max width +inline TInt DoGetMaximumWidth(const RCoeDynamicDataStorage& aData) + { return reinterpret_cast(aData.Data(EMaximumWidthTInt, NULL)); } + +inline TInt DoSetMaximumWidth(RCoeDynamicDataStorage& aData, TInt aMaxWidth) + { return aData.SetData(EMaximumWidthTInt, reinterpret_cast(aMaxWidth)); } + +// Unique Id +inline TInt DoGetUniqueHandle(const RCoeDynamicDataStorage& aData) + { return reinterpret_cast(aData.Data(EUniqueHandleTInt, reinterpret_cast(KErrNotFound))); } + +inline TInt DoSetUniqueHandle(RCoeDynamicDataStorage& aData, TInt aUniqueHandle) + { return aData.SetData(EUniqueHandleTInt, reinterpret_cast(aUniqueHandle)); } + +// ColorOverrides +inline CArrayFix* DoGetColorOverrides(const RCoeDynamicDataStorage& aData) + { return reinterpret_cast*>(aData.Data(EColorOverrides, NULL)); } + +inline TInt DoSetColorOverrides(RCoeDynamicDataStorage& aData, CArrayFix* aColorOverrides) + { return aData.SetData(EColorOverrides, static_cast(aColorOverrides)); } + +// FocusObserverNotificationIdentifier +inline TInt DoGetFocusObserverNotificationIdentifier(const RCoeDynamicDataStorage& aData) + { return reinterpret_cast(aData.Data(EFocusObserverNotificationIdentifier, NULL)); } + +inline TInt DoSetFocusObserverNotificationIdentifier(RCoeDynamicDataStorage& aData, TInt aFocusObserverNotificationIdentifier) + { return aData.SetData(EFocusObserverNotificationIdentifier, reinterpret_cast(aFocusObserverNotificationIdentifier)); } + +// HitTest +inline const MCoeControlHitTest* DoGetHitTest(const RCoeDynamicDataStorage& aData) + { return reinterpret_cast(aData.Data(ECoeControlHitTest, NULL)); } + +inline TInt DoSetHitTest(RCoeDynamicDataStorage& aData, const MCoeControlHitTest* aHitTest) + { return aData.SetData(ECoeControlHitTest, const_cast(aHitTest)); } + +// ZoomWithType +inline TCoeZoomWithType* DoGetZoomWithType(const RCoeDynamicDataStorage& aData) + { return reinterpret_cast(aData.Data(EZoomWithType, NULL)); } + +inline TInt DoSetZoomWithType(RCoeDynamicDataStorage& aData, const TCoeZoomWithType* aZoomWithType) + { return aData.SetData(EZoomWithType, const_cast(aZoomWithType)); } + +// CustomGc +inline CWindowGc* DoGetCustomGc(const RCoeDynamicDataStorage& aData) + { return reinterpret_cast(aData.Data(ECustomGc, NULL)); } + +inline TInt DoSetCustomGc(const RCoeDynamicDataStorage& aData, CWindowGc* aGc) + { return const_cast(aData).SetData(ECustomGc, aGc); } + +// FontProvider +inline const CCoeFontProvider* DoGetFontProvider(const RCoeDynamicDataStorage& aData) + { return reinterpret_cast(aData.Data(EFontProvider, NULL)); } + +inline TInt DoSetFontProvider(const RCoeDynamicDataStorage& aData, const CCoeFontProvider* aFontProvider) + { return const_cast(aData).SetData(EFontProvider, const_cast(aFontProvider)); } +