blob: aa4f1b14b90e2f4831ab80ddb3a59835d543ad22 [file] [log] [blame]
Kevin Rocard93250d12012-07-19 17:48:30 +02001/*
Patrick Benavoli68a91282011-08-31 11:23:23 +02002 * INTEL CONFIDENTIAL
3 * Copyright © 2011 Intel
4 * Corporation All Rights Reserved.
5 *
6 * The source code contained or described herein and all documents related to
7 * the source code ("Material") are owned by Intel Corporation or its suppliers
8 * or licensors. Title to the Material remains with Intel Corporation or its
9 * suppliers and licensors. The Material contains trade secrets and proprietary
10 * and confidential information of Intel or its suppliers and licensors. The
11 * Material is protected by worldwide copyright and trade secret laws and
12 * treaty provisions. No part of the Material may be used, copied, reproduced,
13 * modified, published, uploaded, posted, transmitted, distributed, or
14 * disclosed in any way without Intel’s prior express written permission.
15 *
16 * No license under any patent, copyright, trade secret or other intellectual
17 * property right is granted to or conferred upon you by disclosure or delivery
18 * of the Materials, either expressly, by implication, inducement, estoppel or
19 * otherwise. Any license under such intellectual property rights must be
20 * express and approved by Intel in writing.
21 *
Patrick Benavoli68a91282011-08-31 11:23:23 +020022 * CREATED: 2011-06-01
23 * UPDATED: 2011-07-27
Patrick Benavoli68a91282011-08-31 11:23:23 +020024 */
25#include "Element.h"
26#include <assert.h>
27#include <stdio.h>
28#include <stdarg.h>
Patrick Benavoli2ecf9002011-08-31 11:23:24 +020029#include <sstream>
Patrick Benavoli68a91282011-08-31 11:23:23 +020030#include "XmlElementSerializingContext.h"
31#include "ElementLibrary.h"
32#include "ErrorContext.h"
33
34CElement::CElement(const string& strName) : _strName(strName), _pParent(NULL)
35{
36}
37
38CElement::~CElement()
39{
40 removeChildren();
41}
42
43// Logging
44void CElement::log(const string& strMessage, ...) const
45{
46 char acBuffer[512];
47 va_list listPointer;
48
49 va_start(listPointer, strMessage);
50
51 vsnprintf(acBuffer, sizeof(acBuffer), strMessage.c_str(), listPointer);
52
53 va_end(listPointer);
54
55 doLog(acBuffer);
56}
57
58void CElement::doLog(const string& strLog) const
59{
60 assert(_pParent);
61
62 // Propagate till root
63 _pParent->doLog(strLog);
64}
65
66void CElement::nestLog() const
67{
68 assert(_pParent);
69
70 // Propagate till root
71 _pParent->nestLog();
72}
73
74void CElement::unnestLog() const
75{
76 assert(_pParent);
77
78 // Propagate till root
79 _pParent->unnestLog();
80}
81
82
83void CElement::setDescription(const string& strDescription)
84{
85 _strDescription = strDescription;
86}
87
88const string& CElement::getDescription() const
89{
90 return _strDescription;
91}
92
93bool CElement::childrenAreDynamic() const
94{
95 // By default, children are searched and not created during xml parsing
96 return false;
97}
98
99bool CElement::init(string& strError)
100{
101 uint32_t uiIndex;
102
103 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
104
105 CElement* pElement = _childArray[uiIndex];;
106
107 if (!pElement->init(strError)) {
108
109 return false;
110 }
111 }
112
113 return true;
114}
115
116void CElement::dumpContent(string& strContent, CErrorContext& errorContext, const uint32_t uiDepth) const
117{
118 string strIndent;
119
120 // Level
121 uint32_t uiNbIndents = uiDepth;
122
123 while (uiNbIndents--) {
124
125 strIndent += " ";
126 }
127 // Type
128 strContent += strIndent + "- " + getKind();
129
130 // Name
131 if (!_strName.empty()) {
132
133 strContent += ": " + getName();
134 }
135
136 // Value
137 string strValue;
138 logValue(strValue, errorContext);
139
140 if (!strValue.empty()) {
141
142 strContent += " = " + strValue;
143 }
144
145 strContent += "\n";
146
147 uint32_t uiIndex;
148
149 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
150
151 _childArray[uiIndex]->dumpContent(strContent, errorContext, uiDepth + 1);
152 }
153}
154
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200155// Element properties
156void CElement::showProperties(string& strResult) const
157{
158 strResult = "\n";
159 strResult += "Kind: " + getKind() + "\n";
160}
161
162// Conversion utilities
163string CElement::toString(uint32_t uiValue)
164{
165 ostringstream ostr;
166
167 ostr << uiValue;
168
169 return ostr.str();
170}
171
Guillaume Denneulin95331562012-09-27 15:13:10 +0200172string CElement::toString(uint64_t uiValue)
173{
174 ostringstream ostr;
175
176 ostr << uiValue;
177
178 return ostr.str();
179}
180
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200181string CElement::toString(int32_t iValue)
182{
183 ostringstream ostr;
184
185 ostr << iValue;
186
187 return ostr.str();
188}
189
Patrick Benavoliee65e6d2011-11-20 18:52:24 +0100190string CElement::toString(double dValue)
191{
192 ostringstream ostr;
193
194 ostr << dValue;
195
196 return ostr.str();
197}
198
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200199// Content dumping
Patrick Benavoli68a91282011-08-31 11:23:23 +0200200void CElement::logValue(string& strValue, CErrorContext& errorContext) const
201{
202 (void)strValue;
203 (void)errorContext;
204}
205
206// From IXmlSink
207bool CElement::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
208{
209 // Propagate through children
210 CXmlElement::CChildIterator childIterator(xmlElement);
211
212 // Context
213 CXmlElementSerializingContext& elementSerializingContext = static_cast<CXmlElementSerializingContext&>(serializingContext);
214
215 CXmlElement childElement;
216
217 while (childIterator.next(childElement)) {
218
219 CElement* pChild;
220
221 if (!childrenAreDynamic()) {
222
223 pChild = findChildOfKind(childElement.getType());
224
225 if (!pChild) {
226
Patrick Benavoli065264a2011-11-20 15:46:41 +0100227 elementSerializingContext.setError("Unable to handle XML element: " + childElement.getPath());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200228
229 return false;
230 }
231
232 } else {
233 // Child needs creation
234 pChild = elementSerializingContext.getElementLibrary()->createElement(childElement);
235
236 if (pChild) {
237
238 // Store created child!
239 addChild(pChild);
240 } else {
241
242 elementSerializingContext.setError("Unable to create XML element " + childElement.getPath());
243
244 return false;
245 }
246 }
247
248 // Dig
249 if (!pChild->fromXml(childElement, elementSerializingContext)) {
250
251 return false;
252 }
253 }
254
255 return true;
256}
257
258// From IXmlSource
259void CElement::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
260{
261 // Browse children and propagate
262 uint32_t uiNbChildren = getNbChildren();
263 uint32_t uiChild;
264
265 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
266
267 const CElement* pChild = _childArray[uiChild];
268
269 // Create corresponding child element
270 CXmlElement xmlChildElement;
271
272 xmlElement.createChild(xmlChildElement, pChild->getKind());
273
274 // Set attributes
275 pChild->setXmlNameAttribute(xmlChildElement);
276
277
278 // Propagate
279 pChild->toXml(xmlChildElement, serializingContext);
280 }
281}
282
283void CElement::setXmlNameAttribute(CXmlElement& xmlElement) const
284{
285 // By default, set Name attribute if any
286 string strName = getName();
287
288 if (!strName.empty()) {
289
290 xmlElement.setNameAttribute(strName);
291 }
292}
293
294// Name
295void CElement::setName(const string& strName)
296{
297 _strName = strName;
298}
299
300const string& CElement::getName() const
301{
302 return _strName;
303}
304
305bool CElement::rename(const string& strName, string& strError)
306{
307 // Check for conflict with brotherhood if relevant
308 if (_pParent && _pParent->childrenAreDynamic()) {
309
310 uint32_t uiParentChild;
311 uint32_t uiParentNbChildren = _pParent->getNbChildren();
312
313 for (uiParentChild = 0; uiParentChild < uiParentNbChildren; uiParentChild++) {
314
315 const CElement* pParentChild = _pParent->getChild(uiParentChild);
316
317 if (pParentChild != this && pParentChild->getName() == strName) {
318
319 // Conflict
320 strError = "Name conflicts with brother element";
321
322 return false;
323 }
324 }
325 }
326 // Change name
327 setName(strName);
328
329 return true;
330}
331
332string CElement::getPathName() const
333{
334 if (!_strName.empty()) {
335
336 return _strName;
337 } else {
338
339 return getKind();
340 }
341}
342
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200343// Hierarchy
Patrick Benavoli68a91282011-08-31 11:23:23 +0200344void CElement::addChild(CElement* pChild)
345{
346 _childArray.push_back(pChild);
347
348 pChild->_pParent = this;
349}
350
351CElement* CElement::getChild(uint32_t uiIndex)
352{
353 assert(uiIndex <= _childArray.size());
354
355 return _childArray[uiIndex];
356}
357
358const CElement* CElement::getChild(uint32_t uiIndex) const
359{
360 assert(uiIndex <= _childArray.size());
361
362 return _childArray[uiIndex];
363}
364
365CElement* CElement::getLastChild()
366{
367 uint32_t uiNbChildren = getNbChildren();
368
369 assert(uiNbChildren);
370
371 return _childArray[uiNbChildren - 1];
372}
373
374bool CElement::removeChild(CElement* pChild)
375{
376 ChildArrayIterator it;
377
378 for (it = _childArray.begin(); it != _childArray.end(); ++it) {
379
380 CElement* pElement = *it;
381
382 if (pElement == pChild) {
383
384 _childArray.erase(it);
385
386 return true;
387 }
388 }
389 return false;
390}
391
392void CElement::listChildren(string& strChildList) const
393{
394 strChildList = "\n";
395
396 // Get list of children names
397 uint32_t uiNbChildren = getNbChildren();
398 uint32_t uiChild;
399
400 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
401
402 const CElement* pChild = _childArray[uiChild];
403
404 strChildList += pChild->getName() + "\n";
405 }
406}
407
408string CElement::listQualifiedPaths(bool bDive, uint32_t uiLevel) const
409{
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200410 uint32_t uiNbChildren = getNbChildren();
411 string strResult;
412
413 // Dive Will cause only leaf nodes to be printed
414 if (!bDive || !uiNbChildren) {
415
416 strResult = getQualifiedPath() + "\n";
417 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200418
419 if (bDive || !uiLevel) {
420 // Get list of children paths
Patrick Benavoli68a91282011-08-31 11:23:23 +0200421 uint32_t uiChild;
422
423 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
424
425 const CElement* pChild = _childArray[uiChild];
426
427 strResult += pChild->listQualifiedPaths(bDive, uiLevel + 1);
428 }
429 }
430 return strResult;
431}
432
433void CElement::listChildrenPaths(string& strChildList) const
434{
Patrick Benavoli68a91282011-08-31 11:23:23 +0200435 // Get list of children paths
436 uint32_t uiNbChildren = getNbChildren();
437 uint32_t uiChild;
438
439 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
440
441 const CElement* pChild = _childArray[uiChild];
442
443 strChildList += pChild->getPath() + "\n";
444 }
445}
446
447uint32_t CElement::getNbChildren() const
448{
449 return _childArray.size();
450}
451
452const CElement* CElement::getParent() const
453{
454 return _pParent;
455}
456
457CElement* CElement::getParent()
458{
459 return _pParent;
460}
461
462void CElement::clean()
463{
464 if (childrenAreDynamic()) {
465
466 removeChildren();
467 } else {
468 // Just propagate
469 uint32_t uiIndex;
470
471 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
472
473 _childArray[uiIndex]->clean();
474 }
475 }
476}
477
478void CElement::removeChildren()
479{
480 // Delete in reverse order
481 ChildArrayReverseIterator it;
482
483 for (it = _childArray.rbegin(); it != _childArray.rend(); ++it) {
484
485 delete *it;
486 }
487 _childArray.clear();
488}
489
490const CElement* CElement::findDescendant(CPathNavigator& pathNavigator) const
491{
492 string* pStrChildName = pathNavigator.next();
493
494 if (!pStrChildName) {
495
496 return this;
497 }
498
499 const CElement* pChild = findChild(*pStrChildName);
500
501 if (!pChild) {
502
503 return NULL;
504 }
505
506 return pChild->findDescendant(pathNavigator);
507}
508
509CElement* CElement::findDescendant(CPathNavigator& pathNavigator)
510{
511 string* pStrChildName = pathNavigator.next();
512
513 if (!pStrChildName) {
514
515 return this;
516 }
517
518 CElement* pChild = findChild(*pStrChildName);
519
520 if (!pChild) {
521
522 return NULL;
523 }
524
525 return pChild->findDescendant(pathNavigator);
526}
527
528bool CElement::isDescendantOf(const CElement* pCandidateAscendant) const
529{
530 if (!_pParent) {
531
532 return false;
533 }
534 if (_pParent == pCandidateAscendant) {
535
536 return true;
537 }
538 return _pParent->isDescendantOf(pCandidateAscendant);
539}
540
541CElement* CElement::findAscendantOfKind(const string& strKind)
542{
543 if (!_pParent) {
544
545 return NULL;
546 }
547
548 if (_pParent->getKind() == strKind) {
549
550 return _pParent;
551 }
552 return _pParent->findAscendantOfKind(strKind);
553}
554
555CElement* CElement::findChild(const string& strName)
556{
557 uint32_t uiIndex;
558
559 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
560
561 CElement* pElement = _childArray[uiIndex];
562
563 if (pElement->getPathName() == strName) {
564
565 return pElement;
566 }
567 }
568
569 return NULL;
570}
571
572const CElement* CElement::findChild(const string& strName) const
573{
574 uint32_t uiIndex;
575
576 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
577
578 const CElement* pElement = _childArray[uiIndex];
579
580 if (pElement->getPathName() == strName) {
581
582 return pElement;
583 }
584 }
585
586 return NULL;
587}
588
589CElement* CElement::findChildOfKind(const string& strKind)
590{
591 uint32_t uiIndex;
592
593 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
594
595 CElement* pElement = _childArray[uiIndex];
596
597 if (pElement->getKind() == strKind) {
598
599 return pElement;
600 }
601 }
602
603 return NULL;
604}
605
606const CElement* CElement::findChildOfKind(const string& strKind) const
607{
608 uint32_t uiIndex;
609
610 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
611
612 const CElement* pElement = _childArray[uiIndex];;
613
614 if (pElement->getKind() == strKind) {
615
616 return pElement;
617 }
618 }
619
620 return NULL;
621}
622
623CElement* CElement::getRoot()
624{
625 if (!_pParent) {
626
627 return this;
628 }
629 return _pParent->getRoot();
630}
631
632const CElement* CElement::getRoot() const
633{
634 if (!_pParent) {
635
636 return this;
637 }
638 return _pParent->getRoot();
639}
640
641string CElement::getPath() const
642{
643 // Take out root element from the path
644 if (_pParent && _pParent->_pParent) {
645
646 return _pParent->getPath() + "/" + getPathName();
647 }
648 return "/" + getPathName();
649}
650
651string CElement::getQualifiedPath() const
652{
653 return getPath() + " [" + getKind() + "]";
654}
655
656uint32_t CElement::getDepth() const
657{
658 if (_pParent) {
659
660 return _pParent->getDepth() + 1;
661 }
662
663 return 0;
664}
665
666// Checksum for integrity checks
667uint8_t CElement::computeStructureChecksum() const
668{
669 // Base checksum computation on element kind
670 string strKind = getKind();
671
672 // Get element kind
673 const char* pcData = strKind.c_str();
674
675 // Cumulate
676 uint8_t uiChecksum = 0;
677
678 while (*pcData) {
679
680 uiChecksum += *pcData++;
681 }
682
683 // Propagate
684 uint32_t uiIndex;
685 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
686
687 const CElement* pChild = _childArray[uiIndex];
688
689 uiChecksum += pChild->computeStructureChecksum();
690 }
691
692 return uiChecksum;
693}
694
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200695// Utility to underline
696void CElement::appendTitle(string& strTo, const string& strTitle)
697{
698 strTo += "\n" + strTitle + "\n";
699
700 uint32_t uiLength = strTitle.size();
701
702 while (uiLength--) {
703
Patrick Benavoli1387bda2011-08-31 11:23:24 +0200704 strTo += "=";
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200705 }
706 strTo += "\n";
707}