lafagnosticuifoundation/cone/inc/CoeDynamicStorage.inl
changeset 0 2f259fa3e83a
child 10 9f56a4e1b8ab
--- /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<CCoeControl*>(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<MCoeControlObserver*>(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<CCoeControlArray*>(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<MCoeLayoutManager*>(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<const MCoeControlBackground*>(aData.Data(ECoeControlBackground, NULL)); }
+
+inline TInt DoSetBackground(RCoeDynamicDataStorage& aData, const MCoeControlBackground* aBackground) 
+	{ return aData.SetData(ECoeControlBackground, const_cast<MCoeControlBackground*>(aBackground)); }
+
+// Max width
+inline TInt DoGetMaximumWidth(const RCoeDynamicDataStorage& aData)
+	{ return reinterpret_cast<TInt>(aData.Data(EMaximumWidthTInt, NULL)); }
+
+inline TInt DoSetMaximumWidth(RCoeDynamicDataStorage& aData, TInt aMaxWidth) 
+	{ return aData.SetData(EMaximumWidthTInt, reinterpret_cast<TAny*>(aMaxWidth)); }
+
+// Unique Id
+inline TInt DoGetUniqueHandle(const RCoeDynamicDataStorage& aData)
+	{ return reinterpret_cast<TInt>(aData.Data(EUniqueHandleTInt, reinterpret_cast<TAny*>(KErrNotFound))); }
+
+inline TInt DoSetUniqueHandle(RCoeDynamicDataStorage& aData, TInt aUniqueHandle) 
+	{ return aData.SetData(EUniqueHandleTInt, reinterpret_cast<TAny*>(aUniqueHandle)); }
+
+// ColorOverrides
+inline CArrayFix<SColorOverride>* DoGetColorOverrides(const RCoeDynamicDataStorage& aData)
+	{ return reinterpret_cast<CArrayFix<SColorOverride>*>(aData.Data(EColorOverrides, NULL)); }
+
+inline TInt DoSetColorOverrides(RCoeDynamicDataStorage& aData, CArrayFix<SColorOverride>* aColorOverrides) 
+	{ return aData.SetData(EColorOverrides, static_cast<TAny*>(aColorOverrides)); }
+
+// FocusObserverNotificationIdentifier
+inline TInt DoGetFocusObserverNotificationIdentifier(const RCoeDynamicDataStorage& aData)
+	{ return reinterpret_cast<TInt>(aData.Data(EFocusObserverNotificationIdentifier, NULL)); }
+
+inline TInt DoSetFocusObserverNotificationIdentifier(RCoeDynamicDataStorage& aData, TInt aFocusObserverNotificationIdentifier) 
+	{ return aData.SetData(EFocusObserverNotificationIdentifier, reinterpret_cast<TAny*>(aFocusObserverNotificationIdentifier)); }
+
+// HitTest
+inline const MCoeControlHitTest* DoGetHitTest(const RCoeDynamicDataStorage& aData)
+	{ return reinterpret_cast<const MCoeControlHitTest*>(aData.Data(ECoeControlHitTest, NULL)); }
+
+inline TInt DoSetHitTest(RCoeDynamicDataStorage& aData, const MCoeControlHitTest* aHitTest) 
+	{ return aData.SetData(ECoeControlHitTest, const_cast<MCoeControlHitTest*>(aHitTest)); }
+
+// ZoomWithType
+inline TCoeZoomWithType* DoGetZoomWithType(const RCoeDynamicDataStorage& aData)
+	{ return reinterpret_cast<TCoeZoomWithType*>(aData.Data(EZoomWithType, NULL)); }
+
+inline TInt DoSetZoomWithType(RCoeDynamicDataStorage& aData, const TCoeZoomWithType* aZoomWithType) 
+	{ return aData.SetData(EZoomWithType, const_cast<TCoeZoomWithType*>(aZoomWithType)); }
+
+// CustomGc
+inline CWindowGc* DoGetCustomGc(const RCoeDynamicDataStorage& aData)
+	{ return reinterpret_cast<CWindowGc*>(aData.Data(ECustomGc, NULL)); }
+
+inline TInt DoSetCustomGc(const RCoeDynamicDataStorage& aData, CWindowGc* aGc) 
+	{ return const_cast<RCoeDynamicDataStorage&>(aData).SetData(ECustomGc, aGc); }
+
+// FontProvider
+inline const CCoeFontProvider* DoGetFontProvider(const RCoeDynamicDataStorage& aData)
+	{ return reinterpret_cast<const CCoeFontProvider*>(aData.Data(EFontProvider, NULL)); }
+
+inline TInt DoSetFontProvider(const RCoeDynamicDataStorage& aData, const CCoeFontProvider* aFontProvider) 
+	{ return const_cast<RCoeDynamicDataStorage&>(aData).SetData(EFontProvider, const_cast<CCoeFontProvider*>(aFontProvider)); }
+