|
1 /* |
|
2 * Copyright (c) 2002-2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // disable "identifier was truncated to '255' characters in the browser information" warning |
|
20 #pragma warning (disable:4786) |
|
21 |
|
22 // disable "decorated name length exceeded, name was truncated" warning |
|
23 #pragma warning (disable:4503) |
|
24 |
|
25 #include "MLCompDataParse.h" |
|
26 #include "MLCompCdl2InstO.h" |
|
27 #include "ZoomLevelNames.h" |
|
28 #include "LayoutCompilerErr.h" |
|
29 #include "LayoutParse.h" |
|
30 #include "CppWriter.h" |
|
31 #include "MLCompData2Cdl.h" |
|
32 #include "LayCdl2InstO.h" // for common classes |
|
33 #include "MLAttributesParse.h" |
|
34 #include "MLAttributes.h" |
|
35 #include "CodeGenConsts.h" |
|
36 #include "UsefulDefinitions.h" |
|
37 |
|
38 #include <akndef.hrh> |
|
39 |
|
40 #include <fstream> |
|
41 #include <algorithm> |
|
42 #include <iostream> |
|
43 #include <numeric> // accumulate |
|
44 |
|
45 using namespace std; |
|
46 using namespace CdlCompilerToolkit; |
|
47 |
|
48 // |
|
49 // defines |
|
50 // |
|
51 |
|
52 #define AKNLAYOUT_DEFINE_BYTECODE(name,byte) const char name = char(byte); |
|
53 #include "AknLayoutByteCodes.h" |
|
54 |
|
55 typedef LayoutProcessArgsErr<MLCompDataCdlInstanceOpt> MLCompDataCdlInstanceOptArgsErr; |
|
56 |
|
57 |
|
58 // |
|
59 // constants |
|
60 // |
|
61 |
|
62 const string KDefinitionNotDefined("Layout not defined, this API must not be called for this instance"); |
|
63 const string KDefinitionNotSet("Layout definition not found"); |
|
64 extern string KMultiLine; |
|
65 const string KSpace = " "; |
|
66 const string KComma = ","; |
|
67 const string KTheWordBlank("blank"); |
|
68 const string KParentRelativeMarker("Pp"); |
|
69 const string KCellNameJustification("J"); |
|
70 const string KCompDataFileNameSuffix("compData"); |
|
71 const string KAttributesFileNameSuffix("attributes"); |
|
72 |
|
73 // this is the addressable area for each instance, as the lookup table is 16bit |
|
74 const int KAddressableBytecodedData = 0xFFFF; |
|
75 |
|
76 /** |
|
77 * SCompDataImplFunc |
|
78 * This class represents a layout data decompression function local to a layout instance. |
|
79 * These functions will call the corresponding DLL wide function for decompression. |
|
80 */ |
|
81 struct SCompDataImplFunc |
|
82 { |
|
83 enum TFuncType |
|
84 { |
|
85 EWindowLine, |
|
86 ETextLine, |
|
87 ETableLimits, |
|
88 EWindowTable, |
|
89 ETextTable, |
|
90 ELineParamLimits, |
|
91 ETableParamLimits, |
|
92 EGenericComponentType, |
|
93 EGenericParamLimits, |
|
94 EGenericWindowComponent, |
|
95 EGenericTextComponent |
|
96 }; |
|
97 TFuncType iType; |
|
98 CCdlTkApiParams iParams; |
|
99 string iDefn; |
|
100 string iPtrRef; |
|
101 |
|
102 SCompDataImplFunc(TFuncType aType, string aDefn, string aPtrRef, CCdlTkApiParams& aParams) |
|
103 : |
|
104 iType(aType), |
|
105 iDefn(aDefn), |
|
106 iPtrRef(aPtrRef), |
|
107 iParams(aParams) |
|
108 { |
|
109 |
|
110 } |
|
111 |
|
112 SCompDataImplFunc(TFuncType aType, string aDefn, string aPtrRef) |
|
113 : |
|
114 iType(aType), |
|
115 iDefn(aDefn), |
|
116 iPtrRef(aPtrRef) |
|
117 { |
|
118 |
|
119 } |
|
120 |
|
121 bool IsSimilar(TFuncType aType, CCdlTkApiParams& aParams) |
|
122 { |
|
123 if(iType != aType) |
|
124 return false; |
|
125 int size = iParams.size(); |
|
126 if(size != aParams.size()) |
|
127 return false; |
|
128 for(int ii = 0; ii < size; ii++) |
|
129 { |
|
130 CCdlTkApiParam& thisParam = iParams[ii]; |
|
131 CCdlTkApiParam& otherParam = aParams[ii]; |
|
132 if(thisParam.Name() != otherParam.Name()) |
|
133 return false; |
|
134 if(thisParam.Type() != otherParam.Type()) |
|
135 return false; |
|
136 // don't compare the default value, as we're not interested in that for the implementation. |
|
137 } |
|
138 return true; |
|
139 } |
|
140 }; |
|
141 |
|
142 |
|
143 /** |
|
144 * CAllCompDataFuncs |
|
145 * This represents a collection of all the SCompDataImplFunc objects that a layout instance may need |
|
146 */ |
|
147 class CAllCompDataFuncs : public vector<SCompDataImplFunc> |
|
148 { |
|
149 public: |
|
150 CAllCompDataFuncs(); |
|
151 |
|
152 private: |
|
153 void AddFunc(SCompDataImplFunc::TFuncType aType, CCdlTkApiParams& aParams, const string& aReturn, const string& aFuncName, bool aAppendAbbreviation); |
|
154 void AddParamsToFunc(CCdlTkApiParams& aParams, string& aDefn, string& aBody); |
|
155 void AddParamToFunc(string aFiller, string aParamName, string& aDefn, string& aBody); |
|
156 }; |
|
157 |
|
158 |
|
159 |
|
160 /** |
|
161 * gTheFuncs |
|
162 * This is a collection of all SCompDataImplFunc objects that a layout instance needs, initialised |
|
163 * so that there are up to four integer parameters per API type. |
|
164 */ |
|
165 CAllCompDataFuncs gTheFuncs; |
|
166 |
|
167 // |
|
168 // CAllCompDataFuncs |
|
169 // |
|
170 |
|
171 CAllCompDataFuncs::CAllCompDataFuncs() |
|
172 { |
|
173 // need to generate all combinations of parameters |
|
174 vector<string> paramNames; |
|
175 paramNames.push_back(KParamOptionIndex); |
|
176 paramNames.push_back(KParamColIndex); |
|
177 paramNames.push_back(KParamRowIndex); |
|
178 |
|
179 // all cominations of option, row, and column are possible, in any order |
|
180 typedef vector<int> Seq; |
|
181 Seq pattern; |
|
182 set< Seq > subPatterns; |
|
183 |
|
184 // for each of the available positions, there could be any available value, or it could be empty |
|
185 const int numPlaces = paramNames.size(); |
|
186 for(int jj = 0; jj < numPlaces; jj++) |
|
187 pattern.push_back(jj); |
|
188 |
|
189 // for each permutation, copy all the possible positions |
|
190 // into a separate set, which hence will be filled with the unique permutations |
|
191 do |
|
192 { |
|
193 int numMasks = (1 << numPlaces); // eg for 3 places there are 8 masks |
|
194 for(int mask = 0; mask < numMasks; mask++) |
|
195 { |
|
196 Seq subPattern; |
|
197 int bit = 0; |
|
198 // count down the bits |
|
199 for(int bitCount = mask; bitCount != 0; bitCount >>= 1) |
|
200 { |
|
201 if(mask & (1 << bit)) |
|
202 subPattern.push_back(pattern[bit]); |
|
203 bit++; |
|
204 } |
|
205 subPatterns.insert(subPattern); |
|
206 } |
|
207 } |
|
208 while(next_permutation(pattern.begin(), pattern.end())); |
|
209 |
|
210 for(set< Seq >::iterator pPattern = subPatterns.begin(); pPattern != subPatterns.end(); ++pPattern) |
|
211 { |
|
212 CCdlTkApiParams params; |
|
213 for(Seq::iterator pParam = pPattern->begin(); pParam != pPattern->end(); ++pParam) |
|
214 { |
|
215 int& param = (*pParam); |
|
216 string name = paramNames[param]; |
|
217 params.push_back(CCdlTkApiParam(KTypeInt, name)); |
|
218 } |
|
219 AddFunc(SCompDataImplFunc::EWindowLine, params, KTypeWindowComponentLayout, KFuncWindowLine, true); |
|
220 AddFunc(SCompDataImplFunc::ETextLine, params, KTypeTextComponentLayout, KFuncTextLine, true); |
|
221 |
|
222 params.insert(params.begin(), CCdlTkApiParam(KTypeInt, KParamLineIndex)); |
|
223 AddFunc(SCompDataImplFunc::EWindowTable, params, KTypeWindowComponentLayout, KFuncWindowTable, true); |
|
224 AddFunc(SCompDataImplFunc::ETextTable, params, KTypeTextComponentLayout, KFuncTextTable, true); |
|
225 } |
|
226 |
|
227 for(int ii = 0; ii < 2; ii++) |
|
228 { |
|
229 CCdlTkApiParams params; |
|
230 if(ii) |
|
231 { |
|
232 params.push_back(CCdlTkApiParam(KTypeInt, KParamOptionIndex)); |
|
233 } |
|
234 AddFunc(SCompDataImplFunc::ELineParamLimits, params, KTypeLayoutScalableParameterLimits, KFuncParamLimits, true); |
|
235 params.insert(params.begin(), CCdlTkApiParam(KTypeInt, KParamLineIndex)); |
|
236 AddFunc(SCompDataImplFunc::ETableParamLimits, params, KTypeLayoutScalableParameterLimits, KFuncParamLimitsTable, true); |
|
237 } |
|
238 |
|
239 SCompDataImplFunc limits( |
|
240 SCompDataImplFunc::ETableLimits, |
|
241 KTypeLayoutScalableTableLimits + " Limits() { return AknLayoutScalableDecode::TableLimits(KDataLookup); }", |
|
242 "&Limits"); |
|
243 push_back(limits); |
|
244 |
|
245 // finally, the generic APIs |
|
246 CCdlTkApiParams params; |
|
247 params.push_back(CCdlTkApiParam(KTypeInt, KParamComponentId)); |
|
248 AddFunc(SCompDataImplFunc::EGenericComponentType, params, KTypeLayoutScalableComponentType, KFuncGetComponentTypeById, false); |
|
249 |
|
250 // param limits needs the variety index |
|
251 params.push_back(CCdlTkApiParam(KTypeInt, KParamOptionIndex)); |
|
252 AddFunc(SCompDataImplFunc::EGenericParamLimits, params, KTypeLayoutScalableParameterLimits, KFuncGetParamLimitsById, false); |
|
253 |
|
254 // and getting the component by id requires all the params |
|
255 params.push_back(CCdlTkApiParam(KTypeInt, KParamColIndex)); |
|
256 params.push_back(CCdlTkApiParam(KTypeInt, KParamRowIndex)); |
|
257 AddFunc(SCompDataImplFunc::EGenericWindowComponent, params, KTypeWindowComponentLayout, KFuncGetWindowComponentById, false); |
|
258 AddFunc(SCompDataImplFunc::EGenericTextComponent, params, KTypeTextComponentLayout, KFuncGetTextComponentById, false); |
|
259 } |
|
260 |
|
261 void CAllCompDataFuncs::AddFunc(SCompDataImplFunc::TFuncType aType, CCdlTkApiParams& aParams, const string& aReturn, const string& aFuncName, bool aAppendAbbreviation) |
|
262 { |
|
263 // create a function of this form: |
|
264 //TAknWindowComponentLayout WindowTable$NUM$PARENT($PARAMS_TYPES_AND_NAMES) |
|
265 // { |
|
266 // return AknLayoutScalableDecode::WindowLine$NUM$PARENT(&KImplData, $PARAM_NAMES); |
|
267 // } |
|
268 string funcName = aFuncName; |
|
269 if(aAppendAbbreviation) |
|
270 for(CCdlTkApiParams::iterator pParam = aParams.begin(); pParam != aParams.end(); ++pParam) |
|
271 funcName += pParam->Name().substr(1, 1); // append the first character after the "a" |
|
272 |
|
273 string defn = aReturn + " " + funcName + "("; |
|
274 string body = string(") { return AknLayoutScalableDecode::") + funcName + "(&KImplData"; |
|
275 AddParamsToFunc(aParams, defn, body); |
|
276 defn += body + "); }"; |
|
277 |
|
278 string ptrRef = string("&") + funcName; |
|
279 |
|
280 SCompDataImplFunc func(aType, defn, ptrRef, aParams); |
|
281 push_back(func); |
|
282 } |
|
283 |
|
284 void CAllCompDataFuncs::AddParamsToFunc(CCdlTkApiParams& aParams, string& aDefn, string& aBody) |
|
285 { |
|
286 string filler = ""; |
|
287 for(CCdlTkApiParams::iterator pParam = aParams.begin(); pParam != aParams.end(); ++pParam) |
|
288 { |
|
289 AddParamToFunc(filler, pParam->Name(), aDefn, aBody); |
|
290 filler = KComma + KSpace; |
|
291 } |
|
292 } |
|
293 |
|
294 void CAllCompDataFuncs::AddParamToFunc(string aFiller, string aParamName, string& aDefn, string& aBody) |
|
295 { |
|
296 aDefn += aFiller + string(KTypeInt) + KSpace + aParamName; |
|
297 aBody += KComma + KSpace + aParamName; |
|
298 } |
|
299 |
|
300 |
|
301 // |
|
302 // CMLCompDataInstOptImpl |
|
303 // |
|
304 |
|
305 class CMLCompDataInstOptImpl |
|
306 { |
|
307 public: |
|
308 CMLCompDataInstOptImpl(CCdlTkImplementation* aImpl); |
|
309 virtual ~CMLCompDataInstOptImpl(); |
|
310 public: |
|
311 CCdlTkImplementation* iImpl; |
|
312 int iByteCodeIndex; |
|
313 string iComment; |
|
314 string iName; |
|
315 vector<char> iBytes; |
|
316 bool iIsRedirectedToExactCopy; |
|
317 }; |
|
318 |
|
319 CMLCompDataInstOptImpl::CMLCompDataInstOptImpl(CCdlTkImplementation* aImpl) |
|
320 : |
|
321 iImpl(aImpl), |
|
322 iIsRedirectedToExactCopy(false) |
|
323 { |
|
324 } |
|
325 |
|
326 CMLCompDataInstOptImpl::~CMLCompDataInstOptImpl() |
|
327 { |
|
328 } |
|
329 |
|
330 // |
|
331 // CMLCompDataLineInstOptImpl |
|
332 // |
|
333 |
|
334 class CMLCompDataLineInstOptImpl : public CMLCompDataInstOptImpl |
|
335 { |
|
336 public: |
|
337 CMLCompDataLineInstOptImpl(TMLCompDataLine* aLine, CCdlTkImplementation* aImpl); |
|
338 virtual ~CMLCompDataLineInstOptImpl(); |
|
339 public: |
|
340 TMLCompDataLine* iLine; |
|
341 }; |
|
342 |
|
343 CMLCompDataLineInstOptImpl::CMLCompDataLineInstOptImpl(TMLCompDataLine* aLine, CCdlTkImplementation* aImpl) |
|
344 : |
|
345 CMLCompDataInstOptImpl(aImpl), |
|
346 iLine(aLine) |
|
347 { |
|
348 } |
|
349 |
|
350 CMLCompDataLineInstOptImpl::~CMLCompDataLineInstOptImpl() |
|
351 { |
|
352 } |
|
353 |
|
354 |
|
355 // |
|
356 // CMLCompDataSubTableInstOptImpl |
|
357 // |
|
358 |
|
359 class CMLCompDataSubTableInstOptImpl : public CMLCompDataInstOptImpl |
|
360 { |
|
361 public: |
|
362 CMLCompDataSubTableInstOptImpl( |
|
363 TMLCompDataTable* aTable, |
|
364 TMLCompDataTable::TMLCompDataSubTable* aSubTable, |
|
365 CCdlTkImplementation* aImpl); |
|
366 virtual ~CMLCompDataSubTableInstOptImpl(); |
|
367 public: |
|
368 TMLCompDataTable* iTable; |
|
369 TMLCompDataTable::TMLCompDataSubTable* iSubTable; |
|
370 }; |
|
371 |
|
372 CMLCompDataSubTableInstOptImpl::CMLCompDataSubTableInstOptImpl( |
|
373 TMLCompDataTable* aTable, |
|
374 TMLCompDataTable::TMLCompDataSubTable* aSubTable, |
|
375 CCdlTkImplementation* aImpl) |
|
376 : |
|
377 iTable(aTable), |
|
378 CMLCompDataInstOptImpl(aImpl), |
|
379 iSubTable(aSubTable) |
|
380 { |
|
381 } |
|
382 |
|
383 CMLCompDataSubTableInstOptImpl::~CMLCompDataSubTableInstOptImpl() |
|
384 { |
|
385 } |
|
386 |
|
387 |
|
388 // |
|
389 // CMLCompDataInstOpt |
|
390 // |
|
391 |
|
392 class CMLCompDataInstOpt |
|
393 { |
|
394 public: |
|
395 CMLCompDataInstOpt(MLCompDataCdlInstanceOpt& aInstances, TMLCompData* aLayout, const string& aInstName, const string& aZoomName, int aZoomLevel, bool aAllParams, bool aNonCompleteInstance); |
|
396 ~CMLCompDataInstOpt(); |
|
397 |
|
398 void Process(const string& aFirstInstanceName); |
|
399 void WriteInstance(); |
|
400 |
|
401 CCdlTkInstance& Inst() const { return *iInstance; } |
|
402 string Name() const { return iName; } |
|
403 string ZoomName() const { return iZoomName; } |
|
404 |
|
405 private: |
|
406 typedef vector<int> ParamLimitVarieties; |
|
407 typedef vector<ParamLimitVarieties> ParamLimits; |
|
408 typedef map<int, int> IndexMap; |
|
409 |
|
410 private: |
|
411 void ProcessLines(TMLCompDataTable& aTable); |
|
412 void ProcessTables(TMLCompDataTable& aTable); |
|
413 void ProcessLine(TMLCompDataLine& aLine); |
|
414 void ProcessLineApi(TMLCompDataLine& aLine, CCdlTkImplementation& aImpl); |
|
415 void UpdateBaseOffset(); |
|
416 void UpdateLine(CMLCompDataInstOptImpl& aImpl, int& aByteCodeSizeDelta); |
|
417 void UpdateLineImpls(); |
|
418 void UpdateLineImplDefn(CMLCompDataInstOptImpl& aImpl); |
|
419 void UpdateTableInstance(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub, CMLCompDataInstOptImpl* aImpl); |
|
420 |
|
421 void SetNewLineData(CMLCompDataLineInstOptImpl& aImpl); |
|
422 void SetNewLineParamData(CMLCompDataLineInstOptImpl& aImpl, IndexMap& aIndexMap, int aTotalMax, int aNumVarieties); |
|
423 void OptimizeNewLineData(CMLCompDataLineInstOptImpl& aImpl, IndexMap& aIndexMap, vector<char>& aTempBytes, const vector<string>& aOutputOrder, bool aMirrored, int aTotalMax, int aNumVarieties); |
|
424 void OptimizeNewLineCellData(IndexMap& aIndexMap, vector<char>& aTempBytes, TMLCompDataValues& aValues, unsigned int& aNextCell, int aTotalParams, int aNumVarieties, ParamLimitVarieties& aParamLimitVarieties, string cellName, bool aMirrorJustification); |
|
425 void EncodeNewLineCellData(IndexMap& aIndexMap, vector<char>& aTempBytes, vector<string>& aValuesToEncode, unsigned int& aNextCell, int aTotalMax, bool aOptimizeVarieties, bool aOptimizeCalcs); |
|
426 |
|
427 bool HasApi(const string& aName); |
|
428 CCdlTkImplementation& FindImp(const string& aName); |
|
429 CMLCompDataInstOptImpl* FindSimilarImpl(const CMLCompDataInstOptImpls& aImpls, const CCdlTkImplementation& aImpl); |
|
430 string DefinitionString(int aByteCodeIndex, const string& aApiName); |
|
431 bool CheckByteCodeIndexInRange(int aByteCodeIndex); |
|
432 |
|
433 void SetGenericFunc(CMLCompDataInstOptImpl& aImpl, SCompDataImplFunc::TFuncType aType); |
|
434 void SetLineFunc(CMLCompDataLineInstOptImpl& aImpl); |
|
435 void SetSubTableFunc(CMLCompDataSubTableInstOptImpl& aImpl); |
|
436 void SetParamLimits(CMLCompDataLineInstOptImpl& aImpl); |
|
437 |
|
438 void ValidateRequiredParams(string aApiName, CCdlTkApiParams& aParams, bool aOption, bool aColumn, bool aRow); |
|
439 void CountApiParams(CCdlTkImplementation& aApi, int& aParams); |
|
440 SCompDataImplFunc& AddImplFunc(SCompDataImplFunc::TFuncType aType); |
|
441 SCompDataImplFunc& AddImplFunc(SCompDataImplFunc::TFuncType aType, CCdlTkApiParams& aParams); |
|
442 |
|
443 void SetGenericAPI(SCompDataImplFunc::TFuncType aType, const string& aName); |
|
444 void SetExtraCpp(const string& aFirstInstanceName); |
|
445 void OutputStats(); |
|
446 |
|
447 void AddTableToInstance(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub, int aTableNum); |
|
448 void UpdateTables(TMLCompDataTable& aTable); |
|
449 void AddTableParamLimitsImpl(const string& aApiName, int aByteCodeIndex, SCompDataImplFunc::TFuncType aType, bool aNeedsOptions); |
|
450 void UpdateTableParamLimitsImpl(const string& aApiName, int aByteCodeIndex); |
|
451 void AddTableLimitsImpl(const string& aApiName, TMLCompDataTable::TMLCompDataSubTable& aSubTable); |
|
452 void AddTableLimitsImplDefn(TMLCompDataTable::TMLCompDataSubTable& aSubTable, CCdlTkImplementation& aImpl); |
|
453 void AddTableImpl(const string& aApiName, TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub); |
|
454 void AddParamLimits(TMLCompDataLine& aLine, bool aNeedsOptions); |
|
455 void UpdateParamLimits(const string& apiName); |
|
456 void SetDummyTableData(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSubTable, CMLCompDataInstOptImpl& aImpl); |
|
457 void UpdateTableData(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSubTable, CMLCompDataInstOptImpl& aImpl); |
|
458 void EncodeValue(vector<char>& aBytes, string aValue); |
|
459 void EncodeValue(vector<char>& aBytes, int aValue); |
|
460 void EncodeParentRelativeValue(vector<char>& aBytes, int aValue); |
|
461 void MirrorParamName(string& aParamName); |
|
462 |
|
463 private: |
|
464 MLCompDataCdlInstanceOpt& iInstances; |
|
465 TMLCompData* iLayout; |
|
466 string iName; |
|
467 string iZoomName; |
|
468 CCdlTkInterface& iInterface; |
|
469 CCdlTkInstance* iInstance; // not owned |
|
470 CMLCompDataInstOptImpls iImpls; |
|
471 CMLCompDataInstOptImpls iTableImpls; |
|
472 typedef vector<SCompDataImplFunc*> CImplFuncs; |
|
473 CImplFuncs iFuncs; |
|
474 int iZoomLevel; |
|
475 bool iAllParams; |
|
476 int iBaseOffset; // offset from the start of the main data table to the start of this instance's data |
|
477 }; |
|
478 |
|
479 CMLCompDataInstOpt::CMLCompDataInstOpt(MLCompDataCdlInstanceOpt& aInstances, TMLCompData* aLayout, const string& aInstName, const string& aZoomName, int aZoomLevel, bool aAllParams, bool aNonCompleteInstance) |
|
480 : |
|
481 iInstances(aInstances), |
|
482 iLayout(aLayout), |
|
483 iName(aInstName), |
|
484 iZoomName(aZoomName), |
|
485 iZoomLevel(aZoomLevel), |
|
486 iInterface(iInstances.Interface()), |
|
487 iAllParams(aAllParams), |
|
488 iBaseOffset(0) |
|
489 { |
|
490 string zoomInstName = aInstName; |
|
491 if(aZoomName.length() > 0) |
|
492 zoomInstName += "_" + aZoomName; |
|
493 |
|
494 iInstance = new CCdlTkInstance(iInterface); |
|
495 iInstance->SetName(zoomInstName); |
|
496 |
|
497 CCdlTkImplementations& impl = iInstance->Impl(); |
|
498 for (CCdlTkImplementations::iterator pImpl = impl.begin(); pImpl != impl.end(); ++pImpl) |
|
499 { |
|
500 const CCdlTkInterface& iface = (*pImpl)->Instance().Interface(); |
|
501 const CCdlTkApi& api = (*pImpl)->Api(); |
|
502 if(aLayout->iIsBaseInstance) |
|
503 { |
|
504 // for a base instance, need to set a default implementation |
|
505 // even for missing data |
|
506 (*pImpl)->SetDefinition(CdlTkUtil::ShortToHexString(0) + ",\t// " + KDefinitionNotDefined); |
|
507 |
|
508 // preliminary implementation of "blank" implementation. cdl engine searches to ensure that |
|
509 // all implementations are not NULL. So this will satisfy that test. However, if any of the |
|
510 // methods are called, there will be an access violation, which will cause a panic |
|
511 // this will be a successful guide to implementers not to call the API when the wrong layout |
|
512 // pack is installed. |
|
513 string definition = "(" + iface.NamespaceName() + "::" + api.PointerType() + ")((void*)4), // LAYOUT NOT DEFINED FOR THIS INSTANCE"; |
|
514 (*pImpl)->SetPointerReference(definition); |
|
515 } |
|
516 else if(aNonCompleteInstance) |
|
517 { |
|
518 // for a base instance, need to set a default implementation |
|
519 // even for missing data |
|
520 (*pImpl)->SetDefinition(CdlTkUtil::ShortToHexString(0) + ",\t// " + KDefinitionNotDefined); |
|
521 |
|
522 // but we need the pointer to be null so that CdlEngine falls through the layer below |
|
523 string definition = "0, // " + iface.NamespaceName() + "::" + api.PointerType(); |
|
524 (*pImpl)->SetPointerReference(definition); |
|
525 } |
|
526 else |
|
527 { |
|
528 // Initially set definition that will not compile in the resulting code. |
|
529 // This will alert the programmer to missing layout data. |
|
530 (*pImpl)->SetDefinition(KDefinitionNotSet); |
|
531 } |
|
532 } |
|
533 } |
|
534 |
|
535 CMLCompDataInstOpt::~CMLCompDataInstOpt() |
|
536 { |
|
537 delete iInstance; |
|
538 for (CMLCompDataInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl) |
|
539 delete *pImpl; |
|
540 for (pImpl = iTableImpls.begin(); pImpl != iTableImpls.end(); ++pImpl) |
|
541 delete *pImpl; |
|
542 } |
|
543 |
|
544 void CMLCompDataInstOpt::Process(const string& aFirstInstName) |
|
545 { |
|
546 iLayout->Compile(); |
|
547 |
|
548 for (TMLCompData::iterator pTab = iLayout->begin(); pTab != iLayout->end(); ++pTab) |
|
549 { |
|
550 ProcessLines(**pTab); |
|
551 } |
|
552 |
|
553 for (pTab = iLayout->begin(); pTab != iLayout->end(); ++pTab) |
|
554 { |
|
555 ProcessTables(**pTab); |
|
556 } |
|
557 |
|
558 // update the base offset to include all the data added, including reserving space for the tables |
|
559 UpdateBaseOffset(); |
|
560 |
|
561 // with the correct base offset, the definitions can be updated |
|
562 UpdateLineImpls(); |
|
563 |
|
564 for (pTab = iLayout->begin(); pTab != iLayout->end(); ++pTab) |
|
565 { |
|
566 // now that the rest of the data is stable, we can add the tables at the end |
|
567 UpdateTables(**pTab); |
|
568 } |
|
569 |
|
570 SetGenericAPI(SCompDataImplFunc::EGenericComponentType, KFuncGetComponentTypeById); |
|
571 SetGenericAPI(SCompDataImplFunc::EGenericParamLimits, KFuncGetParamLimitsById); |
|
572 SetGenericAPI(SCompDataImplFunc::EGenericWindowComponent, KFuncGetWindowComponentById); |
|
573 SetGenericAPI(SCompDataImplFunc::EGenericTextComponent, KFuncGetTextComponentById); |
|
574 |
|
575 SetExtraCpp(aFirstInstName); |
|
576 OutputStats(); |
|
577 } |
|
578 |
|
579 void CMLCompDataInstOpt::WriteInstance() |
|
580 { |
|
581 CCdlTkWriteInstance writer(*iInstance); |
|
582 writer.Process(); |
|
583 } |
|
584 |
|
585 void CMLCompDataInstOpt::ProcessLines(TMLCompDataTable& aTable) |
|
586 { |
|
587 for (TMLCompDataTable::iterator pLine = aTable.begin(); pLine != aTable.end(); ++pLine) |
|
588 { |
|
589 ProcessLine(**pLine); |
|
590 } |
|
591 } |
|
592 |
|
593 void CMLCompDataInstOpt::ProcessTables(TMLCompDataTable& aTable) |
|
594 { |
|
595 int line = 0; |
|
596 for (TMLCompDataTable::iterator pLine = aTable.begin(); pLine != aTable.end(); ++pLine) |
|
597 { |
|
598 for (TMLCompDataTable::TMLCompDataSubTables::const_iterator pSub = aTable.iSubTables.begin(); pSub != aTable.iSubTables.end(); ++pSub) |
|
599 { |
|
600 TMLCompDataTable::TMLCompDataSubTable& sub = **pSub; |
|
601 int last = *(sub.rbegin()); |
|
602 if(line == last) |
|
603 AddTableToInstance(aTable, sub, 0); |
|
604 } |
|
605 line++; |
|
606 } |
|
607 } |
|
608 |
|
609 void CMLCompDataInstOpt::ProcessLine(TMLCompDataLine& aLine) |
|
610 { |
|
611 string apiName = MLCompDataToCdl::LineApiName(aLine); |
|
612 if (!HasApi(apiName)) |
|
613 return; |
|
614 |
|
615 ProcessLineApi(aLine, FindImp(apiName)); |
|
616 } |
|
617 |
|
618 void CMLCompDataInstOpt::ProcessLineApi(TMLCompDataLine& aLine, CCdlTkImplementation& aImpl) |
|
619 { |
|
620 string lineName = MLCompDataToCdl::LineApiName(aLine); |
|
621 |
|
622 CMLCompDataLineInstOptImpl* newImpl = new CMLCompDataLineInstOptImpl(&aLine, &aImpl); |
|
623 iImpls.push_back(newImpl); |
|
624 |
|
625 // always set the new line data |
|
626 SetNewLineData(*newImpl); |
|
627 |
|
628 // if we can find the new line data in the aggregated data, point to that instead |
|
629 int foundIndex = iInstances.FindSimilarBytes(newImpl, iBaseOffset); |
|
630 if(foundIndex >= 0) |
|
631 { |
|
632 newImpl->iByteCodeIndex = foundIndex; |
|
633 newImpl->iIsRedirectedToExactCopy = true; |
|
634 } |
|
635 else |
|
636 { |
|
637 iInstances.AddImpl(newImpl); |
|
638 } |
|
639 |
|
640 SetLineFunc(*newImpl); |
|
641 |
|
642 // only add parameter limits if the line is not simple |
|
643 // and we must add the param limits after the actual impl, so that we can find it! |
|
644 bool needsParamLimits = aLine.NeedsOptions() || aLine.NeedsCols() || aLine.NeedsRows(); |
|
645 if(needsParamLimits) |
|
646 { |
|
647 AddParamLimits(aLine, aLine.NeedsOptions()); |
|
648 } |
|
649 } |
|
650 |
|
651 void CMLCompDataInstOpt::UpdateBaseOffset() |
|
652 { |
|
653 // have to account for this instance's tables |
|
654 int tablesSize(0); |
|
655 for(CMLCompDataInstOptImpls::iterator pTableImpl = iTableImpls.begin(); pTableImpl != iTableImpls.end(); ++pTableImpl) |
|
656 { |
|
657 CMLCompDataInstOptImpl* impl = *pTableImpl; |
|
658 tablesSize += impl->iBytes.size(); |
|
659 } |
|
660 |
|
661 int origByteStreamSize = iInstances.ByteStreamSize() + tablesSize; |
|
662 |
|
663 // repeat until base offset stabilizes |
|
664 iBaseOffset = max(0, origByteStreamSize - KAddressableBytecodedData); |
|
665 int newBaseOffset = iBaseOffset; |
|
666 int byteCodeSizeDelta(0); |
|
667 do |
|
668 { |
|
669 iBaseOffset = newBaseOffset; |
|
670 for(CMLCompDataInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl) |
|
671 UpdateLine(**pImpl, byteCodeSizeDelta); |
|
672 newBaseOffset = max(0, origByteStreamSize + byteCodeSizeDelta - KAddressableBytecodedData); |
|
673 } |
|
674 while(iBaseOffset != newBaseOffset); |
|
675 } |
|
676 |
|
677 void CMLCompDataInstOpt::UpdateLine(CMLCompDataInstOptImpl& aImpl, int& aByteCodeSizeDelta) |
|
678 { |
|
679 if(aImpl.iIsRedirectedToExactCopy && aImpl.iByteCodeIndex < iBaseOffset) |
|
680 { |
|
681 // when we encoded the impls, we found a match in an area which now |
|
682 // turns out to be before the base offset (i.e. outside the addressable range). |
|
683 |
|
684 // first of all check in case we've already made another copy close by |
|
685 int foundIndex = iInstances.FindSimilarBytes(&aImpl, iBaseOffset); |
|
686 if(foundIndex >= 0) |
|
687 { |
|
688 aImpl.iByteCodeIndex = foundIndex; |
|
689 } |
|
690 else |
|
691 { |
|
692 // add its bytecodes to the end |
|
693 aImpl.iIsRedirectedToExactCopy = false; |
|
694 iInstances.AddImpl(&aImpl); |
|
695 aByteCodeSizeDelta += aImpl.iBytes.size(); |
|
696 } |
|
697 } |
|
698 } |
|
699 |
|
700 |
|
701 void CMLCompDataInstOpt::UpdateLineImpls() |
|
702 { |
|
703 for(CMLCompDataInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl) |
|
704 UpdateLineImplDefn(**pImpl); |
|
705 } |
|
706 |
|
707 void CMLCompDataInstOpt::UpdateLineImplDefn(CMLCompDataInstOptImpl& aImpl) |
|
708 { |
|
709 if(!CheckByteCodeIndexInRange(aImpl.iByteCodeIndex)) |
|
710 throw GeneralErr(aImpl.iName + " in interface " + iInterface.FileName()); |
|
711 // the base offset has been updated, so all definitions must be refreshed |
|
712 int adjustedIndex = aImpl.iByteCodeIndex - iBaseOffset; |
|
713 aImpl.iImpl->SetDefinition(DefinitionString(aImpl.iByteCodeIndex, aImpl.iName)); |
|
714 UpdateParamLimits(aImpl.iName); |
|
715 } |
|
716 |
|
717 void CMLCompDataInstOpt::UpdateTables(TMLCompDataTable& aTable) |
|
718 { |
|
719 // regenerate the byte code indices, in case they have changed |
|
720 int line = 0; |
|
721 for (TMLCompDataTable::iterator pLine = aTable.begin(); pLine != aTable.end(); ++pLine) |
|
722 { |
|
723 for (TMLCompDataTable::TMLCompDataSubTables::const_iterator pSub = aTable.iSubTables.begin(); pSub != aTable.iSubTables.end(); ++pSub) |
|
724 { |
|
725 TMLCompDataTable::TMLCompDataSubTable& sub = **pSub; |
|
726 int last = *(sub.rbegin()); |
|
727 if(line == last) |
|
728 { |
|
729 string tableName = MLCompDataToCdl::SubTableApiName(sub); |
|
730 CMLCompDataInstOptImpl* impl = FindSimilarImpl(iTableImpls, FindImp(tableName)); |
|
731 UpdateTableInstance(aTable, sub, impl); |
|
732 } |
|
733 } |
|
734 line++; |
|
735 } |
|
736 } |
|
737 |
|
738 void CMLCompDataInstOpt::SetNewLineData(CMLCompDataLineInstOptImpl& aImpl) |
|
739 { |
|
740 aImpl.iBytes.clear(); |
|
741 |
|
742 TMLCompDataLine& line = *aImpl.iLine; |
|
743 aImpl.iComment = string("for line: "); |
|
744 aImpl.iName = MLCompDataToCdl::LineApiName(line); |
|
745 |
|
746 // handle mirroring order |
|
747 bool mirrored = false; |
|
748 if(line.iParentTable) // we know top table can't be mirrored |
|
749 mirrored = line.iParentTable->iTables->iCanBeMirror; |
|
750 const string* outputOrder = mirrored ? |
|
751 KCompDataGraphicOutputOrderMirrored : KCompDataGraphicOutputOrder; |
|
752 int outputSize = KCompDataGraphicOutputOrderSize; |
|
753 if (line.iType == TMLCompDataLine::ETextComponent) |
|
754 { |
|
755 outputOrder = mirrored ? |
|
756 KCompDataTextOutputOrderMirrored : KCompDataTextOutputOrder; |
|
757 outputSize = KCompDataTextOutputOrderSize; |
|
758 } |
|
759 vector<string> cellOrder(outputOrder, outputOrder + outputSize); |
|
760 |
|
761 // we are currently storing variety as max allowed value, but it's a zero based index |
|
762 int numVarieties = line.MaxVariety() + 1; |
|
763 |
|
764 // we will be storing all of the rows and cols, even if the rows and cols limits are lower |
|
765 int totalMaxCols = numVarieties * line.NumCols(); |
|
766 int totalMaxRows = numVarieties * line.NumRows(); |
|
767 int totalMax = totalMaxCols > totalMaxRows ? totalMaxCols : totalMaxRows; |
|
768 |
|
769 // initialize the temporary bytestream, and the index map |
|
770 vector<char> tempBytes; |
|
771 IndexMap indexMap; |
|
772 |
|
773 // fill in the temp byte stream and the index map for each cell |
|
774 OptimizeNewLineData(aImpl, indexMap, tempBytes, cellOrder, mirrored, totalMax, numVarieties); |
|
775 |
|
776 // encode the index map |
|
777 SetNewLineParamData(aImpl, indexMap, totalMax, numVarieties); |
|
778 |
|
779 // finally copy the temp byte stream onto the end of the real encoded byte stream |
|
780 copy(tempBytes.begin(), tempBytes.end(), back_inserter(aImpl.iBytes)); |
|
781 } |
|
782 |
|
783 void CMLCompDataInstOpt::SetNewLineParamData(CMLCompDataLineInstOptImpl& aImpl, IndexMap& aIndexMap, int aTotalMax, int aNumVarieties) |
|
784 { |
|
785 // only set parameter data if the line is not simple |
|
786 TMLCompDataLine& line = *aImpl.iLine; |
|
787 |
|
788 bool needsHeader = line.NeedsOptions() || line.NeedsCols() || line.NeedsRows(); |
|
789 |
|
790 int typeBitfield = line.iType << 1; |
|
791 if(needsHeader) |
|
792 { |
|
793 typeBitfield |= 1; |
|
794 } |
|
795 |
|
796 aImpl.iBytes.push_back(typeBitfield); |
|
797 |
|
798 if(needsHeader) |
|
799 { |
|
800 // we can just dump the number of varieties, this will be used by the limits API |
|
801 // and we can also them to calculate value indices within a cell when decoding |
|
802 aImpl.iBytes.push_back(aNumVarieties); |
|
803 } |
|
804 |
|
805 // count the number of cells that are complex |
|
806 char numMultiValues = aIndexMap.size(); |
|
807 if(needsHeader) |
|
808 { |
|
809 aImpl.iBytes.push_back(numMultiValues); |
|
810 } |
|
811 else |
|
812 { |
|
813 // we didn't think we needed a header, so there should be no complex cells! |
|
814 if (numMultiValues > 0) |
|
815 throw GeneralErr("complex cells detected in simple line"); |
|
816 } |
|
817 |
|
818 // for each complex cell, encode the bitfield and the count |
|
819 for(IndexMap::iterator pIndex = aIndexMap.begin(); pIndex != aIndexMap.end(); ++pIndex) |
|
820 { |
|
821 int count = pIndex->first; |
|
822 int index = pIndex->second; |
|
823 EncodeValue(aImpl.iBytes, index); |
|
824 EncodeValue(aImpl.iBytes, count); |
|
825 } |
|
826 } |
|
827 |
|
828 void CMLCompDataInstOpt::OptimizeNewLineData( |
|
829 CMLCompDataLineInstOptImpl& aImpl, |
|
830 IndexMap& aIndexMap, |
|
831 vector<char>& aTempBytes, |
|
832 const vector<string>& aOutputOrder, |
|
833 bool aMirrored, |
|
834 int aTotalMax, |
|
835 int aNumVarieties) |
|
836 { |
|
837 vector<ParamLimitVarieties> paramLimits; |
|
838 TMLCompDataLine& line = *aImpl.iLine; |
|
839 |
|
840 // start by extracting the row and column data. |
|
841 // we can optimize the stored format along with the rest of the data |
|
842 // so no need to optimize it yet |
|
843 for(int cell = 0; cell < 2; cell++) |
|
844 { |
|
845 string cellName = aOutputOrder[cell]; |
|
846 ParamLimitVarieties nextLimits; |
|
847 TMLCompDataValues& values = line[cellName]; |
|
848 for(int varietyIndex = 0; varietyIndex < aNumVarieties; varietyIndex++) |
|
849 { |
|
850 TMLCompDataZoomLevels& zoomLevels = values[varietyIndex]; |
|
851 TMLCompDataCalcs* calcs = &(zoomLevels[iZoomLevel]); |
|
852 if(!calcs->size()) |
|
853 calcs = &(zoomLevels[EAknUiZoomNormal]); |
|
854 int value = CdlTkUtil::ParseInt((*calcs)[0]); |
|
855 nextLimits.push_back(value); |
|
856 } |
|
857 paramLimits.push_back(nextLimits); |
|
858 } |
|
859 |
|
860 // calculate the number of values |
|
861 bool needsHeader = line.NeedsOptions() || line.NeedsCols() || line.NeedsRows(); |
|
862 unsigned int nextCellFlag = 1; // bit flag for the next cell, note it can get bigger than a char |
|
863 for (cell = 0; cell < aOutputOrder.size(); cell++) |
|
864 { |
|
865 string cellName = aOutputOrder[cell]; |
|
866 TMLCompDataValues::TCompDataCellType type = TMLCompDataValues::Type(cellName); |
|
867 if(!needsHeader && type == TMLCompDataValues::ECellTypeParamLimit) |
|
868 { |
|
869 // if we don't need header, then don't output the param limits values |
|
870 // although we'll still use them internally |
|
871 continue; |
|
872 } |
|
873 |
|
874 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. |
|
875 TMLCompDataValues& values = line[cellName]; |
|
876 int numValues = 0; |
|
877 if(type == TMLCompDataValues::ECellTypeCol || type == TMLCompDataValues::ECellTypeRow) |
|
878 { |
|
879 ParamLimitVarieties& nextLimits = paramLimits[paramLimitsIndex]; |
|
880 numValues = std::accumulate(nextLimits.begin(), nextLimits.end(), 0); |
|
881 } |
|
882 else |
|
883 { |
|
884 numValues = aNumVarieties; |
|
885 } |
|
886 |
|
887 bool mirrorJustification = (aMirrored && cellName == KCellNameJustification); |
|
888 OptimizeNewLineCellData(aIndexMap, aTempBytes, values, nextCellFlag, numValues, aNumVarieties, paramLimits[paramLimitsIndex], cellName, mirrorJustification); |
|
889 } |
|
890 } |
|
891 |
|
892 void CMLCompDataInstOpt::OptimizeNewLineCellData( |
|
893 IndexMap& aIndexMap, |
|
894 vector<char>& aTempBytes, |
|
895 TMLCompDataValues& aValues, |
|
896 unsigned int& aNextCell, |
|
897 int aTotalParams, |
|
898 int aNumVarieties, |
|
899 CMLCompDataInstOpt::ParamLimitVarieties& aParamLimitVarieties, |
|
900 string cellName, |
|
901 bool aMirrorJustification) |
|
902 { |
|
903 // build up the values for each variety |
|
904 // if the valid values for each variety are the same, then we can store them once only |
|
905 // in which case there will be as many values as the variety with the largest number of values |
|
906 vector<string> optimizedValues; |
|
907 |
|
908 // also build up the found valid values in case we can't optimize |
|
909 vector<string> foundValues; |
|
910 |
|
911 bool optimizeVarieties = true; |
|
912 bool optimizeCalcs = true; |
|
913 int numCalcs = 0; |
|
914 int* largestParamLimitPtr = max_element(aParamLimitVarieties.begin(), aParamLimitVarieties.end()); |
|
915 int largestParamLimit = largestParamLimitPtr != aParamLimitVarieties.end() ? *largestParamLimitPtr : 0; |
|
916 |
|
917 // in the case of there being no calcs at all, we don't want to be optimizing, |
|
918 // in order to avoid wasted flags. |
|
919 if(largestParamLimit == 1) |
|
920 optimizeCalcs = false; |
|
921 |
|
922 TMLCompDataValues::TCompDataCellType type = TMLCompDataValues::Type(cellName); |
|
923 bool isColRow = (type == TMLCompDataValues::ECellTypeCol || type == TMLCompDataValues::ECellTypeRow); |
|
924 |
|
925 // only go up to the max variety, as any data past that may be from a spurious merged instance |
|
926 for(int varietyIndex = 0; varietyIndex < aNumVarieties; varietyIndex++) |
|
927 { |
|
928 TMLCompDataZoomLevels& zoomLevels = aValues[varietyIndex]; |
|
929 TMLCompDataCalcs* calcs = &(zoomLevels[iZoomLevel]); |
|
930 if(!calcs->size()) |
|
931 calcs = &(zoomLevels[EAknUiZoomNormal]); |
|
932 numCalcs = calcs->size(); |
|
933 string value; |
|
934 vector<string> foundCalcs; |
|
935 int paramLimit = aParamLimitVarieties[varietyIndex]; |
|
936 if(numCalcs == 0) |
|
937 { |
|
938 if(varietyIndex == 0) |
|
939 optimizedValues.push_back(value); |
|
940 if(varietyIndex > 0 && !(optimizedValues[0].empty())) |
|
941 optimizeVarieties = false; |
|
942 foundCalcs.push_back(value); |
|
943 } |
|
944 else |
|
945 { |
|
946 for(int index = 0; index < numCalcs; index++) |
|
947 { |
|
948 bool needToCheckIndexValidity = !isColRow || (index < paramLimit); |
|
949 value = (*calcs)[index]; |
|
950 value = aMirrorJustification ? TMLCompDataValues::MirrorJustificationValue(value) : value; |
|
951 |
|
952 if(index >= optimizedValues.size() && index < largestParamLimit) // index is zero based, size is quantity |
|
953 { |
|
954 // store the first valid value for a given index that we find. |
|
955 // note that this will pick up additional values in subsequent varieties |
|
956 optimizedValues.push_back(value); |
|
957 } |
|
958 else if(needToCheckIndexValidity && value != optimizedValues[index]) |
|
959 { |
|
960 // so if it doesn't match, we can't optimize |
|
961 optimizeVarieties = false; |
|
962 } |
|
963 |
|
964 // collect the valid found values as we go, in case we aren't able to optimize |
|
965 if(needToCheckIndexValidity) |
|
966 { |
|
967 foundCalcs.push_back(value); |
|
968 } |
|
969 } |
|
970 } |
|
971 if(isColRow) |
|
972 { |
|
973 int found = foundCalcs.size(); |
|
974 if(!found) |
|
975 { |
|
976 foundCalcs.push_back(string()); |
|
977 found++; |
|
978 } |
|
979 if(found > 1) |
|
980 { |
|
981 optimizeCalcs = false; |
|
982 } |
|
983 } |
|
984 else |
|
985 { |
|
986 optimizeCalcs = false; |
|
987 } |
|
988 copy(foundCalcs.begin(), foundCalcs.end(), back_inserter(foundValues)); |
|
989 } |
|
990 |
|
991 if(optimizeVarieties && isColRow) |
|
992 { |
|
993 // now that we know the optimized values, fill missing values by repeating the last one. |
|
994 // but if we're optimizing the calcs, then we don't want to expand them after all |
|
995 if(!optimizeCalcs) |
|
996 { |
|
997 int optimal = optimizedValues.size(); |
|
998 string value = optimal > 0 ? optimizedValues[optimal-1] : string(); |
|
999 for(; optimal < largestParamLimit; optimal++) |
|
1000 { |
|
1001 optimizedValues.push_back(value); |
|
1002 } |
|
1003 } |
|
1004 } |
|
1005 |
|
1006 if(optimizeVarieties && aNumVarieties == 1) |
|
1007 { |
|
1008 optimizeVarieties = false; |
|
1009 } |
|
1010 |
|
1011 vector<string>& valuesToEncode = optimizeVarieties ? optimizedValues : foundValues; |
|
1012 EncodeNewLineCellData(aIndexMap, aTempBytes, valuesToEncode, aNextCell, aTotalParams, optimizeVarieties, optimizeCalcs); |
|
1013 } |
|
1014 |
|
1015 void CMLCompDataInstOpt::EncodeNewLineCellData( |
|
1016 IndexMap& aIndexMap, |
|
1017 vector<char>& aTempBytes, |
|
1018 vector<string>& aValuesToEncode, |
|
1019 unsigned int& aNextCell, |
|
1020 int aTotalMax, |
|
1021 bool aOptimizeVarieties, |
|
1022 bool aOptimizeCalcs) |
|
1023 { |
|
1024 // encode the actual data into the temporary bytestream |
|
1025 int numOptimizedVals = aValuesToEncode.size(); |
|
1026 if(numOptimizedVals > 0) |
|
1027 { |
|
1028 for(vector<string>::iterator pString = aValuesToEncode.begin(); pString != aValuesToEncode.end(); ++pString) |
|
1029 { |
|
1030 EncodeValue(aTempBytes, *pString); |
|
1031 } |
|
1032 } |
|
1033 else |
|
1034 { |
|
1035 EncodeValue(aTempBytes, ""); |
|
1036 } |
|
1037 |
|
1038 if(numOptimizedVals > aTotalMax) |
|
1039 throw GeneralErr("bad index in indexMap"); |
|
1040 |
|
1041 // if there is only one value stored, we can make a further optimization |
|
1042 // as we know that all values must be the same, however they are stored |
|
1043 // so in that case, don't store an index map entry |
|
1044 if(numOptimizedVals > 1) |
|
1045 { |
|
1046 // update the index map, |
|
1047 // put the flags at the right hand side, to avoid it becoming multi-byte in general |
|
1048 int optimizeVarietiesMask = (aOptimizeVarieties ? 1 : 0); |
|
1049 int optimizeCalcsMask = (aOptimizeCalcs ? 1 : 0) << 1; |
|
1050 int numValsMask = (numOptimizedVals) << 2; |
|
1051 int indexField = (numValsMask | optimizeCalcsMask | optimizeVarietiesMask); |
|
1052 aIndexMap[indexField] |= aNextCell; |
|
1053 } |
|
1054 aNextCell = aNextCell << 1; |
|
1055 } |
|
1056 |
|
1057 void CMLCompDataInstOpt::CountApiParams(CCdlTkImplementation& aApi, int& aParams) |
|
1058 { |
|
1059 aParams = 0; |
|
1060 const CCdlTkApiParams& params = aApi.Api().AsFunc().Params(); |
|
1061 for (CCdlTkApiParams::const_iterator pParam = params.begin(); pParam != params.end(); ++pParam) |
|
1062 { |
|
1063 if (pParam->Type() == KTypeInt) // is it a cell index parameter |
|
1064 aParams++; |
|
1065 } |
|
1066 } |
|
1067 |
|
1068 void CMLCompDataInstOpt::ValidateRequiredParams(string aApiName, CCdlTkApiParams& aParams, bool aOption, bool aColumn, bool aRow) |
|
1069 { |
|
1070 // check that data matches api |
|
1071 bool matches = true; |
|
1072 matches &= ((aOption) == (aParams.FindByName(KParamOptionIndex) != aParams.end())); |
|
1073 matches &= ((aColumn) == (aParams.FindByName(KParamColIndex) != aParams.end())); |
|
1074 matches &= ((aRow) == (aParams.FindByName(KParamRowIndex) != aParams.end())); |
|
1075 if(!matches) |
|
1076 throw CdlTkAssert(string("layout data does not match CDL API : ") + aApiName); |
|
1077 } |
|
1078 |
|
1079 void CMLCompDataInstOpt::SetGenericFunc(CMLCompDataInstOptImpl& aImpl, SCompDataImplFunc::TFuncType aType) |
|
1080 { |
|
1081 CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(aImpl.iImpl->Api().AsFunc()); |
|
1082 CCdlTkApiParams& params = api.Params(); |
|
1083 |
|
1084 SCompDataImplFunc& func = AddImplFunc(aType, params); |
|
1085 aImpl.iImpl->SetPointerReference(func.iPtrRef); |
|
1086 } |
|
1087 |
|
1088 void CMLCompDataInstOpt::SetLineFunc(CMLCompDataLineInstOptImpl& aImpl) |
|
1089 { |
|
1090 SCompDataImplFunc::TFuncType type = SCompDataImplFunc::EWindowLine; |
|
1091 if (aImpl.iLine->iType == TMLCompDataLine::ETextComponent) |
|
1092 { |
|
1093 type = SCompDataImplFunc::ETextLine; |
|
1094 } |
|
1095 string name = aImpl.iImpl->Name(); |
|
1096 |
|
1097 // look up the api to see whether we need the params |
|
1098 CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(aImpl.iImpl->Api().AsFunc()); |
|
1099 CCdlTkApiParams& params = api.Params(); |
|
1100 ValidateRequiredParams( |
|
1101 name, |
|
1102 params, |
|
1103 iAllParams || aImpl.iLine->NeedsOptions(), |
|
1104 iAllParams || aImpl.iLine->NeedsCols(), |
|
1105 iAllParams || aImpl.iLine->NeedsRows()); |
|
1106 SCompDataImplFunc& func = AddImplFunc(type, params); |
|
1107 aImpl.iImpl->SetPointerReference(func.iPtrRef); |
|
1108 } |
|
1109 |
|
1110 void CMLCompDataInstOpt::SetSubTableFunc(CMLCompDataSubTableInstOptImpl& aImpl) |
|
1111 { |
|
1112 TMLCompDataTable& table = *(aImpl.iTable); |
|
1113 TMLCompDataTable::TMLCompDataSubTable& subTable = *(aImpl.iSubTable); |
|
1114 TMLCompDataLine& line= *(table[subTable[0]]); |
|
1115 |
|
1116 SCompDataImplFunc::TFuncType type = SCompDataImplFunc::EWindowTable; |
|
1117 |
|
1118 if (line.iType == TMLCompDataLine::ETextComponent) |
|
1119 { |
|
1120 type = SCompDataImplFunc::ETextTable; |
|
1121 } |
|
1122 string name = aImpl.iImpl->Name(); |
|
1123 |
|
1124 CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(aImpl.iImpl->Api().AsFunc()); |
|
1125 CCdlTkApiParams& params = api.Params(); |
|
1126 |
|
1127 string debug; |
|
1128 for(CCdlTkApiParams::iterator pParam = params.begin(); pParam != params.end(); ++pParam) |
|
1129 debug = pParam->Name(); |
|
1130 |
|
1131 ValidateRequiredParams( |
|
1132 name, |
|
1133 params, |
|
1134 iAllParams || subTable.iNeedsOption, |
|
1135 iAllParams || subTable.iNeedsCol, |
|
1136 iAllParams || subTable.iNeedsRow); |
|
1137 SCompDataImplFunc& func = AddImplFunc(type, params); |
|
1138 aImpl.iImpl->SetPointerReference(func.iPtrRef); |
|
1139 } |
|
1140 |
|
1141 bool CMLCompDataInstOpt::HasApi(const string& aName) |
|
1142 { |
|
1143 return iInterface.ApiList().Find(aName) != 0; |
|
1144 } |
|
1145 |
|
1146 CCdlTkImplementation& CMLCompDataInstOpt::FindImp(const string& aName) |
|
1147 { |
|
1148 CCdlTkImplementation* impl = iInstance->Impl().Find(aName); |
|
1149 if (!impl) |
|
1150 throw NotFoundErr(aName + " in interface " + iInterface.FileName()); |
|
1151 return *impl; |
|
1152 } |
|
1153 |
|
1154 CMLCompDataInstOptImpl* CMLCompDataInstOpt::FindSimilarImpl(const CMLCompDataInstOptImpls& aImpls, const CCdlTkImplementation& aImpl) |
|
1155 { |
|
1156 for (CMLCompDataInstOptImpls::const_iterator pOptImpl = aImpls.begin(); pOptImpl != aImpls.end(); ++pOptImpl) |
|
1157 { |
|
1158 CMLCompDataInstOptImpl* optImpl = *pOptImpl; |
|
1159 if (optImpl->iImpl == &aImpl) |
|
1160 return optImpl; |
|
1161 } |
|
1162 return NULL; |
|
1163 } |
|
1164 |
|
1165 string CMLCompDataInstOpt::DefinitionString(int aByteCodeIndex, const string& aApiName) |
|
1166 { |
|
1167 int adjustedIndex = aByteCodeIndex - iBaseOffset; |
|
1168 return CdlTkUtil::ShortToHexString(adjustedIndex) + ",\t// (" + CdlTkUtil::IntToHexString(aByteCodeIndex) + ") " + aApiName; |
|
1169 } |
|
1170 |
|
1171 bool CMLCompDataInstOpt::CheckByteCodeIndexInRange(int aByteCodeIndex) |
|
1172 { |
|
1173 int adjustedIndex = aByteCodeIndex - iBaseOffset; |
|
1174 if(adjustedIndex > KAddressableBytecodedData) |
|
1175 { |
|
1176 cerr << "Error: Out of range: index = " << CdlTkUtil::IntToHexString(aByteCodeIndex) << ", "; |
|
1177 cerr << "baseOffset = " << CdlTkUtil::IntToHexString(iBaseOffset ) << endl; |
|
1178 return false; |
|
1179 } |
|
1180 return true; |
|
1181 } |
|
1182 |
|
1183 SCompDataImplFunc& CMLCompDataInstOpt::AddImplFunc(SCompDataImplFunc::TFuncType aType) |
|
1184 { |
|
1185 CCdlTkApiParams params; |
|
1186 return AddImplFunc(aType, params); |
|
1187 } |
|
1188 |
|
1189 SCompDataImplFunc& CMLCompDataInstOpt::AddImplFunc(SCompDataImplFunc::TFuncType aType, CCdlTkApiParams& aParams) |
|
1190 { |
|
1191 for (CImplFuncs::iterator pFunc = iFuncs.begin(); pFunc != iFuncs.end(); ++pFunc) |
|
1192 { |
|
1193 SCompDataImplFunc& func = **pFunc; |
|
1194 if(func.IsSimilar(aType, aParams)) |
|
1195 return func; |
|
1196 } |
|
1197 |
|
1198 int count = gTheFuncs.size(); |
|
1199 for (int ii=0; ii<count; ii++) |
|
1200 { |
|
1201 SCompDataImplFunc* func = &gTheFuncs[ii]; |
|
1202 if(func->IsSimilar(aType, aParams)) |
|
1203 { |
|
1204 iFuncs.push_back(func); |
|
1205 return *func; |
|
1206 } |
|
1207 } |
|
1208 |
|
1209 throw NotFoundErr("implementation function"); |
|
1210 return gTheFuncs[0]; |
|
1211 } |
|
1212 |
|
1213 void CMLCompDataInstOpt::SetGenericAPI(SCompDataImplFunc::TFuncType aType, const string& aName) |
|
1214 { |
|
1215 CCdlTkImplementation* impl = iInstance->Impl().Find(aName); |
|
1216 |
|
1217 // CMLCompDataInstOptImpl(CCdlTkImplementation* aImpl); |
|
1218 CMLCompDataInstOptImpl* newImpl = new CMLCompDataInstOptImpl(impl); |
|
1219 iImpls.push_back(newImpl); |
|
1220 |
|
1221 SetGenericFunc(*newImpl, aType); |
|
1222 newImpl->iImpl->SetDefinition(CdlTkUtil::ShortToHexString(0) + ","); // no specific data for generic apis |
|
1223 } |
|
1224 |
|
1225 // The following strings and the SetExtraCpp() function build the gross structure of |
|
1226 // the C++ customisation instance. |
|
1227 // So far, the implementations are actually just 16-bit values, typically indexes into |
|
1228 // the data lookup table. These need to be turned into an array by adding declarations |
|
1229 // and brackets to the first and last implementations. Extra support functions are also |
|
1230 // added. |
|
1231 // extern string KScalableExtraCpp; |
|
1232 string KScalableExtraCpp = "\ |
|
1233 #include \"aknlayout2scalabledecode.h\"\n\ |
|
1234 namespace $INTERFACE_NS { extern const TUint8 KByteCodedData_$FIRSTINSTANCENAME[]; }\n"; |
|
1235 |
|
1236 //extern string KScalableInitialCpp; |
|
1237 string KScalableInitialCpp ="\ |
|
1238 extern const TUint16 KDataLookup[$INTERFACE_NS::E_TApiId_TableSize];\n\ |
|
1239 const SCompDataImplData KImplData = { KDataLookup, $INTERFACE_NS::KByteCodedData_$FIRSTINSTANCENAME + $THISINSTANCEBASEOFFSET };\n\ |
|
1240 \n\ |
|
1241 $FUNCTIONS\ |
|
1242 \n\ |
|
1243 const TUint16 KDataLookup[$INTERFACE_NS::E_TApiId_TableSize] =\n\ |
|
1244 \t{\n"; |
|
1245 void CMLCompDataInstOpt::SetExtraCpp(const string& aFirstInstName) |
|
1246 { |
|
1247 // The "extra cpp" field is written to the top of the cpp file. |
|
1248 CdlTkUtil::CReplaceSet cppSet; |
|
1249 cppSet.Add("$INTERFACE_NS", iInterface.NamespaceName()); |
|
1250 cppSet.Add("$FIRSTINSTANCENAME", aFirstInstName); |
|
1251 cppSet.Add("$THISINSTANCEBASEOFFSET", CdlTkUtil::IntToHexString(iBaseOffset)); // base offset can be longer than 16 bits |
|
1252 iInstance->SetExtraCpp(CdlTkUtil::MultiReplace(cppSet, KScalableExtraCpp)); |
|
1253 |
|
1254 // add headers & fwd declarations |
|
1255 string init = CdlTkUtil::MultiReplace(cppSet, KScalableInitialCpp); |
|
1256 |
|
1257 // add decode functions |
|
1258 string functions; |
|
1259 for (CImplFuncs::iterator pFunc = iFuncs.begin(); pFunc != iFuncs.end(); ++pFunc) |
|
1260 { |
|
1261 CdlTkUtil::AppendString(functions, (*pFunc)->iDefn); |
|
1262 CdlTkUtil::AppendString(functions, "\n"); |
|
1263 } |
|
1264 init = CdlTkUtil::Replace("$FUNCTIONS", functions, init); |
|
1265 CCdlTkImplementation& first = **(iInstance->Impl().begin()); |
|
1266 first.SetDefinition(init + first.Definition()); |
|
1267 |
|
1268 // add end of data table |
|
1269 CCdlTkImplementation& last = **(iInstance->Impl().end() - 1); |
|
1270 last.SetDefinition(last.Definition() + "\n};"); |
|
1271 } |
|
1272 |
|
1273 void CMLCompDataInstOpt::OutputStats() |
|
1274 { |
|
1275 int optimizedBytes(0); |
|
1276 int unoptimizedBytes(0); |
|
1277 for (CMLCompDataInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl) |
|
1278 { |
|
1279 int size = (*pImpl)->iBytes.size(); |
|
1280 if ((*pImpl)->iIsRedirectedToExactCopy) |
|
1281 optimizedBytes += size; |
|
1282 else |
|
1283 unoptimizedBytes += size; |
|
1284 } |
|
1285 for (CMLCompDataInstOptImpls::iterator pTableImpl = iTableImpls.begin(); pTableImpl != iTableImpls.end(); ++pTableImpl) |
|
1286 { |
|
1287 int size = (*pTableImpl)->iBytes.size(); |
|
1288 if ((*pTableImpl)->iIsRedirectedToExactCopy) |
|
1289 optimizedBytes += size; |
|
1290 else |
|
1291 unoptimizedBytes += size; |
|
1292 } |
|
1293 |
|
1294 float compress = (100.0 * (float)unoptimizedBytes) / ((float)optimizedBytes + (float)unoptimizedBytes); |
|
1295 int compressInt = (int)(compress + 0.5); |
|
1296 cout << "instance " << iName << " compressed to " << compressInt << "% of total (" << unoptimizedBytes<< " / " << optimizedBytes + unoptimizedBytes << ")" << endl; |
|
1297 } |
|
1298 |
|
1299 void CMLCompDataInstOpt::AddTableToInstance(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub, int /*aTableNum*/) |
|
1300 { |
|
1301 string tableName = MLCompDataToCdl::SubTableApiName(aSub); |
|
1302 string tableParamLimitsName = tableName + KFuncParamLimitsSuffix; |
|
1303 |
|
1304 if (HasApi(tableName)) |
|
1305 { |
|
1306 CCdlTkImplementation& impl = FindImp(tableName); |
|
1307 CMLCompDataSubTableInstOptImpl* newImpl = new CMLCompDataSubTableInstOptImpl(&aTable, &aSub, &impl); |
|
1308 iTableImpls.push_back(newImpl); |
|
1309 |
|
1310 SetDummyTableData(aTable, aSub, *newImpl); |
|
1311 SetSubTableFunc(*newImpl); |
|
1312 |
|
1313 AddTableLimitsImpl(tableName + KFuncLimitsSuffix, aSub); |
|
1314 if (HasApi(tableParamLimitsName)) |
|
1315 { |
|
1316 AddTableParamLimitsImpl(tableParamLimitsName, newImpl->iByteCodeIndex, SCompDataImplFunc::ETableParamLimits, aSub.iNeedsOption); |
|
1317 } |
|
1318 AddTableImpl(tableName, aTable, aSub); |
|
1319 } |
|
1320 } |
|
1321 |
|
1322 void CMLCompDataInstOpt::UpdateTableInstance(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub, CMLCompDataInstOptImpl* aImpl) |
|
1323 { |
|
1324 string tableName = MLCompDataToCdl::SubTableApiName(aSub); |
|
1325 UpdateTableData(aTable, aSub, *aImpl); |
|
1326 |
|
1327 // if we can find the new table data in the aggregated data, point to that instead |
|
1328 int foundIndex = iInstances.FindSimilarBytes(aImpl, iBaseOffset); |
|
1329 if(foundIndex >= 0) |
|
1330 { |
|
1331 if(foundIndex != aImpl->iByteCodeIndex) |
|
1332 { |
|
1333 aImpl->iByteCodeIndex = foundIndex; |
|
1334 aImpl->iIsRedirectedToExactCopy = true; |
|
1335 } |
|
1336 else |
|
1337 { |
|
1338 cerr << "Error: found same table already in bytestream: " << aImpl->iName << endl; |
|
1339 } |
|
1340 } |
|
1341 |
|
1342 // now we've generated the bytecode, it will be added to the bytestream |
|
1343 iInstances.AddImpl(aImpl); |
|
1344 aImpl->iImpl->SetDefinition(DefinitionString(aImpl->iByteCodeIndex, tableName)); |
|
1345 |
|
1346 string tableParamLimitsName = tableName + KFuncParamLimitsSuffix; |
|
1347 if (HasApi(tableParamLimitsName)) |
|
1348 { |
|
1349 UpdateTableParamLimitsImpl(tableParamLimitsName, aImpl->iByteCodeIndex); |
|
1350 } |
|
1351 } |
|
1352 |
|
1353 void CMLCompDataInstOpt::AddTableParamLimitsImpl(const string& aApiName, int aByteCodeIndex, SCompDataImplFunc::TFuncType aType, bool aNeedsOptions) |
|
1354 { |
|
1355 CCdlTkImplementation& impl = FindImp(aApiName); |
|
1356 |
|
1357 // look up the api to see whether we need a variety params |
|
1358 CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(impl.Api().AsFunc()); |
|
1359 CCdlTkApiParams& params = api.Params(); |
|
1360 ValidateRequiredParams( |
|
1361 aApiName, |
|
1362 params, |
|
1363 iAllParams || aNeedsOptions, |
|
1364 false, |
|
1365 false); |
|
1366 |
|
1367 SCompDataImplFunc& func = AddImplFunc(aType, params); |
|
1368 |
|
1369 impl.SetDefinition(DefinitionString(aByteCodeIndex, aApiName)); |
|
1370 impl.SetPointerReference(func.iPtrRef); |
|
1371 } |
|
1372 |
|
1373 void CMLCompDataInstOpt::UpdateTableParamLimitsImpl(const string& aApiName, int aByteCodeIndex) |
|
1374 { |
|
1375 CCdlTkImplementation& paramLimitsImpl = FindImp(aApiName); |
|
1376 paramLimitsImpl.SetDefinition(DefinitionString(aByteCodeIndex, aApiName)); |
|
1377 } |
|
1378 |
|
1379 void CMLCompDataInstOpt::AddTableLimitsImpl(const string& aApiName, TMLCompDataTable::TMLCompDataSubTable& aSubTable) |
|
1380 { |
|
1381 CCdlTkImplementation& impl = FindImp(aApiName); |
|
1382 AddTableLimitsImplDefn(aSubTable, impl); |
|
1383 impl.SetPointerReference(AddImplFunc(SCompDataImplFunc::ETableLimits).iPtrRef); |
|
1384 } |
|
1385 |
|
1386 void CMLCompDataInstOpt::AddTableLimitsImplDefn(TMLCompDataTable::TMLCompDataSubTable& aSubTable, CCdlTkImplementation& aImpl) |
|
1387 { |
|
1388 // code up table limits as a pair of byte values, the first byte is the first table |
|
1389 // index, the second is the last table index. |
|
1390 int first = (*aSubTable.begin()) & 0xff; |
|
1391 int last = (*aSubTable.rbegin()) & 0xff; |
|
1392 |
|
1393 // however, we want these APIs to be accessed zero based, so have to calculate the offset. |
|
1394 int offset = last - first; |
|
1395 |
|
1396 int v = offset; |
|
1397 if ( v > KAddressableBytecodedData ) |
|
1398 { |
|
1399 std::cerr << "*** ERROR: Value " << v << "(unknown/3) of out range" << std::endl; |
|
1400 } |
|
1401 |
|
1402 aImpl.SetDefinition(CdlTkUtil::ShortToHexString(offset) + KComma); |
|
1403 } |
|
1404 |
|
1405 void CMLCompDataInstOpt::AddTableImpl(const string& aApiName, TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSub) |
|
1406 { |
|
1407 CCdlTkImplementation& impl = FindImp(aApiName); |
|
1408 |
|
1409 int nParams; |
|
1410 CountApiParams(impl, nParams); |
|
1411 nParams--; // don't count the aLineIndex param |
|
1412 SCompDataImplFunc::TFuncType type = SCompDataImplFunc::EWindowTable; |
|
1413 TMLCompDataLine::TComponentType subTableType = aTable[aSub[0]]->iType; |
|
1414 switch(subTableType) |
|
1415 { |
|
1416 case TMLCompDataLine::ETextComponent: |
|
1417 { |
|
1418 type = SCompDataImplFunc::ETextTable; |
|
1419 break; |
|
1420 } |
|
1421 } |
|
1422 CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(impl.Api().AsFunc()); |
|
1423 CCdlTkApiParams& params = api.Params(); |
|
1424 ValidateRequiredParams( |
|
1425 aApiName, |
|
1426 params, |
|
1427 iAllParams || aSub.iNeedsOption, |
|
1428 iAllParams || aSub.iNeedsCol, |
|
1429 iAllParams || aSub.iNeedsRow); |
|
1430 SCompDataImplFunc& func = AddImplFunc(type, params); |
|
1431 } |
|
1432 |
|
1433 void CMLCompDataInstOpt::AddParamLimits(TMLCompDataLine& aLine, bool aNeedsOptions) |
|
1434 { |
|
1435 string apiName = MLCompDataToCdl::LineApiName(aLine) ; |
|
1436 string paramLimitsApiName = apiName + KFuncParamLimitsSuffix; |
|
1437 if (!HasApi(paramLimitsApiName)) |
|
1438 throw NotFoundErr(paramLimitsApiName + " in interface " + iInterface.FileName()); |
|
1439 |
|
1440 CCdlTkImplementation& paramLimitsImpl = FindImp(paramLimitsApiName); |
|
1441 |
|
1442 // look up the api to see whether we need a variety params |
|
1443 CCdlTkFunctionApi& api = const_cast<CCdlTkFunctionApi&>(paramLimitsImpl.Api().AsFunc()); |
|
1444 CCdlTkApiParams& params = api.Params(); |
|
1445 ValidateRequiredParams( |
|
1446 paramLimitsApiName, |
|
1447 params, |
|
1448 iAllParams || aNeedsOptions, |
|
1449 false, |
|
1450 false); |
|
1451 |
|
1452 SCompDataImplFunc& func = AddImplFunc(SCompDataImplFunc::ELineParamLimits, params); |
|
1453 paramLimitsImpl.SetPointerReference(func.iPtrRef); |
|
1454 |
|
1455 UpdateParamLimits(apiName); |
|
1456 } |
|
1457 |
|
1458 void CMLCompDataInstOpt::UpdateParamLimits(const string& apiName) |
|
1459 { |
|
1460 string paramLimitsApiName = apiName + KFuncParamLimitsSuffix; |
|
1461 if (HasApi(paramLimitsApiName)) |
|
1462 { |
|
1463 CCdlTkImplementation& paramLimitsImpl = FindImp(paramLimitsApiName); |
|
1464 CMLCompDataInstOptImpl* actualOptImpl = FindSimilarImpl(iImpls, FindImp(apiName)); |
|
1465 |
|
1466 paramLimitsImpl.SetDefinition(DefinitionString(actualOptImpl->iByteCodeIndex, paramLimitsApiName)); |
|
1467 } |
|
1468 } |
|
1469 |
|
1470 void CMLCompDataInstOpt::SetDummyTableData(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSubTable, CMLCompDataInstOptImpl& aImpl) |
|
1471 { |
|
1472 aImpl.iBytes.clear(); |
|
1473 aImpl.iComment = string("for table: "); |
|
1474 aImpl.iName = MLCompDataToCdl::SubTableApiName(aSubTable); |
|
1475 EncodeValue(aImpl.iBytes, aSubTable.size()); |
|
1476 for(TMLCompDataTable::TMLCompDataSubTable::iterator pLineId = aSubTable.begin(); pLineId != aSubTable.end(); ++pLineId) |
|
1477 { |
|
1478 aImpl.iBytes.push_back(0); |
|
1479 aImpl.iBytes.push_back(0); |
|
1480 } |
|
1481 } |
|
1482 |
|
1483 void CMLCompDataInstOpt::UpdateTableData(TMLCompDataTable& aTable, TMLCompDataTable::TMLCompDataSubTable& aSubTable, CMLCompDataInstOptImpl& aImpl) |
|
1484 { |
|
1485 aImpl.iBytes.clear(); |
|
1486 EncodeValue(aImpl.iBytes, aSubTable.size()); |
|
1487 for(TMLCompDataTable::TMLCompDataSubTable::iterator pLineId = aSubTable.begin(); pLineId != aSubTable.end(); ++pLineId) |
|
1488 { |
|
1489 // figure out the offset to the next line of the table |
|
1490 TMLCompDataLine& line = *(aTable[*pLineId]); |
|
1491 string lineName = MLCompDataToCdl::LineApiName(line) ; |
|
1492 CMLCompDataInstOptImpl* lineImpl = FindSimilarImpl(iImpls, FindImp(lineName)); |
|
1493 |
|
1494 // we must store the adjusted index, ie relative to the base offset, in the definition, as that will be used |
|
1495 // in the main output, so check that the offset is in range, which it should be if we've updated the lines |
|
1496 // correctly |
|
1497 if(!CheckByteCodeIndexInRange(lineImpl->iByteCodeIndex)) |
|
1498 throw GeneralErr(aImpl.iName + " in interface " + iInterface.FileName()); |
|
1499 int adjustedIndex = lineImpl->iByteCodeIndex - iBaseOffset; |
|
1500 |
|
1501 // make an assumption that data fits into 16 bits, and don't encode the lookups |
|
1502 // that way, when decoding, we can jump forward by 2 bytes * index without decoding |
|
1503 // all the values (since they're not encoded, we know they're all the same size) |
|
1504 aImpl.iBytes.push_back((adjustedIndex & 0xff00) >> 8); |
|
1505 aImpl.iBytes.push_back(adjustedIndex); |
|
1506 } |
|
1507 } |
|
1508 |
|
1509 struct SIdToInt |
|
1510 { |
|
1511 int iInt; |
|
1512 char* iStr; |
|
1513 }; |
|
1514 |
|
1515 #include <avkon.hrh> |
|
1516 extern SIdToInt gIdToIntTable[]; |
|
1517 extern const int gIdToIntTableCount; |
|
1518 extern void TranslateValue(string& aValue); |
|
1519 |
|
1520 void CMLCompDataInstOpt::EncodeValue(vector<char>& aBytes, string aValue) |
|
1521 { |
|
1522 int pos = 0; |
|
1523 TranslateValue(aValue); |
|
1524 if (aValue == "") |
|
1525 { |
|
1526 aBytes.push_back(KByteEmpty); |
|
1527 } |
|
1528 else |
|
1529 { |
|
1530 pos = aValue.find_first_of(KParentRelativeMarker); |
|
1531 if(pos != string::npos) |
|
1532 { |
|
1533 if (pos != 0) |
|
1534 throw CdlTkAssert(string("arithmetic parser not good enough : ") + aValue); |
|
1535 int val = CdlTkUtil::ParseInt(aValue.substr(1)); |
|
1536 EncodeParentRelativeValue(aBytes, val); |
|
1537 } |
|
1538 else |
|
1539 { |
|
1540 int val = CdlTkUtil::ParseInt(aValue); |
|
1541 EncodeValue(aBytes, val); |
|
1542 } |
|
1543 } |
|
1544 } |
|
1545 |
|
1546 void CMLCompDataInstOpt::EncodeValue(vector<char>& aBytes, int aValue) |
|
1547 { |
|
1548 if (0 <= aValue && aValue <= KMaxSingleByteValue) |
|
1549 { |
|
1550 aBytes.push_back(aValue); |
|
1551 } |
|
1552 else if (aValue > KMaxSingleByteValue && aValue <= KMaxDoubleByteValue) |
|
1553 { |
|
1554 aBytes.push_back(KByteWord); |
|
1555 aBytes.push_back((aValue & 0xff00) >> 8); |
|
1556 aBytes.push_back(aValue); |
|
1557 } |
|
1558 else |
|
1559 { |
|
1560 aBytes.push_back(KByteLong); |
|
1561 aBytes.push_back((aValue & 0xff000000) >> 24); |
|
1562 aBytes.push_back((aValue & 0x00ff0000) >> 16); |
|
1563 aBytes.push_back((aValue & 0x0000ff00) >> 8); |
|
1564 aBytes.push_back(aValue); |
|
1565 } |
|
1566 } |
|
1567 |
|
1568 void CMLCompDataInstOpt::EncodeParentRelativeValue(vector<char>& aBytes, int aValue) |
|
1569 { |
|
1570 if (KMinSingleByteParentRelativeValue <= aValue && aValue <= KMaxSingleByteParentRelativeValue) |
|
1571 { |
|
1572 aBytes.push_back(KByteP1); |
|
1573 aBytes.push_back(aValue); |
|
1574 } |
|
1575 else |
|
1576 { |
|
1577 aBytes.push_back(KByteP2); |
|
1578 aBytes.push_back((aValue & 0xff00) >> 8); |
|
1579 aBytes.push_back(aValue); |
|
1580 } |
|
1581 } |
|
1582 |
|
1583 void CMLCompDataInstOpt::MirrorParamName(string& aParamName) |
|
1584 { |
|
1585 if (aParamName == KParamNameL) |
|
1586 aParamName = KParamNameR; |
|
1587 else if (aParamName == KParamNameR) |
|
1588 aParamName = KParamNameL; |
|
1589 } |
|
1590 |
|
1591 // |
|
1592 // MLCompDataCdlInstanceOpt |
|
1593 // |
|
1594 |
|
1595 MLCompDataCdlInstanceOpt::InstStruct::InstStruct(string aInstName, TMLCompData* aInst, TMLAttributes* aAttribs) |
|
1596 : |
|
1597 iInstName(aInstName), |
|
1598 iInst(aInst), |
|
1599 iAttribs(aAttribs) |
|
1600 { |
|
1601 } |
|
1602 |
|
1603 MLCompDataCdlInstanceOpt::InstList::~InstList() |
|
1604 { |
|
1605 for(InstList::iterator pNext = begin(); pNext != end(); ++pNext) |
|
1606 { |
|
1607 delete pNext->iInst; |
|
1608 } |
|
1609 } |
|
1610 |
|
1611 void MLCompDataCdlInstanceOpt::ProcessSeparators(vector<string>& args, vector<int>& aSeparators) |
|
1612 { |
|
1613 for(int arg = 3; arg < args.size(); arg++) |
|
1614 { |
|
1615 if(args[arg] == "-a") |
|
1616 aSeparators.push_back(arg); |
|
1617 } |
|
1618 |
|
1619 aSeparators.push_back(args.size()); // add an implicit last separator |
|
1620 if(aSeparators.size() < 2) |
|
1621 throw MLCompDataCdlInstanceOptArgsErr(); |
|
1622 |
|
1623 // check that the distance between each separator is not a multiple of 2 |
|
1624 // i.e. counting the steps between aSeparators ( sep -> xml -> inst -> sep) is 3 steps |
|
1625 // i.e. counting the steps between aSeparators ( sep -> xml -> inst -> xml -> inst -> sep) is 5 steps |
|
1626 for(int sep = 0; sep < aSeparators.size() - 1; sep++) |
|
1627 { |
|
1628 int delta = aSeparators[sep+1] - aSeparators[sep]; |
|
1629 if (delta%2 == 0) |
|
1630 throw MLCompDataCdlInstanceOptArgsErr(); |
|
1631 } |
|
1632 } |
|
1633 |
|
1634 bool MLCompDataCdlInstanceOpt::CheckForUsedInstances( |
|
1635 const CInstanceList& aUsedList, |
|
1636 const CZoomLevelNames& aZoomLevelNames, |
|
1637 const vector<string>& aArgs, |
|
1638 const vector<int>& aSeparators, |
|
1639 int aSepIndex) |
|
1640 { |
|
1641 bool ok = false; |
|
1642 for(CZoomLevelNames::const_iterator pZoomLevel = aZoomLevelNames.begin(); pZoomLevel != aZoomLevelNames.end(); ++pZoomLevel) |
|
1643 { |
|
1644 // check if any of these instances are used - skip this if none are used |
|
1645 for (int arg = aSeparators[aSepIndex] + 1; arg < aSeparators[aSepIndex+1]; arg += 2) |
|
1646 { |
|
1647 string instName = aArgs[arg+1] + "_" + pZoomLevel->second; |
|
1648 if (aUsedList.IsInstanceOk(instName)) |
|
1649 ok = true; |
|
1650 } |
|
1651 } |
|
1652 return ok; |
|
1653 } |
|
1654 |
|
1655 void MLCompDataCdlInstanceOpt::ParseInstances(const vector<string>& aArgs, const vector<int>& aSeparators, int aSepIndex, MLCompDataCdlInstanceOpt::InstList& aInstList) |
|
1656 { |
|
1657 for (int arg = aSeparators[aSepIndex] + 1; arg < aSeparators[aSepIndex+1]; arg += 2) |
|
1658 { |
|
1659 string layoutName = aArgs[arg]; |
|
1660 string instName = aArgs[arg+1]; |
|
1661 string attribsName = CdlTkUtil::Replace(KCompDataFileNameSuffix, KAttributesFileNameSuffix, layoutName); |
|
1662 |
|
1663 auto_ptr<TMLCompDataParseLayout> layoutParse = TMLCompDataParseLayout::Parse(layoutName); |
|
1664 auto_ptr<TMLCompData> layout(layoutParse.get()); |
|
1665 layoutParse.release(); |
|
1666 |
|
1667 auto_ptr<TMLAttributesParse> attribsParse = TMLAttributesParse::Parse(attribsName); |
|
1668 auto_ptr<TMLAttributes> attribs(attribsParse.get()); |
|
1669 attribsParse.release(); |
|
1670 |
|
1671 InstStruct instStruct(instName, layout.get(), attribs.get()); |
|
1672 aInstList.push_back(instStruct); |
|
1673 layout.release(); |
|
1674 attribs.release(); |
|
1675 } |
|
1676 } |
|
1677 |
|
1678 void MLCompDataCdlInstanceOpt::MergeLayouts(CInstanceList& aInstUsedList, CZoomLevelNames& aZoomLevelNames, const InstList& aInstances, InstList& aMergedLayouts) |
|
1679 { |
|
1680 // start with the non-mirrored instances |
|
1681 for(int count = 0; count < 2; count++) |
|
1682 { |
|
1683 bool isMirrored = (count != 0); |
|
1684 // first iterate through the layouts, we will generate one instance per layout |
|
1685 for(int instIndex = 0; instIndex < aInstances.size(); instIndex++) |
|
1686 { |
|
1687 const InstStruct& instStruct = aInstances[instIndex]; |
|
1688 string targetInstName = instStruct.iInstName; |
|
1689 TMLCompData& targetLayout = *(instStruct.iInst); |
|
1690 TMLAttributes& targetAttribs = *(instStruct.iAttribs); |
|
1691 |
|
1692 bool required = false; |
|
1693 for(CZoomLevelNames::const_iterator pZoomLevel = aZoomLevelNames.begin(); pZoomLevel != aZoomLevelNames.end(); ++pZoomLevel) |
|
1694 { |
|
1695 string zoomInstName = targetInstName + "_" + pZoomLevel->second; |
|
1696 if(aInstUsedList.IsInstanceOk(zoomInstName)) |
|
1697 required = true; |
|
1698 } |
|
1699 |
|
1700 // if this target is not required, or if it's the wrong sort of mirrored |
|
1701 // for this iteration, skip it. |
|
1702 if(targetLayout.iCanBeMirror != isMirrored || !required) |
|
1703 continue; |
|
1704 |
|
1705 // for each instance, we must merge all the other layouts |
|
1706 auto_ptr<TMLCompData> mergedLayout(new TMLCompData()); |
|
1707 auto_ptr<TMLAttributes> mergedAttribs(new TMLAttributes()); |
|
1708 for (InstList::const_iterator pInst2 = aInstances.begin(); pInst2 != aInstances.end(); ++pInst2) |
|
1709 { |
|
1710 // merge in all the others |
|
1711 const InstStruct& instStruct2 = *pInst2; |
|
1712 if(instStruct2.iInstName != targetInstName) |
|
1713 { |
|
1714 TMLCompData& nextLayout = *(instStruct2.iInst); |
|
1715 TMLAttributes& nextAttribs = *(instStruct2.iAttribs); |
|
1716 // but only if it's the right kind of mirrored |
|
1717 if(nextLayout.iCanBeMirror == isMirrored) |
|
1718 { |
|
1719 mergedLayout->Merge(nextLayout); |
|
1720 mergedAttribs->Merge(nextAttribs); |
|
1721 } |
|
1722 } |
|
1723 } |
|
1724 // then end up merging in the one we want |
|
1725 mergedLayout->Merge(targetLayout); |
|
1726 mergedAttribs->Merge(targetAttribs); |
|
1727 if(isMirrored) |
|
1728 { |
|
1729 // If we have just processed a mirrored layout, |
|
1730 // we need to do a mirror merge with the corresponding one. |
|
1731 // The instances are ordered as on the command line, |
|
1732 // but the merged layouts are grouped toghether, unmirrored first. |
|
1733 // So to convert between the two indexes: 1 -> 0, and 3 -> 1 |
|
1734 int unMirroredMergedLayoutIndex = (instIndex / 2); |
|
1735 InstStruct& unMirroredInst = aMergedLayouts[unMirroredMergedLayoutIndex]; // this works as we have already added the unmirrored instance to the vector |
|
1736 TMLCompData& unMirroredLayout = *(unMirroredInst.iInst); |
|
1737 TMLAttributes& unMirroredAttribs = *(unMirroredInst.iAttribs); |
|
1738 mergedLayout->Merge(unMirroredLayout); |
|
1739 mergedAttribs->Merge(unMirroredAttribs); |
|
1740 } |
|
1741 |
|
1742 InstStruct mergedInstStruct(targetInstName, mergedLayout.get(), mergedAttribs.get()); |
|
1743 aMergedLayouts.push_back(mergedInstStruct); |
|
1744 mergedLayout.release(); |
|
1745 mergedAttribs.release(); |
|
1746 } |
|
1747 } |
|
1748 } |
|
1749 |
|
1750 int MLCompDataCdlInstanceOpt::Process(vector<string>& args) |
|
1751 { |
|
1752 // parse the file containing the used instances list. only instances in this list |
|
1753 // will be generated, even if also mentioned on the command line |
|
1754 CInstanceList instUsedList; |
|
1755 instUsedList.ProcessOptions(args); |
|
1756 |
|
1757 // extract the zoom level names, note that this consumes the argument if present |
|
1758 CZoomLevelNames zoomLevelNames; |
|
1759 zoomLevelNames.ProcessOptions(args); |
|
1760 |
|
1761 // check that we have an acceptable number of arguments |
|
1762 int extraArgs = args.size() - 3; |
|
1763 if (extraArgs < 0) |
|
1764 throw MLCompDataCdlInstanceOptArgsErr(); |
|
1765 |
|
1766 // check for optional flags |
|
1767 int arg = 2; |
|
1768 bool allParams = false; |
|
1769 if (args[arg] == "-allparams") |
|
1770 { |
|
1771 allParams = true; |
|
1772 arg++; |
|
1773 } |
|
1774 |
|
1775 bool nonCompleteInstance = false; |
|
1776 if(args[arg].substr(0,2) == "-d") |
|
1777 { |
|
1778 arg++; |
|
1779 if (args[arg].size() >= 2) |
|
1780 { |
|
1781 nonCompleteInstance = true; |
|
1782 } |
|
1783 } |
|
1784 |
|
1785 // parse the CDL interface |
|
1786 string cdlName = args[arg]; |
|
1787 CCdlTkCdlFileParser parser(cdlName); |
|
1788 auto_ptr<CCdlTkInterface> iface(parser.LoadAndParse(true)); |
|
1789 MLCompDataCdlInstanceOpt process(*iface); |
|
1790 |
|
1791 // the separators divide the layout instances that are aggregated together |
|
1792 vector<int> separators; |
|
1793 ProcessSeparators(args, separators); |
|
1794 for(int sep = 0; sep < separators.size() - 1; sep++) |
|
1795 { |
|
1796 if(!CheckForUsedInstances(instUsedList, zoomLevelNames, args, separators, sep)) |
|
1797 continue; |
|
1798 // start from after the next separator, and continue until before the next one |
|
1799 InstList instances; |
|
1800 ParseInstances(args, separators, sep, instances); |
|
1801 |
|
1802 InstList mergedLayouts; |
|
1803 MergeLayouts(instUsedList, zoomLevelNames, instances, mergedLayouts); |
|
1804 for(InstList::iterator pMergedLayout = mergedLayouts.begin(); pMergedLayout != mergedLayouts.end(); ) |
|
1805 { |
|
1806 process.AddInst(*pMergedLayout, zoomLevelNames, allParams, nonCompleteInstance); // pass ownership of mergedLayout |
|
1807 pMergedLayout = mergedLayouts.erase(pMergedLayout); |
|
1808 } |
|
1809 } |
|
1810 |
|
1811 process.Process(); |
|
1812 process.WriteInstances(); |
|
1813 return 0; |
|
1814 } |
|
1815 |
|
1816 void MLCompDataCdlInstanceOpt::ShowHelp(ostream& stream) |
|
1817 { |
|
1818 stream << "MLCompCdl2InstO [-i<instanceList>] [-z<zoomList>] [-allparams] [-d<deliveryType>] <interface.cdl> (-a ([-m]<layout.xml> <instanceName>)+ )+" << endl; |
|
1819 stream << " Creates optimised CDL instances containing the layout data." << endl; |
|
1820 stream << " Each -a flag is followed by a collection of xml and instance name pairs." << endl; |
|
1821 stream << " Each collection is aggregated separately." << endl; |
|
1822 stream << " The aggregation of the layout instances must conform to the CDL interface, " << endl; |
|
1823 stream << " but note any missing data in an instance may result in data being returned " << endl; |
|
1824 stream << " from a different instance, although duplicate implementations will be reused " << endl; |
|
1825 stream << " to reduce ROM usage." << endl; |
|
1826 stream << " A -m flag must precede an xml file that contains mirrored layout data." << endl; |
|
1827 stream << " An aggregated collection of layouts must contain interleaved" << endl; |
|
1828 stream << " elaf and the corresponding abrw instances." << endl; |
|
1829 stream << " If -i<instanceList> is specified, then only instances whose name" << endl; |
|
1830 stream << " appears in the file <instanceList> will be processed." << endl; |
|
1831 stream << " If -z<zoomList> is specified, then only instances whose zoom factor" << endl; |
|
1832 stream << " (in the form \"n,string\") appears in the file <zoomList> will be generated." << endl; |
|
1833 stream << " If -allparams is used, all processed APIs will have all available params added, " << endl; |
|
1834 stream << " otherwise only needed params are added." << endl; |
|
1835 stream << " If -d<deliveryType> is supplied with any value, any API that has a missing" << endl; |
|
1836 stream << " implementation will be filled in with NULL, allowing fall-through to an instance" << endl; |
|
1837 stream << " from a lower priority pack." << endl; |
|
1838 } |
|
1839 |
|
1840 MLCompDataCdlInstanceOpt::MLCompDataCdlInstanceOpt(CCdlTkInterface& aInterface) |
|
1841 : |
|
1842 iInterface(aInterface) |
|
1843 { |
|
1844 } |
|
1845 |
|
1846 MLCompDataCdlInstanceOpt::~MLCompDataCdlInstanceOpt() |
|
1847 { |
|
1848 for(CCompDataZoomLevelDatas::iterator pZoomLevel = iZoomLevelDatas.begin(); pZoomLevel != iZoomLevelDatas.end(); ++pZoomLevel) |
|
1849 { |
|
1850 CCompDatas& compDatas = pZoomLevel->second; |
|
1851 for (CCompDatas::iterator pInstOpt = compDatas.begin(); pInstOpt != compDatas.end(); ++pInstOpt) |
|
1852 delete *pInstOpt; |
|
1853 } |
|
1854 for(CCompDataLayouts::iterator pLayout = iLayouts.begin(); pLayout != iLayouts.end(); ++pLayout) |
|
1855 delete *pLayout; |
|
1856 } |
|
1857 |
|
1858 void MLCompDataCdlInstanceOpt::AddInst(const InstStruct& aInstStruct, CZoomLevelNames& aZoomLevelNames, bool aAllParams, bool aNonCompleteInstance) |
|
1859 { |
|
1860 TMLCompData* layout = aInstStruct.iInst; |
|
1861 layout->iAttributes = aInstStruct.iAttribs; // transfer ownership |
|
1862 iLayouts.push_back(aInstStruct.iInst); |
|
1863 for(CZoomLevelNames::iterator pZoomLevel = aZoomLevelNames.begin(); pZoomLevel != aZoomLevelNames.end(); ++pZoomLevel) |
|
1864 { |
|
1865 auto_ptr<CMLCompDataInstOpt> p(new CMLCompDataInstOpt(*this, layout, aInstStruct.iInstName, pZoomLevel->second, pZoomLevel->first, aAllParams, aNonCompleteInstance)); |
|
1866 CCompDatas& compDatas = iZoomLevelDatas[pZoomLevel->first]; |
|
1867 compDatas.push_back(p.get()); |
|
1868 p.release(); |
|
1869 } |
|
1870 } |
|
1871 |
|
1872 void MLCompDataCdlInstanceOpt::Process() |
|
1873 { |
|
1874 for(CCompDataZoomLevelDatas::iterator pZoomLevel = iZoomLevelDatas.begin(); pZoomLevel != iZoomLevelDatas.end(); ++pZoomLevel) |
|
1875 { |
|
1876 CCompDatas& compDatas = pZoomLevel->second; |
|
1877 if(compDatas.size() == 0) |
|
1878 continue; |
|
1879 CMLCompDataInstOpt* firstInstOpt = compDatas[0]; |
|
1880 cout << "processing instances for zoom level: " << firstInstOpt->ZoomName() << endl; |
|
1881 |
|
1882 string firstInstName = firstInstOpt->Name(); |
|
1883 for (CCompDatas::iterator pLayout = compDatas.begin(); pLayout != compDatas.end(); ++pLayout) |
|
1884 (*pLayout)->Process(firstInstName); |
|
1885 } |
|
1886 ProcessCommonImpl(); |
|
1887 } |
|
1888 |
|
1889 void MLCompDataCdlInstanceOpt::WriteInstances() |
|
1890 { |
|
1891 bool found = false; |
|
1892 for(CCompDataZoomLevelDatas::iterator pZoomLevel = iZoomLevelDatas.begin(); pZoomLevel != iZoomLevelDatas.end(); ++pZoomLevel) |
|
1893 { |
|
1894 CCompDatas& compDatas = pZoomLevel->second; |
|
1895 if(!found && compDatas.size() > 0) |
|
1896 { |
|
1897 found = true; |
|
1898 cout << "writing instances ... " << endl; |
|
1899 } |
|
1900 for (CCompDatas::iterator pLayout = compDatas.begin(); pLayout != compDatas.end(); ++pLayout) |
|
1901 (*pLayout)->WriteInstance(); |
|
1902 } |
|
1903 } |
|
1904 |
|
1905 CCdlTkInterface& MLCompDataCdlInstanceOpt::Interface() |
|
1906 { |
|
1907 return iInterface; |
|
1908 } |
|
1909 |
|
1910 const string KCommonImplStart = "\ |
|
1911 #include \"aknlayout2scalabledecode.h\"\n\ |
|
1912 namespace $NAMESPACENAME { extern TUint8 const KByteCodedData_$FIRSTINSTANCENAME[] = {\n"; |
|
1913 |
|
1914 const string KCommonImplImpl = "\ |
|
1915 // $INDEX $COMMENT\n\ |
|
1916 $BYTES\n"; |
|
1917 |
|
1918 void MLCompDataCdlInstanceOpt::ProcessCommonImpl() |
|
1919 { |
|
1920 // use the first instance name of the first zoom level |
|
1921 // it's not entirely accurate but it only needs to disambiguate |
|
1922 CCompDatas& compDatas = iZoomLevelDatas[EAknUiZoomNormal]; |
|
1923 if(compDatas.size() == 0) |
|
1924 return; |
|
1925 CMLCompDataInstOpt* firstInstOpt = compDatas[0]; |
|
1926 |
|
1927 CdlTkUtil::CReplaceSet startImplSet; |
|
1928 startImplSet.Add("$NAMESPACENAME", iInterface.NamespaceName()); |
|
1929 startImplSet.Add("$FIRSTINSTANCENAME", firstInstOpt->Name()); |
|
1930 string bytecode = CdlTkUtil::MultiReplace(startImplSet, KCommonImplStart); |
|
1931 int byteCounter(0); |
|
1932 |
|
1933 for (CMLCompDataInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl) |
|
1934 { |
|
1935 vector<char>& bytes = (*pImpl)->iBytes; |
|
1936 if (!(*pImpl)->iIsRedirectedToExactCopy && bytes.size()) |
|
1937 { |
|
1938 string byteString; |
|
1939 for (vector<char>::iterator pChar = bytes.begin(); pChar != bytes.end(); ++pChar) |
|
1940 { |
|
1941 CdlTkUtil::AppendString(byteString, CdlTkUtil::CharToHexString(*pChar)); |
|
1942 CdlTkUtil::AppendString(byteString, KComma); |
|
1943 } |
|
1944 |
|
1945 // in this case, we want to know the absolute index to help with debugging |
|
1946 int index = (*pImpl)->iByteCodeIndex; |
|
1947 if(byteCounter != index) |
|
1948 { |
|
1949 cerr << "Error: Data table mismatch for " << (*pImpl)->iName; |
|
1950 cerr << ": Bytecode index = " << CdlTkUtil::ShortToHexString(index); |
|
1951 cerr << "; byte counter = " << CdlTkUtil::ShortToHexString(byteCounter) << endl; |
|
1952 throw GeneralErr((*pImpl)->iName + " in interface " + iInterface.FileName()); |
|
1953 } |
|
1954 byteCounter += bytes.size(); |
|
1955 |
|
1956 CdlTkUtil::CReplaceSet implSet; |
|
1957 implSet.Add("$INDEX", CdlTkUtil::IntToHexString(index)); |
|
1958 implSet.Add("$COMMENT", (*pImpl)->iComment + (*pImpl)->iName + " (" + CdlTkUtil::ShortToHexString(bytes.size()) + " bytes)"); |
|
1959 implSet.Add("$BYTES", byteString); |
|
1960 CdlTkUtil::AppendString(bytecode, CdlTkUtil::MultiReplace(implSet, KCommonImplImpl)); |
|
1961 } |
|
1962 } |
|
1963 CdlTkUtil::AppendString(bytecode, "};\n}"); |
|
1964 CCdlTkInstance& firstInst = firstInstOpt->Inst(); |
|
1965 firstInst.SetExtraCpp(bytecode); |
|
1966 } |
|
1967 |
|
1968 int MLCompDataCdlInstanceOpt::FindSimilarBytes(CMLCompDataInstOptImpl* aImpl, int aBaseOffset) |
|
1969 { |
|
1970 int index = -1; |
|
1971 vector<char>::iterator startOfAddressableBlock = iBytesAggregated.begin() + aBaseOffset; |
|
1972 vector<char>::iterator found = std::search( |
|
1973 startOfAddressableBlock, |
|
1974 iBytesAggregated.end(), |
|
1975 aImpl->iBytes.begin(), |
|
1976 aImpl->iBytes.end()); |
|
1977 if(found != iBytesAggregated.end()) |
|
1978 { |
|
1979 index = std::distance(iBytesAggregated.begin(), found); // we return the absolute position |
|
1980 } |
|
1981 return index; |
|
1982 } |
|
1983 |
|
1984 void MLCompDataCdlInstanceOpt::AddImpl(CMLCompDataInstOptImpl* aImpl) |
|
1985 { |
|
1986 if(!aImpl->iIsRedirectedToExactCopy) |
|
1987 { |
|
1988 CMLCompDataInstOptImpls::iterator found = std::find(iImpls.begin(), iImpls.end(), aImpl); |
|
1989 if(found == iImpls.end()) |
|
1990 { |
|
1991 iImpls.push_back(aImpl); |
|
1992 } |
|
1993 else |
|
1994 { |
|
1995 cerr << "Error: " << aImpl->iName << " already added to byte stream" << endl; |
|
1996 throw GeneralErr(aImpl->iName + " in interface " + iInterface.FileName()); |
|
1997 } |
|
1998 if (aImpl->iBytes.size()) |
|
1999 { |
|
2000 aImpl->iByteCodeIndex = iBytesAggregated.size(); |
|
2001 iBytesAggregated.insert( |
|
2002 iBytesAggregated.end(), |
|
2003 aImpl->iBytes.begin(), |
|
2004 aImpl->iBytes.end()); |
|
2005 } |
|
2006 } |
|
2007 } |
|
2008 |
|
2009 int MLCompDataCdlInstanceOpt::ByteStreamSize() const |
|
2010 { |
|
2011 return iBytesAggregated.size(); |
|
2012 } |
|
2013 |
|
2014 // end of file |
|
2015 |
|
2016 |