--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/aknlayoutcompiler/src/MLCompCdl2InstO.cpp Thu Dec 17 09:14:18 2009 +0200
@@ -0,0 +1,2016 @@
+/*
+* Copyright (c) 2002-2008 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:
+*
+*/
+
+
+// disable "identifier was truncated to '255' characters in the browser information" warning
+#pragma warning (disable:4786)
+
+// disable "decorated name length exceeded, name was truncated" warning
+#pragma warning (disable:4503)
+
+#include "MLCompDataParse.h"
+#include "MLCompCdl2InstO.h"
+#include "ZoomLevelNames.h"
+#include "LayoutCompilerErr.h"
+#include "LayoutParse.h"
+#include "CppWriter.h"
+#include "MLCompData2Cdl.h"
+#include "LayCdl2InstO.h" // for common classes
+#include "MLAttributesParse.h"
+#include "MLAttributes.h"
+#include "CodeGenConsts.h"
+#include "UsefulDefinitions.h"
+
+#include <akndef.hrh>
+
+#include <fstream>
+#include <algorithm>
+#include <iostream>
+#include <numeric> // accumulate
+
+using namespace std;
+using namespace CdlCompilerToolkit;
+
+//
+// defines
+//
+
+#define AKNLAYOUT_DEFINE_BYTECODE(name,byte) const char name = char(byte);
+#include "AknLayoutByteCodes.h"
+
+typedef LayoutProcessArgsErr<MLCompDataCdlInstanceOpt> MLCompDataCdlInstanceOptArgsErr;
+
+
+//
+// constants
+//
+
+const string KDefinitionNotDefined("Layout not defined, this API must not be called for this instance");
+const string KDefinitionNotSet("Layout definition not found");
+extern string KMultiLine;
+const string KSpace = " ";
+const string KComma = ",";
+const string KTheWordBlank("blank");
+const string KParentRelativeMarker("Pp");
+const string KCellNameJustification("J");
+const string KCompDataFileNameSuffix("compData");
+const string KAttributesFileNameSuffix("attributes");
+
+// this is the addressable area for each instance, as the lookup table is 16bit
+const int KAddressableBytecodedData = 0xFFFF;
+
+/**
+* SCompDataImplFunc
+* This class represents a layout data decompression function local to a layout instance.
+* These functions will call the corresponding DLL wide function for decompression.
+*/
+struct SCompDataImplFunc
+ {
+ enum TFuncType
+ {
+ EWindowLine,
+ ETextLine,
+ ETableLimits,
+ EWindowTable,
+ ETextTable,
+ ELineParamLimits,
+ ETableParamLimits,
+ EGenericComponentType,
+ EGenericParamLimits,
+ EGenericWindowComponent,
+ EGenericTextComponent
+ };
+ TFuncType iType;
+ CCdlTkApiParams iParams;
+ string iDefn;
+ string iPtrRef;
+
+ SCompDataImplFunc(TFuncType aType, string aDefn, string aPtrRef, CCdlTkApiParams& aParams)
+ :
+ iType(aType),
+ iDefn(aDefn),
+ iPtrRef(aPtrRef),
+ iParams(aParams)
+ {
+
+ }
+
+ SCompDataImplFunc(TFuncType aType, string aDefn, string aPtrRef)
+ :
+ iType(aType),
+ iDefn(aDefn),
+ iPtrRef(aPtrRef)
+ {
+
+ }
+
+ bool IsSimilar(TFuncType aType, CCdlTkApiParams& aParams)
+ {
+ if(iType != aType)
+ return false;
+ int size = iParams.size();
+ if(size != aParams.size())
+ return false;
+ for(int ii = 0; ii < size; ii++)
+ {
+ CCdlTkApiParam& thisParam = iParams[ii];
+ CCdlTkApiParam& otherParam = aParams[ii];
+ if(thisParam.Name() != otherParam.Name())
+ return false;
+ if(thisParam.Type() != otherParam.Type())
+ return false;
+ // don't compare the default value, as we're not interested in that for the implementation.
+ }
+ return true;
+ }
+ };
+
+
+/**
+* CAllCompDataFuncs
+* This represents a collection of all the SCompDataImplFunc objects that a layout instance may need
+*/
+class CAllCompDataFuncs : public vector<SCompDataImplFunc>
+ {
+public:
+ CAllCompDataFuncs();
+
+private:
+ void AddFunc(SCompDataImplFunc::TFuncType aType, CCdlTkApiParams& aParams, const string& aReturn, const string& aFuncName, bool aAppendAbbreviation);
+ void AddParamsToFunc(CCdlTkApiParams& aParams, string& aDefn, string& aBody);
+ void AddParamToFunc(string aFiller, string aParamName, string& aDefn, string& aBody);
+ };
+
+
+
+/**
+* gTheFuncs
+* This is a collection of all SCompDataImplFunc objects that a layout instance needs, initialised
+* so that there are up to four integer parameters per API type.
+*/
+CAllCompDataFuncs gTheFuncs;
+
+//
+// CAllCompDataFuncs
+//
+
+CAllCompDataFuncs::CAllCompDataFuncs()
+ {
+ // need to generate all combinations of parameters
+ vector<string> paramNames;
+ paramNames.push_back(KParamOptionIndex);
+ paramNames.push_back(KParamColIndex);
+ paramNames.push_back(KParamRowIndex);
+
+ // all cominations of option, row, and column are possible, in any order
+ typedef vector<int> Seq;
+ Seq pattern;
+ set< Seq > subPatterns;
+
+ // for each of the available positions, there could be any available value, or it could be empty
+ const int numPlaces = paramNames.size();
+ for(int jj = 0; jj < numPlaces; jj++)
+ pattern.push_back(jj);
+
+ // for each permutation, copy all the possible positions
+ // into a separate set, which hence will be filled with the unique permutations
+ do
+ {
+ int numMasks = (1 << numPlaces); // eg for 3 places there are 8 masks
+ for(int mask = 0; mask < numMasks; mask++)
+ {
+ Seq subPattern;
+ int bit = 0;
+ // count down the bits
+ for(int bitCount = mask; bitCount != 0; bitCount >>= 1)
+ {
+ if(mask & (1 << bit))
+ subPattern.push_back(pattern[bit]);
+ bit++;
+ }
+ subPatterns.insert(subPattern);
+ }
+ }
+ while(next_permutation(pattern.begin(), pattern.end()));
+
+ for(set< Seq >::iterator pPattern = subPatterns.begin(); pPattern != subPatterns.end(); ++pPattern)
+ {
+ CCdlTkApiParams params;
+ for(Seq::iterator pParam = pPattern->begin(); pParam != pPattern->end(); ++pParam)
+ {
+ int& param = (*pParam);
+ string name = paramNames[param];
+ params.push_back(CCdlTkApiParam(KTypeInt, name));
+ }
+ AddFunc(SCompDataImplFunc::EWindowLine, params, KTypeWindowComponentLayout, KFuncWindowLine, true);
+ AddFunc(SCompDataImplFunc::ETextLine, params, KTypeTextComponentLayout, KFuncTextLine, true);
+
+ params.insert(params.begin(), CCdlTkApiParam(KTypeInt, KParamLineIndex));
+ AddFunc(SCompDataImplFunc::EWindowTable, params, KTypeWindowComponentLayout, KFuncWindowTable, true);
+ AddFunc(SCompDataImplFunc::ETextTable, params, KTypeTextComponentLayout, KFuncTextTable, true);
+ }
+
+ for(int ii = 0; ii < 2; ii++)
+ {
+ CCdlTkApiParams params;
+ if(ii)
+ {
+ params.push_back(CCdlTkApiParam(KTypeInt, KParamOptionIndex));
+ }
+ AddFunc(SCompDataImplFunc::ELineParamLimits, params, KTypeLayoutScalableParameterLimits, KFuncParamLimits, true);
+ params.insert(params.begin(), CCdlTkApiParam(KTypeInt, KParamLineIndex));
+ AddFunc(SCompDataImplFunc::ETableParamLimits, params, KTypeLayoutScalableParameterLimits, KFuncParamLimitsTable, true);
+ }
+
+ SCompDataImplFunc limits(
+ SCompDataImplFunc::ETableLimits,
+ KTypeLayoutScalableTableLimits + " Limits() { return AknLayoutScalableDecode::TableLimits(KDataLookup); }",
+ "&Limits");
+ push_back(limits);
+
+ // finally, the generic APIs
+ CCdlTkApiParams params;
+ params.push_back(CCdlTkApiParam(KTypeInt, KParamComponentId));
+ AddFunc(SCompDataImplFunc::EGenericComponentType, params, KTypeLayoutScalableComponentType, KFuncGetComponentTypeById, false);
+
+ // param limits needs the variety index
+ params.push_back(CCdlTkApiParam(KTypeInt, KParamOptionIndex));
+ AddFunc(SCompDataImplFunc::EGenericParamLimits, params, KTypeLayoutScalableParameterLimits, KFuncGetParamLimitsById, false);
+
+ // and getting the component by id requires all the params
+ params.push_back(CCdlTkApiParam(KTypeInt, KParamColIndex));
+ params.push_back(CCdlTkApiParam(KTypeInt, KParamRowIndex));
+ AddFunc(SCompDataImplFunc::EGenericWindowComponent, params, KTypeWindowComponentLayout, KFuncGetWindowComponentById, false);
+ AddFunc(SCompDataImplFunc::EGenericTextComponent, params, KTypeTextComponentLayout, KFuncGetTextComponentById, false);
+ }
+
+void CAllCompDataFuncs::AddFunc(SCompDataImplFunc::TFuncType aType, CCdlTkApiParams& aParams, const string& aReturn, const string& aFuncName, bool aAppendAbbreviation)
+ {
+ // create a function of this form:
+ //TAknWindowComponentLayout WindowTable$NUM$PARENT($PARAMS_TYPES_AND_NAMES)
+ // {
+ // return AknLayoutScalableDecode::WindowLine$NUM$PARENT(&KImplData, $PARAM_NAMES);
+ // }
+ string funcName = aFuncName;
+ if(aAppendAbbreviation)
+ for(CCdlTkApiParams::iterator pParam = aParams.begin(); pParam != aParams.end(); ++pParam)
+ funcName += pParam->Name().substr(1, 1); // append the first character after the "a"
+
+ string defn = aReturn + " " + funcName + "(";
+ string body = string(") { return AknLayoutScalableDecode::") + funcName + "(&KImplData";
+ AddParamsToFunc(aParams, defn, body);
+ defn += body + "); }";
+
+ string ptrRef = string("&") + funcName;
+
+ SCompDataImplFunc func(aType, defn, ptrRef, aParams);
+ push_back(func);
+ }
+
+void CAllCompDataFuncs::AddParamsToFunc(CCdlTkApiParams& aParams, string& aDefn, string& aBody)
+ {
+ string filler = "";
+ for(CCdlTkApiParams::iterator pParam = aParams.begin(); pParam != aParams.end(); ++pParam)
+ {
+ AddParamToFunc(filler, pParam->Name(), aDefn, aBody);
+ filler = KComma + KSpace;
+ }
+ }
+
+void CAllCompDataFuncs::AddParamToFunc(string aFiller, string aParamName, string& aDefn, string& aBody)
+ {
+ aDefn += aFiller + string(KTypeInt) + KSpace + aParamName;
+ aBody += KComma + KSpace + aParamName;
+ }
+
+
+//
+// CMLCompDataInstOptImpl
+//
+
+class CMLCompDataInstOptImpl
+ {
+public:
+ CMLCompDataInstOptImpl(CCdlTkImplementation* aImpl);
+ virtual ~CMLCompDataInstOptImpl();
+public:
+ CCdlTkImplementation* iImpl;
+ int iByteCodeIndex;
+ string iComment;
+ string iName;
+ vector<char> iBytes;
+ bool iIsRedirectedToExactCopy;
+ };
+
+CMLCompDataInstOptImpl::CMLCompDataInstOptImpl(CCdlTkImplementation* aImpl)
+ :
+ iImpl(aImpl),
+ iIsRedirectedToExactCopy(false)
+ {
+ }
+
+CMLCompDataInstOptImpl::~CMLCompDataInstOptImpl()
+ {
+ }
+
+//
+// CMLCompDataLineInstOptImpl
+//
+
+class CMLCompDataLineInstOptImpl : public CMLCompDataInstOptImpl
+ {
+public:
+ CMLCompDataLineInstOptImpl(TMLCompDataLine* aLine, CCdlTkImplementation* aImpl);
+ virtual ~CMLCompDataLineInstOptImpl();
+public:
+ TMLCompDataLine* iLine;
+ };
+
+CMLCompDataLineInstOptImpl::CMLCompDataLineInstOptImpl(TMLCompDataLine* aLine, CCdlTkImplementation* aImpl)
+ :
+ CMLCompDataInstOptImpl(aImpl),
+ iLine(aLine)
+ {
+ }
+
+CMLCompDataLineInstOptImpl::~CMLCompDataLineInstOptImpl()
+ {
+ }
+
+
+//
+// CMLCompDataSubTableInstOptImpl
+//
+
+class CMLCompDataSubTableInstOptImpl : public CMLCompDataInstOptImpl
+ {
+public:
+ CMLCompDataSubTableInstOptImpl(
+ TMLCompDataTable* aTable,
+ TMLCompDataTable::TMLCompDataSubTable* aSubTable,
+ CCdlTkImplementation* aImpl);
+ virtual ~CMLCompDataSubTableInstOptImpl();
+public:
+ TMLCompDataTable* iTable;
+ TMLCompDataTable::TMLCompDataSubTable* iSubTable;
+ };
+
+CMLCompDataSubTableInstOptImpl::CMLCompDataSubTableInstOptImpl(
+ TMLCompDataTable* aTable,
+ TMLCompDataTable::TMLCompDataSubTable* aSubTable,
+ CCdlTkImplementation* aImpl)
+ :
+ iTable(aTable),
+ CMLCompDataInstOptImpl(aImpl),
+ iSubTable(aSubTable)
+ {
+ }
+
+CMLCompDataSubTableInstOptImpl::~CMLCompDataSubTableInstOptImpl()
+ {
+ }
+
+
+//
+// CMLCompDataInstOpt
+//
+
+class CMLCompDataInstOpt
+ {
+public:
+ CMLCompDataInstOpt(MLCompDataCdlInstanceOpt& aInstances, TMLCompData* aLayout, const string& aInstName, const string& aZoomName, int aZoomLevel, bool aAllParams, bool aNonCompleteInstance);
+ ~CMLCompDataInstOpt();
+
+ void Process(const string& aFirstInstanceName);
+ void WriteInstance();
+
+ CCdlTkInstance& Inst() const { return *iInstance; }
+ string Name() const { return iName; }
+ string ZoomName() const { return iZoomName; }
+
+private:
+ typedef vector<int> ParamLimitVarieties;
+ typedef vector<ParamLimitVarieties> ParamLimits;
+ typedef map<int, int> IndexMap;
+
+private:
+ void ProcessLines(TMLCompDataTable& aTable);
+ void ProcessTables(TMLCompDataTable& aTable);
+ void ProcessLine(TMLCompDataLine& aLine);
+ void ProcessLineApi(TMLCompDataLine& aLine, CCdlTkImplementation& aImpl);
+ void UpdateBaseOffset();
+ void UpdateLine(CMLCompDataInstOptImpl& aImpl, int& aByteCodeSizeDelta);
+ void UpdateLineImpls();
+ void UpdateLineImplDefn(CMLCompDataInstOptImpl& aImpl);
+ void UpdateTableInstance(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub, CMLCompDataInstOptImpl* aImpl);
+
+ void SetNewLineData(CMLCompDataLineInstOptImpl& aImpl);
+ void SetNewLineParamData(CMLCompDataLineInstOptImpl& aImpl, IndexMap& aIndexMap, int aTotalMax, int aNumVarieties);
+ void OptimizeNewLineData(CMLCompDataLineInstOptImpl& aImpl, IndexMap& aIndexMap, vector<char>& aTempBytes, const vector<string>& aOutputOrder, bool aMirrored, int aTotalMax, int aNumVarieties);
+ void OptimizeNewLineCellData(IndexMap& aIndexMap, vector<char>& aTempBytes, TMLCompDataValues& aValues, unsigned int& aNextCell, int aTotalParams, int aNumVarieties, ParamLimitVarieties& aParamLimitVarieties, string cellName, bool aMirrorJustification);
+ void EncodeNewLineCellData(IndexMap& aIndexMap, vector<char>& aTempBytes, vector<string>& aValuesToEncode, unsigned int& aNextCell, int aTotalMax, bool aOptimizeVarieties, bool aOptimizeCalcs);
+
+ bool HasApi(const string& aName);
+ CCdlTkImplementation& FindImp(const string& aName);
+ CMLCompDataInstOptImpl* FindSimilarImpl(const CMLCompDataInstOptImpls& aImpls, const CCdlTkImplementation& aImpl);
+ string DefinitionString(int aByteCodeIndex, const string& aApiName);
+ bool CheckByteCodeIndexInRange(int aByteCodeIndex);
+
+ void SetGenericFunc(CMLCompDataInstOptImpl& aImpl, SCompDataImplFunc::TFuncType aType);
+ void SetLineFunc(CMLCompDataLineInstOptImpl& aImpl);
+ void SetSubTableFunc(CMLCompDataSubTableInstOptImpl& aImpl);
+ void SetParamLimits(CMLCompDataLineInstOptImpl& aImpl);
+
+ void ValidateRequiredParams(string aApiName, CCdlTkApiParams& aParams, bool aOption, bool aColumn, bool aRow);
+ void CountApiParams(CCdlTkImplementation& aApi, int& aParams);
+ SCompDataImplFunc& AddImplFunc(SCompDataImplFunc::TFuncType aType);
+ SCompDataImplFunc& AddImplFunc(SCompDataImplFunc::TFuncType aType, CCdlTkApiParams& aParams);
+
+ void SetGenericAPI(SCompDataImplFunc::TFuncType aType, const string& aName);
+ void SetExtraCpp(const string& aFirstInstanceName);
+ void OutputStats();
+
+ void AddTableToInstance(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub, int aTableNum);
+ void UpdateTables(TMLCompDataTable& aTable);
+ void AddTableParamLimitsImpl(const string& aApiName, int aByteCodeIndex, SCompDataImplFunc::TFuncType aType, bool aNeedsOptions);
+ void UpdateTableParamLimitsImpl(const string& aApiName, int aByteCodeIndex);
+ void AddTableLimitsImpl(const string& aApiName, TMLCompDataTable::TMLCompDataSubTable& aSubTable);
+ void AddTableLimitsImplDefn(TMLCompDataTable::TMLCompDataSubTable& aSubTable, CCdlTkImplementation& aImpl);
+ void AddTableImpl(const string& aApiName, TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub);
+ void AddParamLimits(TMLCompDataLine& aLine, bool aNeedsOptions);
+ void UpdateParamLimits(const string& apiName);
+ void SetDummyTableData(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSubTable, CMLCompDataInstOptImpl& aImpl);
+ void UpdateTableData(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSubTable, CMLCompDataInstOptImpl& aImpl);
+ void EncodeValue(vector<char>& aBytes, string aValue);
+ void EncodeValue(vector<char>& aBytes, int aValue);
+ void EncodeParentRelativeValue(vector<char>& aBytes, int aValue);
+ void MirrorParamName(string& aParamName);
+
+private:
+ MLCompDataCdlInstanceOpt& iInstances;
+ TMLCompData* iLayout;
+ string iName;
+ string iZoomName;
+ CCdlTkInterface& iInterface;
+ CCdlTkInstance* iInstance; // not owned
+ CMLCompDataInstOptImpls iImpls;
+ CMLCompDataInstOptImpls iTableImpls;
+ typedef vector<SCompDataImplFunc*> CImplFuncs;
+ CImplFuncs iFuncs;
+ int iZoomLevel;
+ bool iAllParams;
+ int iBaseOffset; // offset from the start of the main data table to the start of this instance's data
+ };
+
+CMLCompDataInstOpt::CMLCompDataInstOpt(MLCompDataCdlInstanceOpt& aInstances, TMLCompData* aLayout, const string& aInstName, const string& aZoomName, int aZoomLevel, bool aAllParams, bool aNonCompleteInstance)
+ :
+ iInstances(aInstances),
+ iLayout(aLayout),
+ iName(aInstName),
+ iZoomName(aZoomName),
+ iZoomLevel(aZoomLevel),
+ iInterface(iInstances.Interface()),
+ iAllParams(aAllParams),
+ iBaseOffset(0)
+ {
+ string zoomInstName = aInstName;
+ if(aZoomName.length() > 0)
+ zoomInstName += "_" + aZoomName;
+
+ iInstance = new CCdlTkInstance(iInterface);
+ iInstance->SetName(zoomInstName);
+
+ CCdlTkImplementations& impl = iInstance->Impl();
+ for (CCdlTkImplementations::iterator pImpl = impl.begin(); pImpl != impl.end(); ++pImpl)
+ {
+ const CCdlTkInterface& iface = (*pImpl)->Instance().Interface();
+ const CCdlTkApi& api = (*pImpl)->Api();
+ if(aLayout->iIsBaseInstance)
+ {
+ // for a base instance, need to set a default implementation
+ // even for missing data
+ (*pImpl)->SetDefinition(CdlTkUtil::ShortToHexString(0) + ",\t// " + KDefinitionNotDefined);
+
+ // preliminary implementation of "blank" implementation. cdl engine searches to ensure that
+ // all implementations are not NULL. So this will satisfy that test. However, if any of the
+ // methods are called, there will be an access violation, which will cause a panic
+ // this will be a successful guide to implementers not to call the API when the wrong layout
+ // pack is installed.
+ string definition = "(" + iface.NamespaceName() + "::" + api.PointerType() + ")((void*)4), // LAYOUT NOT DEFINED FOR THIS INSTANCE";
+ (*pImpl)->SetPointerReference(definition);
+ }
+ else if(aNonCompleteInstance)
+ {
+ // for a base instance, need to set a default implementation
+ // even for missing data
+ (*pImpl)->SetDefinition(CdlTkUtil::ShortToHexString(0) + ",\t// " + KDefinitionNotDefined);
+
+ // but we need the pointer to be null so that CdlEngine falls through the layer below
+ string definition = "0, // " + iface.NamespaceName() + "::" + api.PointerType();
+ (*pImpl)->SetPointerReference(definition);
+ }
+ else
+ {
+ // Initially set definition that will not compile in the resulting code.
+ // This will alert the programmer to missing layout data.
+ (*pImpl)->SetDefinition(KDefinitionNotSet);
+ }
+ }
+ }
+
+CMLCompDataInstOpt::~CMLCompDataInstOpt()
+ {
+ delete iInstance;
+ for (CMLCompDataInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl)
+ delete *pImpl;
+ for (pImpl = iTableImpls.begin(); pImpl != iTableImpls.end(); ++pImpl)
+ delete *pImpl;
+ }
+
+void CMLCompDataInstOpt::Process(const string& aFirstInstName)
+ {
+ iLayout->Compile();
+
+ for (TMLCompData::iterator pTab = iLayout->begin(); pTab != iLayout->end(); ++pTab)
+ {
+ ProcessLines(**pTab);
+ }
+
+ for (pTab = iLayout->begin(); pTab != iLayout->end(); ++pTab)
+ {
+ ProcessTables(**pTab);
+ }
+
+ // update the base offset to include all the data added, including reserving space for the tables
+ UpdateBaseOffset();
+
+ // with the correct base offset, the definitions can be updated
+ UpdateLineImpls();
+
+ for (pTab = iLayout->begin(); pTab != iLayout->end(); ++pTab)
+ {
+ // now that the rest of the data is stable, we can add the tables at the end
+ UpdateTables(**pTab);
+ }
+
+ SetGenericAPI(SCompDataImplFunc::EGenericComponentType, KFuncGetComponentTypeById);
+ SetGenericAPI(SCompDataImplFunc::EGenericParamLimits, KFuncGetParamLimitsById);
+ SetGenericAPI(SCompDataImplFunc::EGenericWindowComponent, KFuncGetWindowComponentById);
+ SetGenericAPI(SCompDataImplFunc::EGenericTextComponent, KFuncGetTextComponentById);
+
+ SetExtraCpp(aFirstInstName);
+ OutputStats();
+ }
+
+void CMLCompDataInstOpt::WriteInstance()
+ {
+ CCdlTkWriteInstance writer(*iInstance);
+ writer.Process();
+ }
+
+void CMLCompDataInstOpt::ProcessLines(TMLCompDataTable& aTable)
+ {
+ for (TMLCompDataTable::iterator pLine = aTable.begin(); pLine != aTable.end(); ++pLine)
+ {
+ ProcessLine(**pLine);
+ }
+ }
+
+void CMLCompDataInstOpt::ProcessTables(TMLCompDataTable& aTable)
+ {
+ int line = 0;
+ for (TMLCompDataTable::iterator pLine = aTable.begin(); pLine != aTable.end(); ++pLine)
+ {
+ for (TMLCompDataTable::TMLCompDataSubTables::const_iterator pSub = aTable.iSubTables.begin(); pSub != aTable.iSubTables.end(); ++pSub)
+ {
+ TMLCompDataTable::TMLCompDataSubTable& sub = **pSub;
+ int last = *(sub.rbegin());
+ if(line == last)
+ AddTableToInstance(aTable, sub, 0);
+ }
+ line++;
+ }
+ }
+
+void CMLCompDataInstOpt::ProcessLine(TMLCompDataLine& aLine)
+ {
+ string apiName = MLCompDataToCdl::LineApiName(aLine);
+ if (!HasApi(apiName))
+ return;
+
+ ProcessLineApi(aLine, FindImp(apiName));
+ }
+
+void CMLCompDataInstOpt::ProcessLineApi(TMLCompDataLine& aLine, CCdlTkImplementation& aImpl)
+ {
+ string lineName = MLCompDataToCdl::LineApiName(aLine);
+
+ CMLCompDataLineInstOptImpl* newImpl = new CMLCompDataLineInstOptImpl(&aLine, &aImpl);
+ iImpls.push_back(newImpl);
+
+ // always set the new line data
+ SetNewLineData(*newImpl);
+
+ // if we can find the new line data in the aggregated data, point to that instead
+ int foundIndex = iInstances.FindSimilarBytes(newImpl, iBaseOffset);
+ if(foundIndex >= 0)
+ {
+ newImpl->iByteCodeIndex = foundIndex;
+ newImpl->iIsRedirectedToExactCopy = true;
+ }
+ else
+ {
+ iInstances.AddImpl(newImpl);
+ }
+
+ SetLineFunc(*newImpl);
+
+ // only add parameter limits if the line is not simple
+ // and we must add the param limits after the actual impl, so that we can find it!
+ bool needsParamLimits = aLine.NeedsOptions() || aLine.NeedsCols() || aLine.NeedsRows();
+ if(needsParamLimits)
+ {
+ AddParamLimits(aLine, aLine.NeedsOptions());
+ }
+ }
+
+void CMLCompDataInstOpt::UpdateBaseOffset()
+ {
+ // have to account for this instance's tables
+ int tablesSize(0);
+ for(CMLCompDataInstOptImpls::iterator pTableImpl = iTableImpls.begin(); pTableImpl != iTableImpls.end(); ++pTableImpl)
+ {
+ CMLCompDataInstOptImpl* impl = *pTableImpl;
+ tablesSize += impl->iBytes.size();
+ }
+
+ int origByteStreamSize = iInstances.ByteStreamSize() + tablesSize;
+
+ // repeat until base offset stabilizes
+ iBaseOffset = max(0, origByteStreamSize - KAddressableBytecodedData);
+ int newBaseOffset = iBaseOffset;
+ int byteCodeSizeDelta(0);
+ do
+ {
+ iBaseOffset = newBaseOffset;
+ for(CMLCompDataInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl)
+ UpdateLine(**pImpl, byteCodeSizeDelta);
+ newBaseOffset = max(0, origByteStreamSize + byteCodeSizeDelta - KAddressableBytecodedData);
+ }
+ while(iBaseOffset != newBaseOffset);
+ }
+
+void CMLCompDataInstOpt::UpdateLine(CMLCompDataInstOptImpl& aImpl, int& aByteCodeSizeDelta)
+ {
+ if(aImpl.iIsRedirectedToExactCopy && aImpl.iByteCodeIndex < iBaseOffset)
+ {
+ // when we encoded the impls, we found a match in an area which now
+ // turns out to be before the base offset (i.e. outside the addressable range).
+
+ // first of all check in case we've already made another copy close by
+ int foundIndex = iInstances.FindSimilarBytes(&aImpl, iBaseOffset);
+ if(foundIndex >= 0)
+ {
+ aImpl.iByteCodeIndex = foundIndex;
+ }
+ else
+ {
+ // add its bytecodes to the end
+ aImpl.iIsRedirectedToExactCopy = false;
+ iInstances.AddImpl(&aImpl);
+ aByteCodeSizeDelta += aImpl.iBytes.size();
+ }
+ }
+ }
+
+
+void CMLCompDataInstOpt::UpdateLineImpls()
+ {
+ for(CMLCompDataInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl)
+ UpdateLineImplDefn(**pImpl);
+ }
+
+void CMLCompDataInstOpt::UpdateLineImplDefn(CMLCompDataInstOptImpl& aImpl)
+ {
+ if(!CheckByteCodeIndexInRange(aImpl.iByteCodeIndex))
+ throw GeneralErr(aImpl.iName + " in interface " + iInterface.FileName());
+ // the base offset has been updated, so all definitions must be refreshed
+ int adjustedIndex = aImpl.iByteCodeIndex - iBaseOffset;
+ aImpl.iImpl->SetDefinition(DefinitionString(aImpl.iByteCodeIndex, aImpl.iName));
+ UpdateParamLimits(aImpl.iName);
+ }
+
+void CMLCompDataInstOpt::UpdateTables(TMLCompDataTable& aTable)
+ {
+ // regenerate the byte code indices, in case they have changed
+ int line = 0;
+ for (TMLCompDataTable::iterator pLine = aTable.begin(); pLine != aTable.end(); ++pLine)
+ {
+ for (TMLCompDataTable::TMLCompDataSubTables::const_iterator pSub = aTable.iSubTables.begin(); pSub != aTable.iSubTables.end(); ++pSub)
+ {
+ TMLCompDataTable::TMLCompDataSubTable& sub = **pSub;
+ int last = *(sub.rbegin());
+ if(line == last)
+ {
+ string tableName = MLCompDataToCdl::SubTableApiName(sub);
+ CMLCompDataInstOptImpl* impl = FindSimilarImpl(iTableImpls, FindImp(tableName));
+ UpdateTableInstance(aTable, sub, impl);
+ }
+ }
+ line++;
+ }
+ }
+
+void CMLCompDataInstOpt::SetNewLineData(CMLCompDataLineInstOptImpl& aImpl)
+ {
+ aImpl.iBytes.clear();
+
+ TMLCompDataLine& line = *aImpl.iLine;
+ aImpl.iComment = string("for line: ");
+ aImpl.iName = MLCompDataToCdl::LineApiName(line);
+
+ // handle mirroring order
+ bool mirrored = false;
+ if(line.iParentTable) // we know top table can't be mirrored
+ mirrored = line.iParentTable->iTables->iCanBeMirror;
+ const string* outputOrder = mirrored ?
+ KCompDataGraphicOutputOrderMirrored : KCompDataGraphicOutputOrder;
+ int outputSize = KCompDataGraphicOutputOrderSize;
+ if (line.iType == TMLCompDataLine::ETextComponent)
+ {
+ outputOrder = mirrored ?
+ KCompDataTextOutputOrderMirrored : KCompDataTextOutputOrder;
+ outputSize = KCompDataTextOutputOrderSize;
+ }
+ vector<string> cellOrder(outputOrder, outputOrder + outputSize);
+
+ // we are currently storing variety as max allowed value, but it's a zero based index
+ int numVarieties = line.MaxVariety() + 1;
+
+ // we will be storing all of the rows and cols, even if the rows and cols limits are lower
+ int totalMaxCols = numVarieties * line.NumCols();
+ int totalMaxRows = numVarieties * line.NumRows();
+ int totalMax = totalMaxCols > totalMaxRows ? totalMaxCols : totalMaxRows;
+
+ // initialize the temporary bytestream, and the index map
+ vector<char> tempBytes;
+ IndexMap indexMap;
+
+ // fill in the temp byte stream and the index map for each cell
+ OptimizeNewLineData(aImpl, indexMap, tempBytes, cellOrder, mirrored, totalMax, numVarieties);
+
+ // encode the index map
+ SetNewLineParamData(aImpl, indexMap, totalMax, numVarieties);
+
+ // finally copy the temp byte stream onto the end of the real encoded byte stream
+ copy(tempBytes.begin(), tempBytes.end(), back_inserter(aImpl.iBytes));
+ }
+
+void CMLCompDataInstOpt::SetNewLineParamData(CMLCompDataLineInstOptImpl& aImpl, IndexMap& aIndexMap, int aTotalMax, int aNumVarieties)
+ {
+ // only set parameter data if the line is not simple
+ TMLCompDataLine& line = *aImpl.iLine;
+
+ bool needsHeader = line.NeedsOptions() || line.NeedsCols() || line.NeedsRows();
+
+ int typeBitfield = line.iType << 1;
+ if(needsHeader)
+ {
+ typeBitfield |= 1;
+ }
+
+ aImpl.iBytes.push_back(typeBitfield);
+
+ if(needsHeader)
+ {
+ // we can just dump the number of varieties, this will be used by the limits API
+ // and we can also them to calculate value indices within a cell when decoding
+ aImpl.iBytes.push_back(aNumVarieties);
+ }
+
+ // count the number of cells that are complex
+ char numMultiValues = aIndexMap.size();
+ if(needsHeader)
+ {
+ aImpl.iBytes.push_back(numMultiValues);
+ }
+ else
+ {
+ // we didn't think we needed a header, so there should be no complex cells!
+ if (numMultiValues > 0)
+ throw GeneralErr("complex cells detected in simple line");
+ }
+
+ // for each complex cell, encode the bitfield and the count
+ for(IndexMap::iterator pIndex = aIndexMap.begin(); pIndex != aIndexMap.end(); ++pIndex)
+ {
+ int count = pIndex->first;
+ int index = pIndex->second;
+ EncodeValue(aImpl.iBytes, index);
+ EncodeValue(aImpl.iBytes, count);
+ }
+ }
+
+void CMLCompDataInstOpt::OptimizeNewLineData(
+ CMLCompDataLineInstOptImpl& aImpl,
+ IndexMap& aIndexMap,
+ vector<char>& aTempBytes,
+ const vector<string>& aOutputOrder,
+ bool aMirrored,
+ int aTotalMax,
+ int aNumVarieties)
+ {
+ vector<ParamLimitVarieties> paramLimits;
+ TMLCompDataLine& line = *aImpl.iLine;
+
+ // start by extracting the row and column data.
+ // we can optimize the stored format along with the rest of the data
+ // so no need to optimize it yet
+ for(int cell = 0; cell < 2; cell++)
+ {
+ string cellName = aOutputOrder[cell];
+ ParamLimitVarieties nextLimits;
+ TMLCompDataValues& values = line[cellName];
+ for(int varietyIndex = 0; varietyIndex < aNumVarieties; varietyIndex++)
+ {
+ TMLCompDataZoomLevels& zoomLevels = values[varietyIndex];
+ TMLCompDataCalcs* calcs = &(zoomLevels[iZoomLevel]);
+ if(!calcs->size())
+ calcs = &(zoomLevels[EAknUiZoomNormal]);
+ int value = CdlTkUtil::ParseInt((*calcs)[0]);
+ nextLimits.push_back(value);
+ }
+ paramLimits.push_back(nextLimits);
+ }
+
+ // calculate the number of values
+ bool needsHeader = line.NeedsOptions() || line.NeedsCols() || line.NeedsRows();
+ unsigned int nextCellFlag = 1; // bit flag for the next cell, note it can get bigger than a char
+ for (cell = 0; cell < aOutputOrder.size(); cell++)
+ {
+ string cellName = aOutputOrder[cell];
+ TMLCompDataValues::TCompDataCellType type = TMLCompDataValues::Type(cellName);
+ if(!needsHeader && type == TMLCompDataValues::ECellTypeParamLimit)
+ {
+ // if we don't need header, then don't output the param limits values
+ // although we'll still use them internally
+ continue;
+ }
+
+ int paramLimitsIndex = TMLCompDataValues::Type(cellName) == TMLCompDataValues::ECellTypeCol ? 0 : 1; // if it's not a row or col, it doesn't matter what param limits are used.
+ TMLCompDataValues& values = line[cellName];
+ int numValues = 0;
+ if(type == TMLCompDataValues::ECellTypeCol || type == TMLCompDataValues::ECellTypeRow)
+ {
+ ParamLimitVarieties& nextLimits = paramLimits[paramLimitsIndex];
+ numValues = std::accumulate(nextLimits.begin(), nextLimits.end(), 0);
+ }
+ else
+ {
+ numValues = aNumVarieties;
+ }
+
+ bool mirrorJustification = (aMirrored && cellName == KCellNameJustification);
+ OptimizeNewLineCellData(aIndexMap, aTempBytes, values, nextCellFlag, numValues, aNumVarieties, paramLimits[paramLimitsIndex], cellName, mirrorJustification);
+ }
+ }
+
+void CMLCompDataInstOpt::OptimizeNewLineCellData(
+ IndexMap& aIndexMap,
+ vector<char>& aTempBytes,
+ TMLCompDataValues& aValues,
+ unsigned int& aNextCell,
+ int aTotalParams,
+ int aNumVarieties,
+ CMLCompDataInstOpt::ParamLimitVarieties& aParamLimitVarieties,
+ string cellName,
+ bool aMirrorJustification)
+ {
+ // build up the values for each variety
+ // if the valid values for each variety are the same, then we can store them once only
+ // in which case there will be as many values as the variety with the largest number of values
+ vector<string> optimizedValues;
+
+ // also build up the found valid values in case we can't optimize
+ vector<string> foundValues;
+
+ bool optimizeVarieties = true;
+ bool optimizeCalcs = true;
+ int numCalcs = 0;
+ int* largestParamLimitPtr = max_element(aParamLimitVarieties.begin(), aParamLimitVarieties.end());
+ int largestParamLimit = largestParamLimitPtr != aParamLimitVarieties.end() ? *largestParamLimitPtr : 0;
+
+ // in the case of there being no calcs at all, we don't want to be optimizing,
+ // in order to avoid wasted flags.
+ if(largestParamLimit == 1)
+ optimizeCalcs = false;
+
+ TMLCompDataValues::TCompDataCellType type = TMLCompDataValues::Type(cellName);
+ bool isColRow = (type == TMLCompDataValues::ECellTypeCol || type == TMLCompDataValues::ECellTypeRow);
+
+ // only go up to the max variety, as any data past that may be from a spurious merged instance
+ for(int varietyIndex = 0; varietyIndex < aNumVarieties; varietyIndex++)
+ {
+ TMLCompDataZoomLevels& zoomLevels = aValues[varietyIndex];
+ TMLCompDataCalcs* calcs = &(zoomLevels[iZoomLevel]);
+ if(!calcs->size())
+ calcs = &(zoomLevels[EAknUiZoomNormal]);
+ numCalcs = calcs->size();
+ string value;
+ vector<string> foundCalcs;
+ int paramLimit = aParamLimitVarieties[varietyIndex];
+ if(numCalcs == 0)
+ {
+ if(varietyIndex == 0)
+ optimizedValues.push_back(value);
+ if(varietyIndex > 0 && !(optimizedValues[0].empty()))
+ optimizeVarieties = false;
+ foundCalcs.push_back(value);
+ }
+ else
+ {
+ for(int index = 0; index < numCalcs; index++)
+ {
+ bool needToCheckIndexValidity = !isColRow || (index < paramLimit);
+ value = (*calcs)[index];
+ value = aMirrorJustification ? TMLCompDataValues::MirrorJustificationValue(value) : value;
+
+ if(index >= optimizedValues.size() && index < largestParamLimit) // index is zero based, size is quantity
+ {
+ // store the first valid value for a given index that we find.
+ // note that this will pick up additional values in subsequent varieties
+ optimizedValues.push_back(value);
+ }
+ else if(needToCheckIndexValidity && value != optimizedValues[index])
+ {
+ // so if it doesn't match, we can't optimize
+ optimizeVarieties = false;
+ }
+
+ // collect the valid found values as we go, in case we aren't able to optimize
+ if(needToCheckIndexValidity)
+ {
+ foundCalcs.push_back(value);
+ }
+ }
+ }
+ if(isColRow)
+ {
+ int found = foundCalcs.size();
+ if(!found)
+ {
+ foundCalcs.push_back(string());
+ found++;
+ }
+ if(found > 1)
+ {
+ optimizeCalcs = false;
+ }
+ }
+ else
+ {
+ optimizeCalcs = false;
+ }
+ copy(foundCalcs.begin(), foundCalcs.end(), back_inserter(foundValues));
+ }
+
+ if(optimizeVarieties && isColRow)
+ {
+ // now that we know the optimized values, fill missing values by repeating the last one.
+ // but if we're optimizing the calcs, then we don't want to expand them after all
+ if(!optimizeCalcs)
+ {
+ int optimal = optimizedValues.size();
+ string value = optimal > 0 ? optimizedValues[optimal-1] : string();
+ for(; optimal < largestParamLimit; optimal++)
+ {
+ optimizedValues.push_back(value);
+ }
+ }
+ }
+
+ if(optimizeVarieties && aNumVarieties == 1)
+ {
+ optimizeVarieties = false;
+ }
+
+ vector<string>& valuesToEncode = optimizeVarieties ? optimizedValues : foundValues;
+ EncodeNewLineCellData(aIndexMap, aTempBytes, valuesToEncode, aNextCell, aTotalParams, optimizeVarieties, optimizeCalcs);
+ }
+
+void CMLCompDataInstOpt::EncodeNewLineCellData(
+ IndexMap& aIndexMap,
+ vector<char>& aTempBytes,
+ vector<string>& aValuesToEncode,
+ unsigned int& aNextCell,
+ int aTotalMax,
+ bool aOptimizeVarieties,
+ bool aOptimizeCalcs)
+ {
+ // encode the actual data into the temporary bytestream
+ int numOptimizedVals = aValuesToEncode.size();
+ if(numOptimizedVals > 0)
+ {
+ for(vector<string>::iterator pString = aValuesToEncode.begin(); pString != aValuesToEncode.end(); ++pString)
+ {
+ EncodeValue(aTempBytes, *pString);
+ }
+ }
+ else
+ {
+ EncodeValue(aTempBytes, "");
+ }
+
+ if(numOptimizedVals > aTotalMax)
+ throw GeneralErr("bad index in indexMap");
+
+ // if there is only one value stored, we can make a further optimization
+ // as we know that all values must be the same, however they are stored
+ // so in that case, don't store an index map entry
+ if(numOptimizedVals > 1)
+ {
+ // update the index map,
+ // put the flags at the right hand side, to avoid it becoming multi-byte in general
+ int optimizeVarietiesMask = (aOptimizeVarieties ? 1 : 0);
+ int optimizeCalcsMask = (aOptimizeCalcs ? 1 : 0) << 1;
+ int numValsMask = (numOptimizedVals) << 2;
+ int indexField = (numValsMask | optimizeCalcsMask | optimizeVarietiesMask);
+ aIndexMap[indexField] |= aNextCell;
+ }
+ aNextCell = aNextCell << 1;
+ }
+
+void CMLCompDataInstOpt::CountApiParams(CCdlTkImplementation& aApi, int& aParams)
+ {
+ aParams = 0;
+ const CCdlTkApiParams& params = aApi.Api().AsFunc().Params();
+ for (CCdlTkApiParams::const_iterator pParam = params.begin(); pParam != params.end(); ++pParam)
+ {
+ if (pParam->Type() == KTypeInt) // is it a cell index parameter
+ aParams++;
+ }
+ }
+
+void CMLCompDataInstOpt::ValidateRequiredParams(string aApiName, CCdlTkApiParams& aParams, bool aOption, bool aColumn, bool aRow)
+ {
+ // check that data matches api
+ bool matches = true;
+ matches &= ((aOption) == (aParams.FindByName(KParamOptionIndex) != aParams.end()));
+ matches &= ((aColumn) == (aParams.FindByName(KParamColIndex) != aParams.end()));
+ matches &= ((aRow) == (aParams.FindByName(KParamRowIndex) != aParams.end()));
+ if(!matches)
+ throw CdlTkAssert(string("layout data does not match CDL API : ") + aApiName);
+ }
+
+void CMLCompDataInstOpt::SetGenericFunc(CMLCompDataInstOptImpl& aImpl, SCompDataImplFunc::TFuncType aType)
+ {
+ CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(aImpl.iImpl->Api().AsFunc());
+ CCdlTkApiParams& params = api.Params();
+
+ SCompDataImplFunc& func = AddImplFunc(aType, params);
+ aImpl.iImpl->SetPointerReference(func.iPtrRef);
+ }
+
+void CMLCompDataInstOpt::SetLineFunc(CMLCompDataLineInstOptImpl& aImpl)
+ {
+ SCompDataImplFunc::TFuncType type = SCompDataImplFunc::EWindowLine;
+ if (aImpl.iLine->iType == TMLCompDataLine::ETextComponent)
+ {
+ type = SCompDataImplFunc::ETextLine;
+ }
+ string name = aImpl.iImpl->Name();
+
+ // look up the api to see whether we need the params
+ CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(aImpl.iImpl->Api().AsFunc());
+ CCdlTkApiParams& params = api.Params();
+ ValidateRequiredParams(
+ name,
+ params,
+ iAllParams || aImpl.iLine->NeedsOptions(),
+ iAllParams || aImpl.iLine->NeedsCols(),
+ iAllParams || aImpl.iLine->NeedsRows());
+ SCompDataImplFunc& func = AddImplFunc(type, params);
+ aImpl.iImpl->SetPointerReference(func.iPtrRef);
+ }
+
+void CMLCompDataInstOpt::SetSubTableFunc(CMLCompDataSubTableInstOptImpl& aImpl)
+ {
+ TMLCompDataTable& table = *(aImpl.iTable);
+ TMLCompDataTable::TMLCompDataSubTable& subTable = *(aImpl.iSubTable);
+ TMLCompDataLine& line= *(table[subTable[0]]);
+
+ SCompDataImplFunc::TFuncType type = SCompDataImplFunc::EWindowTable;
+
+ if (line.iType == TMLCompDataLine::ETextComponent)
+ {
+ type = SCompDataImplFunc::ETextTable;
+ }
+ string name = aImpl.iImpl->Name();
+
+ CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(aImpl.iImpl->Api().AsFunc());
+ CCdlTkApiParams& params = api.Params();
+
+ string debug;
+ for(CCdlTkApiParams::iterator pParam = params.begin(); pParam != params.end(); ++pParam)
+ debug = pParam->Name();
+
+ ValidateRequiredParams(
+ name,
+ params,
+ iAllParams || subTable.iNeedsOption,
+ iAllParams || subTable.iNeedsCol,
+ iAllParams || subTable.iNeedsRow);
+ SCompDataImplFunc& func = AddImplFunc(type, params);
+ aImpl.iImpl->SetPointerReference(func.iPtrRef);
+ }
+
+bool CMLCompDataInstOpt::HasApi(const string& aName)
+ {
+ return iInterface.ApiList().Find(aName) != 0;
+ }
+
+CCdlTkImplementation& CMLCompDataInstOpt::FindImp(const string& aName)
+ {
+ CCdlTkImplementation* impl = iInstance->Impl().Find(aName);
+ if (!impl)
+ throw NotFoundErr(aName + " in interface " + iInterface.FileName());
+ return *impl;
+ }
+
+CMLCompDataInstOptImpl* CMLCompDataInstOpt::FindSimilarImpl(const CMLCompDataInstOptImpls& aImpls, const CCdlTkImplementation& aImpl)
+ {
+ for (CMLCompDataInstOptImpls::const_iterator pOptImpl = aImpls.begin(); pOptImpl != aImpls.end(); ++pOptImpl)
+ {
+ CMLCompDataInstOptImpl* optImpl = *pOptImpl;
+ if (optImpl->iImpl == &aImpl)
+ return optImpl;
+ }
+ return NULL;
+ }
+
+string CMLCompDataInstOpt::DefinitionString(int aByteCodeIndex, const string& aApiName)
+ {
+ int adjustedIndex = aByteCodeIndex - iBaseOffset;
+ return CdlTkUtil::ShortToHexString(adjustedIndex) + ",\t// (" + CdlTkUtil::IntToHexString(aByteCodeIndex) + ") " + aApiName;
+ }
+
+bool CMLCompDataInstOpt::CheckByteCodeIndexInRange(int aByteCodeIndex)
+ {
+ int adjustedIndex = aByteCodeIndex - iBaseOffset;
+ if(adjustedIndex > KAddressableBytecodedData)
+ {
+ cerr << "Error: Out of range: index = " << CdlTkUtil::IntToHexString(aByteCodeIndex) << ", ";
+ cerr << "baseOffset = " << CdlTkUtil::IntToHexString(iBaseOffset ) << endl;
+ return false;
+ }
+ return true;
+ }
+
+SCompDataImplFunc& CMLCompDataInstOpt::AddImplFunc(SCompDataImplFunc::TFuncType aType)
+ {
+ CCdlTkApiParams params;
+ return AddImplFunc(aType, params);
+ }
+
+SCompDataImplFunc& CMLCompDataInstOpt::AddImplFunc(SCompDataImplFunc::TFuncType aType, CCdlTkApiParams& aParams)
+ {
+ for (CImplFuncs::iterator pFunc = iFuncs.begin(); pFunc != iFuncs.end(); ++pFunc)
+ {
+ SCompDataImplFunc& func = **pFunc;
+ if(func.IsSimilar(aType, aParams))
+ return func;
+ }
+
+ int count = gTheFuncs.size();
+ for (int ii=0; ii<count; ii++)
+ {
+ SCompDataImplFunc* func = &gTheFuncs[ii];
+ if(func->IsSimilar(aType, aParams))
+ {
+ iFuncs.push_back(func);
+ return *func;
+ }
+ }
+
+ throw NotFoundErr("implementation function");
+ return gTheFuncs[0];
+ }
+
+void CMLCompDataInstOpt::SetGenericAPI(SCompDataImplFunc::TFuncType aType, const string& aName)
+ {
+ CCdlTkImplementation* impl = iInstance->Impl().Find(aName);
+
+ // CMLCompDataInstOptImpl(CCdlTkImplementation* aImpl);
+ CMLCompDataInstOptImpl* newImpl = new CMLCompDataInstOptImpl(impl);
+ iImpls.push_back(newImpl);
+
+ SetGenericFunc(*newImpl, aType);
+ newImpl->iImpl->SetDefinition(CdlTkUtil::ShortToHexString(0) + ","); // no specific data for generic apis
+ }
+
+// The following strings and the SetExtraCpp() function build the gross structure of
+// the C++ customisation instance.
+// So far, the implementations are actually just 16-bit values, typically indexes into
+// the data lookup table. These need to be turned into an array by adding declarations
+// and brackets to the first and last implementations. Extra support functions are also
+// added.
+// extern string KScalableExtraCpp;
+string KScalableExtraCpp = "\
+#include \"aknlayout2scalabledecode.h\"\n\
+namespace $INTERFACE_NS { extern const TUint8 KByteCodedData_$FIRSTINSTANCENAME[]; }\n";
+
+//extern string KScalableInitialCpp;
+string KScalableInitialCpp ="\
+extern const TUint16 KDataLookup[$INTERFACE_NS::E_TApiId_TableSize];\n\
+const SCompDataImplData KImplData = { KDataLookup, $INTERFACE_NS::KByteCodedData_$FIRSTINSTANCENAME + $THISINSTANCEBASEOFFSET };\n\
+\n\
+$FUNCTIONS\
+\n\
+const TUint16 KDataLookup[$INTERFACE_NS::E_TApiId_TableSize] =\n\
+\t{\n";
+void CMLCompDataInstOpt::SetExtraCpp(const string& aFirstInstName)
+ {
+ // The "extra cpp" field is written to the top of the cpp file.
+ CdlTkUtil::CReplaceSet cppSet;
+ cppSet.Add("$INTERFACE_NS", iInterface.NamespaceName());
+ cppSet.Add("$FIRSTINSTANCENAME", aFirstInstName);
+ cppSet.Add("$THISINSTANCEBASEOFFSET", CdlTkUtil::IntToHexString(iBaseOffset)); // base offset can be longer than 16 bits
+ iInstance->SetExtraCpp(CdlTkUtil::MultiReplace(cppSet, KScalableExtraCpp));
+
+ // add headers & fwd declarations
+ string init = CdlTkUtil::MultiReplace(cppSet, KScalableInitialCpp);
+
+ // add decode functions
+ string functions;
+ for (CImplFuncs::iterator pFunc = iFuncs.begin(); pFunc != iFuncs.end(); ++pFunc)
+ {
+ CdlTkUtil::AppendString(functions, (*pFunc)->iDefn);
+ CdlTkUtil::AppendString(functions, "\n");
+ }
+ init = CdlTkUtil::Replace("$FUNCTIONS", functions, init);
+ CCdlTkImplementation& first = **(iInstance->Impl().begin());
+ first.SetDefinition(init + first.Definition());
+
+ // add end of data table
+ CCdlTkImplementation& last = **(iInstance->Impl().end() - 1);
+ last.SetDefinition(last.Definition() + "\n};");
+ }
+
+void CMLCompDataInstOpt::OutputStats()
+ {
+ int optimizedBytes(0);
+ int unoptimizedBytes(0);
+ for (CMLCompDataInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl)
+ {
+ int size = (*pImpl)->iBytes.size();
+ if ((*pImpl)->iIsRedirectedToExactCopy)
+ optimizedBytes += size;
+ else
+ unoptimizedBytes += size;
+ }
+ for (CMLCompDataInstOptImpls::iterator pTableImpl = iTableImpls.begin(); pTableImpl != iTableImpls.end(); ++pTableImpl)
+ {
+ int size = (*pTableImpl)->iBytes.size();
+ if ((*pTableImpl)->iIsRedirectedToExactCopy)
+ optimizedBytes += size;
+ else
+ unoptimizedBytes += size;
+ }
+
+ float compress = (100.0 * (float)unoptimizedBytes) / ((float)optimizedBytes + (float)unoptimizedBytes);
+ int compressInt = (int)(compress + 0.5);
+ cout << "instance " << iName << " compressed to " << compressInt << "% of total (" << unoptimizedBytes<< " / " << optimizedBytes + unoptimizedBytes << ")" << endl;
+ }
+
+void CMLCompDataInstOpt::AddTableToInstance(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub, int /*aTableNum*/)
+ {
+ string tableName = MLCompDataToCdl::SubTableApiName(aSub);
+ string tableParamLimitsName = tableName + KFuncParamLimitsSuffix;
+
+ if (HasApi(tableName))
+ {
+ CCdlTkImplementation& impl = FindImp(tableName);
+ CMLCompDataSubTableInstOptImpl* newImpl = new CMLCompDataSubTableInstOptImpl(&aTable, &aSub, &impl);
+ iTableImpls.push_back(newImpl);
+
+ SetDummyTableData(aTable, aSub, *newImpl);
+ SetSubTableFunc(*newImpl);
+
+ AddTableLimitsImpl(tableName + KFuncLimitsSuffix, aSub);
+ if (HasApi(tableParamLimitsName))
+ {
+ AddTableParamLimitsImpl(tableParamLimitsName, newImpl->iByteCodeIndex, SCompDataImplFunc::ETableParamLimits, aSub.iNeedsOption);
+ }
+ AddTableImpl(tableName, aTable, aSub);
+ }
+ }
+
+void CMLCompDataInstOpt::UpdateTableInstance(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub, CMLCompDataInstOptImpl* aImpl)
+ {
+ string tableName = MLCompDataToCdl::SubTableApiName(aSub);
+ UpdateTableData(aTable, aSub, *aImpl);
+
+ // if we can find the new table data in the aggregated data, point to that instead
+ int foundIndex = iInstances.FindSimilarBytes(aImpl, iBaseOffset);
+ if(foundIndex >= 0)
+ {
+ if(foundIndex != aImpl->iByteCodeIndex)
+ {
+ aImpl->iByteCodeIndex = foundIndex;
+ aImpl->iIsRedirectedToExactCopy = true;
+ }
+ else
+ {
+ cerr << "Error: found same table already in bytestream: " << aImpl->iName << endl;
+ }
+ }
+
+ // now we've generated the bytecode, it will be added to the bytestream
+ iInstances.AddImpl(aImpl);
+ aImpl->iImpl->SetDefinition(DefinitionString(aImpl->iByteCodeIndex, tableName));
+
+ string tableParamLimitsName = tableName + KFuncParamLimitsSuffix;
+ if (HasApi(tableParamLimitsName))
+ {
+ UpdateTableParamLimitsImpl(tableParamLimitsName, aImpl->iByteCodeIndex);
+ }
+ }
+
+void CMLCompDataInstOpt::AddTableParamLimitsImpl(const string& aApiName, int aByteCodeIndex, SCompDataImplFunc::TFuncType aType, bool aNeedsOptions)
+ {
+ CCdlTkImplementation& impl = FindImp(aApiName);
+
+ // look up the api to see whether we need a variety params
+ CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(impl.Api().AsFunc());
+ CCdlTkApiParams& params = api.Params();
+ ValidateRequiredParams(
+ aApiName,
+ params,
+ iAllParams || aNeedsOptions,
+ false,
+ false);
+
+ SCompDataImplFunc& func = AddImplFunc(aType, params);
+
+ impl.SetDefinition(DefinitionString(aByteCodeIndex, aApiName));
+ impl.SetPointerReference(func.iPtrRef);
+ }
+
+void CMLCompDataInstOpt::UpdateTableParamLimitsImpl(const string& aApiName, int aByteCodeIndex)
+ {
+ CCdlTkImplementation& paramLimitsImpl = FindImp(aApiName);
+ paramLimitsImpl.SetDefinition(DefinitionString(aByteCodeIndex, aApiName));
+ }
+
+void CMLCompDataInstOpt::AddTableLimitsImpl(const string& aApiName, TMLCompDataTable::TMLCompDataSubTable& aSubTable)
+ {
+ CCdlTkImplementation& impl = FindImp(aApiName);
+ AddTableLimitsImplDefn(aSubTable, impl);
+ impl.SetPointerReference(AddImplFunc(SCompDataImplFunc::ETableLimits).iPtrRef);
+ }
+
+void CMLCompDataInstOpt::AddTableLimitsImplDefn(TMLCompDataTable::TMLCompDataSubTable& aSubTable, CCdlTkImplementation& aImpl)
+ {
+ // code up table limits as a pair of byte values, the first byte is the first table
+ // index, the second is the last table index.
+ int first = (*aSubTable.begin()) & 0xff;
+ int last = (*aSubTable.rbegin()) & 0xff;
+
+ // however, we want these APIs to be accessed zero based, so have to calculate the offset.
+ int offset = last - first;
+
+ int v = offset;
+ if ( v > KAddressableBytecodedData )
+ {
+ std::cerr << "*** ERROR: Value " << v << "(unknown/3) of out range" << std::endl;
+ }
+
+ aImpl.SetDefinition(CdlTkUtil::ShortToHexString(offset) + KComma);
+ }
+
+void CMLCompDataInstOpt::AddTableImpl(const string& aApiName, TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub)
+ {
+ CCdlTkImplementation& impl = FindImp(aApiName);
+
+ int nParams;
+ CountApiParams(impl, nParams);
+ nParams--; // don't count the aLineIndex param
+ SCompDataImplFunc::TFuncType type = SCompDataImplFunc::EWindowTable;
+ TMLCompDataLine::TComponentType subTableType = aTable[aSub[0]]->iType;
+ switch(subTableType)
+ {
+ case TMLCompDataLine::ETextComponent:
+ {
+ type = SCompDataImplFunc::ETextTable;
+ break;
+ }
+ }
+ CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(impl.Api().AsFunc());
+ CCdlTkApiParams& params = api.Params();
+ ValidateRequiredParams(
+ aApiName,
+ params,
+ iAllParams || aSub.iNeedsOption,
+ iAllParams || aSub.iNeedsCol,
+ iAllParams || aSub.iNeedsRow);
+ SCompDataImplFunc& func = AddImplFunc(type, params);
+ }
+
+void CMLCompDataInstOpt::AddParamLimits(TMLCompDataLine& aLine, bool aNeedsOptions)
+ {
+ string apiName = MLCompDataToCdl::LineApiName(aLine) ;
+ string paramLimitsApiName = apiName + KFuncParamLimitsSuffix;
+ if (!HasApi(paramLimitsApiName))
+ throw NotFoundErr(paramLimitsApiName + " in interface " + iInterface.FileName());
+
+ CCdlTkImplementation& paramLimitsImpl = FindImp(paramLimitsApiName);
+
+ // look up the api to see whether we need a variety params
+ CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(paramLimitsImpl.Api().AsFunc());
+ CCdlTkApiParams& params = api.Params();
+ ValidateRequiredParams(
+ paramLimitsApiName,
+ params,
+ iAllParams || aNeedsOptions,
+ false,
+ false);
+
+ SCompDataImplFunc& func = AddImplFunc(SCompDataImplFunc::ELineParamLimits, params);
+ paramLimitsImpl.SetPointerReference(func.iPtrRef);
+
+ UpdateParamLimits(apiName);
+ }
+
+void CMLCompDataInstOpt::UpdateParamLimits(const string& apiName)
+ {
+ string paramLimitsApiName = apiName + KFuncParamLimitsSuffix;
+ if (HasApi(paramLimitsApiName))
+ {
+ CCdlTkImplementation& paramLimitsImpl = FindImp(paramLimitsApiName);
+ CMLCompDataInstOptImpl* actualOptImpl = FindSimilarImpl(iImpls, FindImp(apiName));
+
+ paramLimitsImpl.SetDefinition(DefinitionString(actualOptImpl->iByteCodeIndex, paramLimitsApiName));
+ }
+ }
+
+void CMLCompDataInstOpt::SetDummyTableData(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSubTable, CMLCompDataInstOptImpl& aImpl)
+ {
+ aImpl.iBytes.clear();
+ aImpl.iComment = string("for table: ");
+ aImpl.iName = MLCompDataToCdl::SubTableApiName(aSubTable);
+ EncodeValue(aImpl.iBytes, aSubTable.size());
+ for(TMLCompDataTable::TMLCompDataSubTable::iterator pLineId = aSubTable.begin(); pLineId != aSubTable.end(); ++pLineId)
+ {
+ aImpl.iBytes.push_back(0);
+ aImpl.iBytes.push_back(0);
+ }
+ }
+
+void CMLCompDataInstOpt::UpdateTableData(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSubTable, CMLCompDataInstOptImpl& aImpl)
+ {
+ aImpl.iBytes.clear();
+ EncodeValue(aImpl.iBytes, aSubTable.size());
+ for(TMLCompDataTable::TMLCompDataSubTable::iterator pLineId = aSubTable.begin(); pLineId != aSubTable.end(); ++pLineId)
+ {
+ // figure out the offset to the next line of the table
+ TMLCompDataLine& line = *(aTable[*pLineId]);
+ string lineName = MLCompDataToCdl::LineApiName(line) ;
+ CMLCompDataInstOptImpl* lineImpl = FindSimilarImpl(iImpls, FindImp(lineName));
+
+ // we must store the adjusted index, ie relative to the base offset, in the definition, as that will be used
+ // in the main output, so check that the offset is in range, which it should be if we've updated the lines
+ // correctly
+ if(!CheckByteCodeIndexInRange(lineImpl->iByteCodeIndex))
+ throw GeneralErr(aImpl.iName + " in interface " + iInterface.FileName());
+ int adjustedIndex = lineImpl->iByteCodeIndex - iBaseOffset;
+
+ // make an assumption that data fits into 16 bits, and don't encode the lookups
+ // that way, when decoding, we can jump forward by 2 bytes * index without decoding
+ // all the values (since they're not encoded, we know they're all the same size)
+ aImpl.iBytes.push_back((adjustedIndex & 0xff00) >> 8);
+ aImpl.iBytes.push_back(adjustedIndex);
+ }
+ }
+
+struct SIdToInt
+ {
+ int iInt;
+ char* iStr;
+ };
+
+#include <avkon.hrh>
+extern SIdToInt gIdToIntTable[];
+extern const int gIdToIntTableCount;
+extern void TranslateValue(string& aValue);
+
+void CMLCompDataInstOpt::EncodeValue(vector<char>& aBytes, string aValue)
+ {
+ int pos = 0;
+ TranslateValue(aValue);
+ if (aValue == "")
+ {
+ aBytes.push_back(KByteEmpty);
+ }
+ else
+ {
+ pos = aValue.find_first_of(KParentRelativeMarker);
+ if(pos != string::npos)
+ {
+ if (pos != 0)
+ throw CdlTkAssert(string("arithmetic parser not good enough : ") + aValue);
+ int val = CdlTkUtil::ParseInt(aValue.substr(1));
+ EncodeParentRelativeValue(aBytes, val);
+ }
+ else
+ {
+ int val = CdlTkUtil::ParseInt(aValue);
+ EncodeValue(aBytes, val);
+ }
+ }
+ }
+
+void CMLCompDataInstOpt::EncodeValue(vector<char>& aBytes, int aValue)
+ {
+ if (0 <= aValue && aValue <= KMaxSingleByteValue)
+ {
+ aBytes.push_back(aValue);
+ }
+ else if (aValue > KMaxSingleByteValue && aValue <= KMaxDoubleByteValue)
+ {
+ aBytes.push_back(KByteWord);
+ aBytes.push_back((aValue & 0xff00) >> 8);
+ aBytes.push_back(aValue);
+ }
+ else
+ {
+ aBytes.push_back(KByteLong);
+ aBytes.push_back((aValue & 0xff000000) >> 24);
+ aBytes.push_back((aValue & 0x00ff0000) >> 16);
+ aBytes.push_back((aValue & 0x0000ff00) >> 8);
+ aBytes.push_back(aValue);
+ }
+ }
+
+void CMLCompDataInstOpt::EncodeParentRelativeValue(vector<char>& aBytes, int aValue)
+ {
+ if (KMinSingleByteParentRelativeValue <= aValue && aValue <= KMaxSingleByteParentRelativeValue)
+ {
+ aBytes.push_back(KByteP1);
+ aBytes.push_back(aValue);
+ }
+ else
+ {
+ aBytes.push_back(KByteP2);
+ aBytes.push_back((aValue & 0xff00) >> 8);
+ aBytes.push_back(aValue);
+ }
+ }
+
+void CMLCompDataInstOpt::MirrorParamName(string& aParamName)
+ {
+ if (aParamName == KParamNameL)
+ aParamName = KParamNameR;
+ else if (aParamName == KParamNameR)
+ aParamName = KParamNameL;
+ }
+
+//
+// MLCompDataCdlInstanceOpt
+//
+
+MLCompDataCdlInstanceOpt::InstStruct::InstStruct(string aInstName, TMLCompData* aInst, TMLAttributes* aAttribs)
+ :
+ iInstName(aInstName),
+ iInst(aInst),
+ iAttribs(aAttribs)
+ {
+ }
+
+MLCompDataCdlInstanceOpt::InstList::~InstList()
+ {
+ for(InstList::iterator pNext = begin(); pNext != end(); ++pNext)
+ {
+ delete pNext->iInst;
+ }
+ }
+
+void MLCompDataCdlInstanceOpt::ProcessSeparators(vector<string>& args, vector<int>& aSeparators)
+ {
+ for(int arg = 3; arg < args.size(); arg++)
+ {
+ if(args[arg] == "-a")
+ aSeparators.push_back(arg);
+ }
+
+ aSeparators.push_back(args.size()); // add an implicit last separator
+ if(aSeparators.size() < 2)
+ throw MLCompDataCdlInstanceOptArgsErr();
+
+ // check that the distance between each separator is not a multiple of 2
+ // i.e. counting the steps between aSeparators ( sep -> xml -> inst -> sep) is 3 steps
+ // i.e. counting the steps between aSeparators ( sep -> xml -> inst -> xml -> inst -> sep) is 5 steps
+ for(int sep = 0; sep < aSeparators.size() - 1; sep++)
+ {
+ int delta = aSeparators[sep+1] - aSeparators[sep];
+ if (delta%2 == 0)
+ throw MLCompDataCdlInstanceOptArgsErr();
+ }
+ }
+
+bool MLCompDataCdlInstanceOpt::CheckForUsedInstances(
+ const CInstanceList& aUsedList,
+ const CZoomLevelNames& aZoomLevelNames,
+ const vector<string>& aArgs,
+ const vector<int>& aSeparators,
+ int aSepIndex)
+ {
+ bool ok = false;
+ for(CZoomLevelNames::const_iterator pZoomLevel = aZoomLevelNames.begin(); pZoomLevel != aZoomLevelNames.end(); ++pZoomLevel)
+ {
+ // check if any of these instances are used - skip this if none are used
+ for (int arg = aSeparators[aSepIndex] + 1; arg < aSeparators[aSepIndex+1]; arg += 2)
+ {
+ string instName = aArgs[arg+1] + "_" + pZoomLevel->second;
+ if (aUsedList.IsInstanceOk(instName))
+ ok = true;
+ }
+ }
+ return ok;
+ }
+
+void MLCompDataCdlInstanceOpt::ParseInstances(const vector<string>& aArgs, const vector<int>& aSeparators, int aSepIndex, MLCompDataCdlInstanceOpt::InstList& aInstList)
+ {
+ for (int arg = aSeparators[aSepIndex] + 1; arg < aSeparators[aSepIndex+1]; arg += 2)
+ {
+ string layoutName = aArgs[arg];
+ string instName = aArgs[arg+1];
+ string attribsName = CdlTkUtil::Replace(KCompDataFileNameSuffix, KAttributesFileNameSuffix, layoutName);
+
+ auto_ptr<TMLCompDataParseLayout> layoutParse = TMLCompDataParseLayout::Parse(layoutName);
+ auto_ptr<TMLCompData> layout(layoutParse.get());
+ layoutParse.release();
+
+ auto_ptr<TMLAttributesParse> attribsParse = TMLAttributesParse::Parse(attribsName);
+ auto_ptr<TMLAttributes> attribs(attribsParse.get());
+ attribsParse.release();
+
+ InstStruct instStruct(instName, layout.get(), attribs.get());
+ aInstList.push_back(instStruct);
+ layout.release();
+ attribs.release();
+ }
+ }
+
+void MLCompDataCdlInstanceOpt::MergeLayouts(CInstanceList& aInstUsedList, CZoomLevelNames& aZoomLevelNames, const InstList& aInstances, InstList& aMergedLayouts)
+ {
+ // start with the non-mirrored instances
+ for(int count = 0; count < 2; count++)
+ {
+ bool isMirrored = (count != 0);
+ // first iterate through the layouts, we will generate one instance per layout
+ for(int instIndex = 0; instIndex < aInstances.size(); instIndex++)
+ {
+ const InstStruct& instStruct = aInstances[instIndex];
+ string targetInstName = instStruct.iInstName;
+ TMLCompData& targetLayout = *(instStruct.iInst);
+ TMLAttributes& targetAttribs = *(instStruct.iAttribs);
+
+ bool required = false;
+ for(CZoomLevelNames::const_iterator pZoomLevel = aZoomLevelNames.begin(); pZoomLevel != aZoomLevelNames.end(); ++pZoomLevel)
+ {
+ string zoomInstName = targetInstName + "_" + pZoomLevel->second;
+ if(aInstUsedList.IsInstanceOk(zoomInstName))
+ required = true;
+ }
+
+ // if this target is not required, or if it's the wrong sort of mirrored
+ // for this iteration, skip it.
+ if(targetLayout.iCanBeMirror != isMirrored || !required)
+ continue;
+
+ // for each instance, we must merge all the other layouts
+ auto_ptr<TMLCompData> mergedLayout(new TMLCompData());
+ auto_ptr<TMLAttributes> mergedAttribs(new TMLAttributes());
+ for (InstList::const_iterator pInst2 = aInstances.begin(); pInst2 != aInstances.end(); ++pInst2)
+ {
+ // merge in all the others
+ const InstStruct& instStruct2 = *pInst2;
+ if(instStruct2.iInstName != targetInstName)
+ {
+ TMLCompData& nextLayout = *(instStruct2.iInst);
+ TMLAttributes& nextAttribs = *(instStruct2.iAttribs);
+ // but only if it's the right kind of mirrored
+ if(nextLayout.iCanBeMirror == isMirrored)
+ {
+ mergedLayout->Merge(nextLayout);
+ mergedAttribs->Merge(nextAttribs);
+ }
+ }
+ }
+ // then end up merging in the one we want
+ mergedLayout->Merge(targetLayout);
+ mergedAttribs->Merge(targetAttribs);
+ if(isMirrored)
+ {
+ // If we have just processed a mirrored layout,
+ // we need to do a mirror merge with the corresponding one.
+ // The instances are ordered as on the command line,
+ // but the merged layouts are grouped toghether, unmirrored first.
+ // So to convert between the two indexes: 1 -> 0, and 3 -> 1
+ int unMirroredMergedLayoutIndex = (instIndex / 2);
+ InstStruct& unMirroredInst = aMergedLayouts[unMirroredMergedLayoutIndex]; // this works as we have already added the unmirrored instance to the vector
+ TMLCompData& unMirroredLayout = *(unMirroredInst.iInst);
+ TMLAttributes& unMirroredAttribs = *(unMirroredInst.iAttribs);
+ mergedLayout->Merge(unMirroredLayout);
+ mergedAttribs->Merge(unMirroredAttribs);
+ }
+
+ InstStruct mergedInstStruct(targetInstName, mergedLayout.get(), mergedAttribs.get());
+ aMergedLayouts.push_back(mergedInstStruct);
+ mergedLayout.release();
+ mergedAttribs.release();
+ }
+ }
+ }
+
+int MLCompDataCdlInstanceOpt::Process(vector<string>& args)
+ {
+ // parse the file containing the used instances list. only instances in this list
+ // will be generated, even if also mentioned on the command line
+ CInstanceList instUsedList;
+ instUsedList.ProcessOptions(args);
+
+ // extract the zoom level names, note that this consumes the argument if present
+ CZoomLevelNames zoomLevelNames;
+ zoomLevelNames.ProcessOptions(args);
+
+ // check that we have an acceptable number of arguments
+ int extraArgs = args.size() - 3;
+ if (extraArgs < 0)
+ throw MLCompDataCdlInstanceOptArgsErr();
+
+ // check for optional flags
+ int arg = 2;
+ bool allParams = false;
+ if (args[arg] == "-allparams")
+ {
+ allParams = true;
+ arg++;
+ }
+
+ bool nonCompleteInstance = false;
+ if(args[arg].substr(0,2) == "-d")
+ {
+ arg++;
+ if (args[arg].size() >= 2)
+ {
+ nonCompleteInstance = true;
+ }
+ }
+
+ // parse the CDL interface
+ string cdlName = args[arg];
+ CCdlTkCdlFileParser parser(cdlName);
+ auto_ptr<CCdlTkInterface> iface(parser.LoadAndParse(true));
+ MLCompDataCdlInstanceOpt process(*iface);
+
+ // the separators divide the layout instances that are aggregated together
+ vector<int> separators;
+ ProcessSeparators(args, separators);
+ for(int sep = 0; sep < separators.size() - 1; sep++)
+ {
+ if(!CheckForUsedInstances(instUsedList, zoomLevelNames, args, separators, sep))
+ continue;
+ // start from after the next separator, and continue until before the next one
+ InstList instances;
+ ParseInstances(args, separators, sep, instances);
+
+ InstList mergedLayouts;
+ MergeLayouts(instUsedList, zoomLevelNames, instances, mergedLayouts);
+ for(InstList::iterator pMergedLayout = mergedLayouts.begin(); pMergedLayout != mergedLayouts.end(); )
+ {
+ process.AddInst(*pMergedLayout, zoomLevelNames, allParams, nonCompleteInstance); // pass ownership of mergedLayout
+ pMergedLayout = mergedLayouts.erase(pMergedLayout);
+ }
+ }
+
+ process.Process();
+ process.WriteInstances();
+ return 0;
+ }
+
+void MLCompDataCdlInstanceOpt::ShowHelp(ostream& stream)
+ {
+ stream << "MLCompCdl2InstO [-i<instanceList>] [-z<zoomList>] [-allparams] [-d<deliveryType>] <interface.cdl> (-a ([-m]<layout.xml> <instanceName>)+ )+" << endl;
+ stream << " Creates optimised CDL instances containing the layout data." << endl;
+ stream << " Each -a flag is followed by a collection of xml and instance name pairs." << endl;
+ stream << " Each collection is aggregated separately." << endl;
+ stream << " The aggregation of the layout instances must conform to the CDL interface, " << endl;
+ stream << " but note any missing data in an instance may result in data being returned " << endl;
+ stream << " from a different instance, although duplicate implementations will be reused " << endl;
+ stream << " to reduce ROM usage." << endl;
+ stream << " A -m flag must precede an xml file that contains mirrored layout data." << endl;
+ stream << " An aggregated collection of layouts must contain interleaved" << endl;
+ stream << " elaf and the corresponding abrw instances." << endl;
+ stream << " If -i<instanceList> is specified, then only instances whose name" << endl;
+ stream << " appears in the file <instanceList> will be processed." << endl;
+ stream << " If -z<zoomList> is specified, then only instances whose zoom factor" << endl;
+ stream << " (in the form \"n,string\") appears in the file <zoomList> will be generated." << endl;
+ stream << " If -allparams is used, all processed APIs will have all available params added, " << endl;
+ stream << " otherwise only needed params are added." << endl;
+ stream << " If -d<deliveryType> is supplied with any value, any API that has a missing" << endl;
+ stream << " implementation will be filled in with NULL, allowing fall-through to an instance" << endl;
+ stream << " from a lower priority pack." << endl;
+ }
+
+MLCompDataCdlInstanceOpt::MLCompDataCdlInstanceOpt(CCdlTkInterface& aInterface)
+ :
+ iInterface(aInterface)
+ {
+ }
+
+MLCompDataCdlInstanceOpt::~MLCompDataCdlInstanceOpt()
+ {
+ for(CCompDataZoomLevelDatas::iterator pZoomLevel = iZoomLevelDatas.begin(); pZoomLevel != iZoomLevelDatas.end(); ++pZoomLevel)
+ {
+ CCompDatas& compDatas = pZoomLevel->second;
+ for (CCompDatas::iterator pInstOpt = compDatas.begin(); pInstOpt != compDatas.end(); ++pInstOpt)
+ delete *pInstOpt;
+ }
+ for(CCompDataLayouts::iterator pLayout = iLayouts.begin(); pLayout != iLayouts.end(); ++pLayout)
+ delete *pLayout;
+ }
+
+void MLCompDataCdlInstanceOpt::AddInst(const InstStruct& aInstStruct, CZoomLevelNames& aZoomLevelNames, bool aAllParams, bool aNonCompleteInstance)
+ {
+ TMLCompData* layout = aInstStruct.iInst;
+ layout->iAttributes = aInstStruct.iAttribs; // transfer ownership
+ iLayouts.push_back(aInstStruct.iInst);
+ for(CZoomLevelNames::iterator pZoomLevel = aZoomLevelNames.begin(); pZoomLevel != aZoomLevelNames.end(); ++pZoomLevel)
+ {
+ auto_ptr<CMLCompDataInstOpt> p(new CMLCompDataInstOpt(*this, layout, aInstStruct.iInstName, pZoomLevel->second, pZoomLevel->first, aAllParams, aNonCompleteInstance));
+ CCompDatas& compDatas = iZoomLevelDatas[pZoomLevel->first];
+ compDatas.push_back(p.get());
+ p.release();
+ }
+ }
+
+void MLCompDataCdlInstanceOpt::Process()
+ {
+ for(CCompDataZoomLevelDatas::iterator pZoomLevel = iZoomLevelDatas.begin(); pZoomLevel != iZoomLevelDatas.end(); ++pZoomLevel)
+ {
+ CCompDatas& compDatas = pZoomLevel->second;
+ if(compDatas.size() == 0)
+ continue;
+ CMLCompDataInstOpt* firstInstOpt = compDatas[0];
+ cout << "processing instances for zoom level: " << firstInstOpt->ZoomName() << endl;
+
+ string firstInstName = firstInstOpt->Name();
+ for (CCompDatas::iterator pLayout = compDatas.begin(); pLayout != compDatas.end(); ++pLayout)
+ (*pLayout)->Process(firstInstName);
+ }
+ ProcessCommonImpl();
+ }
+
+void MLCompDataCdlInstanceOpt::WriteInstances()
+ {
+ bool found = false;
+ for(CCompDataZoomLevelDatas::iterator pZoomLevel = iZoomLevelDatas.begin(); pZoomLevel != iZoomLevelDatas.end(); ++pZoomLevel)
+ {
+ CCompDatas& compDatas = pZoomLevel->second;
+ if(!found && compDatas.size() > 0)
+ {
+ found = true;
+ cout << "writing instances ... " << endl;
+ }
+ for (CCompDatas::iterator pLayout = compDatas.begin(); pLayout != compDatas.end(); ++pLayout)
+ (*pLayout)->WriteInstance();
+ }
+ }
+
+CCdlTkInterface& MLCompDataCdlInstanceOpt::Interface()
+ {
+ return iInterface;
+ }
+
+const string KCommonImplStart = "\
+#include \"aknlayout2scalabledecode.h\"\n\
+namespace $NAMESPACENAME { extern TUint8 const KByteCodedData_$FIRSTINSTANCENAME[] = {\n";
+
+const string KCommonImplImpl = "\
+// $INDEX $COMMENT\n\
+$BYTES\n";
+
+void MLCompDataCdlInstanceOpt::ProcessCommonImpl()
+ {
+ // use the first instance name of the first zoom level
+ // it's not entirely accurate but it only needs to disambiguate
+ CCompDatas& compDatas = iZoomLevelDatas[EAknUiZoomNormal];
+ if(compDatas.size() == 0)
+ return;
+ CMLCompDataInstOpt* firstInstOpt = compDatas[0];
+
+ CdlTkUtil::CReplaceSet startImplSet;
+ startImplSet.Add("$NAMESPACENAME", iInterface.NamespaceName());
+ startImplSet.Add("$FIRSTINSTANCENAME", firstInstOpt->Name());
+ string bytecode = CdlTkUtil::MultiReplace(startImplSet, KCommonImplStart);
+ int byteCounter(0);
+
+ for (CMLCompDataInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl)
+ {
+ vector<char>& bytes = (*pImpl)->iBytes;
+ if (!(*pImpl)->iIsRedirectedToExactCopy && bytes.size())
+ {
+ string byteString;
+ for (vector<char>::iterator pChar = bytes.begin(); pChar != bytes.end(); ++pChar)
+ {
+ CdlTkUtil::AppendString(byteString, CdlTkUtil::CharToHexString(*pChar));
+ CdlTkUtil::AppendString(byteString, KComma);
+ }
+
+ // in this case, we want to know the absolute index to help with debugging
+ int index = (*pImpl)->iByteCodeIndex;
+ if(byteCounter != index)
+ {
+ cerr << "Error: Data table mismatch for " << (*pImpl)->iName;
+ cerr << ": Bytecode index = " << CdlTkUtil::ShortToHexString(index);
+ cerr << "; byte counter = " << CdlTkUtil::ShortToHexString(byteCounter) << endl;
+ throw GeneralErr((*pImpl)->iName + " in interface " + iInterface.FileName());
+ }
+ byteCounter += bytes.size();
+
+ CdlTkUtil::CReplaceSet implSet;
+ implSet.Add("$INDEX", CdlTkUtil::IntToHexString(index));
+ implSet.Add("$COMMENT", (*pImpl)->iComment + (*pImpl)->iName + " (" + CdlTkUtil::ShortToHexString(bytes.size()) + " bytes)");
+ implSet.Add("$BYTES", byteString);
+ CdlTkUtil::AppendString(bytecode, CdlTkUtil::MultiReplace(implSet, KCommonImplImpl));
+ }
+ }
+ CdlTkUtil::AppendString(bytecode, "};\n}");
+ CCdlTkInstance& firstInst = firstInstOpt->Inst();
+ firstInst.SetExtraCpp(bytecode);
+ }
+
+int MLCompDataCdlInstanceOpt::FindSimilarBytes(CMLCompDataInstOptImpl* aImpl, int aBaseOffset)
+ {
+ int index = -1;
+ vector<char>::iterator startOfAddressableBlock = iBytesAggregated.begin() + aBaseOffset;
+ vector<char>::iterator found = std::search(
+ startOfAddressableBlock,
+ iBytesAggregated.end(),
+ aImpl->iBytes.begin(),
+ aImpl->iBytes.end());
+ if(found != iBytesAggregated.end())
+ {
+ index = std::distance(iBytesAggregated.begin(), found); // we return the absolute position
+ }
+ return index;
+ }
+
+void MLCompDataCdlInstanceOpt::AddImpl(CMLCompDataInstOptImpl* aImpl)
+ {
+ if(!aImpl->iIsRedirectedToExactCopy)
+ {
+ CMLCompDataInstOptImpls::iterator found = std::find(iImpls.begin(), iImpls.end(), aImpl);
+ if(found == iImpls.end())
+ {
+ iImpls.push_back(aImpl);
+ }
+ else
+ {
+ cerr << "Error: " << aImpl->iName << " already added to byte stream" << endl;
+ throw GeneralErr(aImpl->iName + " in interface " + iInterface.FileName());
+ }
+ if (aImpl->iBytes.size())
+ {
+ aImpl->iByteCodeIndex = iBytesAggregated.size();
+ iBytesAggregated.insert(
+ iBytesAggregated.end(),
+ aImpl->iBytes.begin(),
+ aImpl->iBytes.end());
+ }
+ }
+ }
+
+int MLCompDataCdlInstanceOpt::ByteStreamSize() const
+ {
+ return iBytesAggregated.size();
+ }
+
+// end of file
+
+