blob: b68205b4b978d8c0b4b286cd7e4a03cf15320146 [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"
Kevin Rocard7f265822012-12-07 18:51:22 +010026#include "XmlElementSerializingContext.h"
27#include "ElementLibrary.h"
28#include "ErrorContext.h"
Patrick Benavoli68a91282011-08-31 11:23:23 +020029#include <assert.h>
30#include <stdio.h>
31#include <stdarg.h>
Guillaume Denneulin2aab8712013-12-03 14:27:41 +010032#include <stdlib.h>
Patrick Benavoli2ecf9002011-08-31 11:23:24 +020033#include <sstream>
Patrick Benavoli68a91282011-08-31 11:23:23 +020034
35CElement::CElement(const string& strName) : _strName(strName), _pParent(NULL)
36{
37}
38
39CElement::~CElement()
40{
41 removeChildren();
42}
43
44// Logging
Kevin Rocardace81f82012-12-11 16:19:17 +010045void CElement::log_info(const string& strMessage, ...) const
Patrick Benavoli68a91282011-08-31 11:23:23 +020046{
Guillaume Denneulin2aab8712013-12-03 14:27:41 +010047 char *pacBuffer;
Patrick Benavoli68a91282011-08-31 11:23:23 +020048 va_list listPointer;
49
50 va_start(listPointer, strMessage);
51
Guillaume Denneulin2aab8712013-12-03 14:27:41 +010052 vasprintf(&pacBuffer, strMessage.c_str(), listPointer);
Patrick Benavoli68a91282011-08-31 11:23:23 +020053
54 va_end(listPointer);
55
Guillaume Denneulin2aab8712013-12-03 14:27:41 +010056 doLog(false, pacBuffer);
57
58 free(pacBuffer);
Patrick Benavoli68a91282011-08-31 11:23:23 +020059}
60
Kevin Rocardace81f82012-12-11 16:19:17 +010061void CElement::log_warning(const string& strMessage, ...) const
62{
Guillaume Denneulin2aab8712013-12-03 14:27:41 +010063 char *pacBuffer;
Kevin Rocardace81f82012-12-11 16:19:17 +010064 va_list listPointer;
65
66 va_start(listPointer, strMessage);
67
Guillaume Denneulin2aab8712013-12-03 14:27:41 +010068 vasprintf(&pacBuffer, strMessage.c_str(), listPointer);
Kevin Rocardace81f82012-12-11 16:19:17 +010069
70 va_end(listPointer);
71
Guillaume Denneulin2aab8712013-12-03 14:27:41 +010072 doLog(true, pacBuffer);
73
74 free(pacBuffer);
Kevin Rocardace81f82012-12-11 16:19:17 +010075}
76
Kevin Rocard36299362013-02-04 14:57:47 +010077// Log each element of the string list
78void CElement::log_table(bool bIsWarning, const list<string> lstrMessage) const
79{
80 list<string>::const_iterator iterator(lstrMessage.begin());
81 list<string>::const_iterator end(lstrMessage.end());
82
83 while (iterator != end) {
84 // Log current list element
85 doLog(bIsWarning, iterator->c_str());
86 ++iterator;
87 }
88}
89
Kevin Rocardace81f82012-12-11 16:19:17 +010090void CElement::doLog(bool bIsWarning, const string& strLog) const
Patrick Benavoli68a91282011-08-31 11:23:23 +020091{
92 assert(_pParent);
93
94 // Propagate till root
Kevin Rocardace81f82012-12-11 16:19:17 +010095 _pParent->doLog(bIsWarning, strLog);
Patrick Benavoli68a91282011-08-31 11:23:23 +020096}
97
98void CElement::nestLog() const
99{
100 assert(_pParent);
101
102 // Propagate till root
103 _pParent->nestLog();
104}
105
106void CElement::unnestLog() const
107{
108 assert(_pParent);
109
110 // Propagate till root
111 _pParent->unnestLog();
112}
113
114
115void CElement::setDescription(const string& strDescription)
116{
117 _strDescription = strDescription;
118}
119
120const string& CElement::getDescription() const
121{
122 return _strDescription;
123}
124
125bool CElement::childrenAreDynamic() const
126{
127 // By default, children are searched and not created during xml parsing
128 return false;
129}
130
131bool CElement::init(string& strError)
132{
133 uint32_t uiIndex;
134
135 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
136
137 CElement* pElement = _childArray[uiIndex];;
138
139 if (!pElement->init(strError)) {
140
141 return false;
142 }
143 }
144
145 return true;
146}
147
148void CElement::dumpContent(string& strContent, CErrorContext& errorContext, const uint32_t uiDepth) const
149{
150 string strIndent;
151
152 // Level
153 uint32_t uiNbIndents = uiDepth;
154
155 while (uiNbIndents--) {
156
157 strIndent += " ";
158 }
159 // Type
160 strContent += strIndent + "- " + getKind();
161
162 // Name
163 if (!_strName.empty()) {
164
165 strContent += ": " + getName();
166 }
167
168 // Value
169 string strValue;
170 logValue(strValue, errorContext);
171
172 if (!strValue.empty()) {
173
174 strContent += " = " + strValue;
175 }
176
177 strContent += "\n";
178
179 uint32_t uiIndex;
180
181 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
182
183 _childArray[uiIndex]->dumpContent(strContent, errorContext, uiDepth + 1);
184 }
185}
186
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200187// Element properties
188void CElement::showProperties(string& strResult) const
189{
190 strResult = "\n";
191 strResult += "Kind: " + getKind() + "\n";
192}
193
194// Conversion utilities
195string CElement::toString(uint32_t uiValue)
196{
197 ostringstream ostr;
198
199 ostr << uiValue;
200
201 return ostr.str();
202}
203
Guillaume Denneulin95331562012-09-27 15:13:10 +0200204string CElement::toString(uint64_t uiValue)
205{
206 ostringstream ostr;
207
208 ostr << uiValue;
209
210 return ostr.str();
211}
212
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200213string CElement::toString(int32_t iValue)
214{
215 ostringstream ostr;
216
217 ostr << iValue;
218
219 return ostr.str();
220}
221
Patrick Benavoliee65e6d2011-11-20 18:52:24 +0100222string CElement::toString(double dValue)
223{
224 ostringstream ostr;
225
226 ostr << dValue;
227
228 return ostr.str();
229}
230
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200231// Content dumping
Patrick Benavoli68a91282011-08-31 11:23:23 +0200232void CElement::logValue(string& strValue, CErrorContext& errorContext) const
233{
234 (void)strValue;
235 (void)errorContext;
236}
237
238// From IXmlSink
239bool CElement::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
240{
241 // Propagate through children
242 CXmlElement::CChildIterator childIterator(xmlElement);
243
244 // Context
245 CXmlElementSerializingContext& elementSerializingContext = static_cast<CXmlElementSerializingContext&>(serializingContext);
246
247 CXmlElement childElement;
248
249 while (childIterator.next(childElement)) {
250
251 CElement* pChild;
252
253 if (!childrenAreDynamic()) {
254
255 pChild = findChildOfKind(childElement.getType());
256
257 if (!pChild) {
258
Patrick Benavoli065264a2011-11-20 15:46:41 +0100259 elementSerializingContext.setError("Unable to handle XML element: " + childElement.getPath());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200260
261 return false;
262 }
263
264 } else {
265 // Child needs creation
266 pChild = elementSerializingContext.getElementLibrary()->createElement(childElement);
267
268 if (pChild) {
269
270 // Store created child!
271 addChild(pChild);
272 } else {
273
274 elementSerializingContext.setError("Unable to create XML element " + childElement.getPath());
275
276 return false;
277 }
278 }
279
280 // Dig
281 if (!pChild->fromXml(childElement, elementSerializingContext)) {
282
283 return false;
284 }
285 }
286
287 return true;
288}
289
290// From IXmlSource
291void CElement::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
292{
293 // Browse children and propagate
294 uint32_t uiNbChildren = getNbChildren();
295 uint32_t uiChild;
296
297 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
298
299 const CElement* pChild = _childArray[uiChild];
300
301 // Create corresponding child element
302 CXmlElement xmlChildElement;
303
304 xmlElement.createChild(xmlChildElement, pChild->getKind());
305
306 // Set attributes
307 pChild->setXmlNameAttribute(xmlChildElement);
308
309
310 // Propagate
311 pChild->toXml(xmlChildElement, serializingContext);
312 }
313}
314
315void CElement::setXmlNameAttribute(CXmlElement& xmlElement) const
316{
317 // By default, set Name attribute if any
318 string strName = getName();
319
320 if (!strName.empty()) {
321
322 xmlElement.setNameAttribute(strName);
323 }
324}
325
326// Name
327void CElement::setName(const string& strName)
328{
329 _strName = strName;
330}
331
332const string& CElement::getName() const
333{
334 return _strName;
335}
336
337bool CElement::rename(const string& strName, string& strError)
338{
339 // Check for conflict with brotherhood if relevant
340 if (_pParent && _pParent->childrenAreDynamic()) {
341
342 uint32_t uiParentChild;
343 uint32_t uiParentNbChildren = _pParent->getNbChildren();
344
345 for (uiParentChild = 0; uiParentChild < uiParentNbChildren; uiParentChild++) {
346
347 const CElement* pParentChild = _pParent->getChild(uiParentChild);
348
349 if (pParentChild != this && pParentChild->getName() == strName) {
350
351 // Conflict
352 strError = "Name conflicts with brother element";
353
354 return false;
355 }
356 }
357 }
358 // Change name
359 setName(strName);
360
361 return true;
362}
363
364string CElement::getPathName() const
365{
366 if (!_strName.empty()) {
367
368 return _strName;
369 } else {
370
371 return getKind();
372 }
373}
374
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200375// Hierarchy
Patrick Benavoli68a91282011-08-31 11:23:23 +0200376void CElement::addChild(CElement* pChild)
377{
378 _childArray.push_back(pChild);
379
380 pChild->_pParent = this;
381}
382
383CElement* CElement::getChild(uint32_t uiIndex)
384{
385 assert(uiIndex <= _childArray.size());
386
387 return _childArray[uiIndex];
388}
389
390const CElement* CElement::getChild(uint32_t uiIndex) const
391{
392 assert(uiIndex <= _childArray.size());
393
394 return _childArray[uiIndex];
395}
396
397CElement* CElement::getLastChild()
398{
399 uint32_t uiNbChildren = getNbChildren();
400
401 assert(uiNbChildren);
402
403 return _childArray[uiNbChildren - 1];
404}
405
406bool CElement::removeChild(CElement* pChild)
407{
408 ChildArrayIterator it;
409
410 for (it = _childArray.begin(); it != _childArray.end(); ++it) {
411
412 CElement* pElement = *it;
413
414 if (pElement == pChild) {
415
416 _childArray.erase(it);
417
418 return true;
419 }
420 }
421 return false;
422}
423
424void CElement::listChildren(string& strChildList) const
425{
426 strChildList = "\n";
427
428 // Get list of children names
429 uint32_t uiNbChildren = getNbChildren();
430 uint32_t uiChild;
431
432 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
433
434 const CElement* pChild = _childArray[uiChild];
435
436 strChildList += pChild->getName() + "\n";
437 }
438}
439
440string CElement::listQualifiedPaths(bool bDive, uint32_t uiLevel) const
441{
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200442 uint32_t uiNbChildren = getNbChildren();
443 string strResult;
444
445 // Dive Will cause only leaf nodes to be printed
446 if (!bDive || !uiNbChildren) {
447
448 strResult = getQualifiedPath() + "\n";
449 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200450
451 if (bDive || !uiLevel) {
452 // Get list of children paths
Patrick Benavoli68a91282011-08-31 11:23:23 +0200453 uint32_t uiChild;
454
455 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
456
457 const CElement* pChild = _childArray[uiChild];
458
459 strResult += pChild->listQualifiedPaths(bDive, uiLevel + 1);
460 }
461 }
462 return strResult;
463}
464
465void CElement::listChildrenPaths(string& strChildList) const
466{
Patrick Benavoli68a91282011-08-31 11:23:23 +0200467 // Get list of children paths
468 uint32_t uiNbChildren = getNbChildren();
469 uint32_t uiChild;
470
471 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
472
473 const CElement* pChild = _childArray[uiChild];
474
475 strChildList += pChild->getPath() + "\n";
476 }
477}
478
479uint32_t CElement::getNbChildren() const
480{
481 return _childArray.size();
482}
483
484const CElement* CElement::getParent() const
485{
486 return _pParent;
487}
488
489CElement* CElement::getParent()
490{
491 return _pParent;
492}
493
494void CElement::clean()
495{
496 if (childrenAreDynamic()) {
497
498 removeChildren();
499 } else {
500 // Just propagate
501 uint32_t uiIndex;
502
503 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
504
505 _childArray[uiIndex]->clean();
506 }
507 }
508}
509
510void CElement::removeChildren()
511{
512 // Delete in reverse order
513 ChildArrayReverseIterator it;
514
515 for (it = _childArray.rbegin(); it != _childArray.rend(); ++it) {
516
517 delete *it;
518 }
519 _childArray.clear();
520}
521
522const CElement* CElement::findDescendant(CPathNavigator& pathNavigator) const
523{
524 string* pStrChildName = pathNavigator.next();
525
526 if (!pStrChildName) {
527
528 return this;
529 }
530
531 const CElement* pChild = findChild(*pStrChildName);
532
533 if (!pChild) {
534
535 return NULL;
536 }
537
538 return pChild->findDescendant(pathNavigator);
539}
540
541CElement* CElement::findDescendant(CPathNavigator& pathNavigator)
542{
543 string* pStrChildName = pathNavigator.next();
544
545 if (!pStrChildName) {
546
547 return this;
548 }
549
550 CElement* pChild = findChild(*pStrChildName);
551
552 if (!pChild) {
553
554 return NULL;
555 }
556
557 return pChild->findDescendant(pathNavigator);
558}
559
560bool CElement::isDescendantOf(const CElement* pCandidateAscendant) const
561{
562 if (!_pParent) {
563
564 return false;
565 }
566 if (_pParent == pCandidateAscendant) {
567
568 return true;
569 }
570 return _pParent->isDescendantOf(pCandidateAscendant);
571}
572
573CElement* CElement::findAscendantOfKind(const string& strKind)
574{
575 if (!_pParent) {
576
577 return NULL;
578 }
579
580 if (_pParent->getKind() == strKind) {
581
582 return _pParent;
583 }
584 return _pParent->findAscendantOfKind(strKind);
585}
586
587CElement* CElement::findChild(const string& strName)
588{
589 uint32_t uiIndex;
590
591 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
592
593 CElement* pElement = _childArray[uiIndex];
594
595 if (pElement->getPathName() == strName) {
596
597 return pElement;
598 }
599 }
600
601 return NULL;
602}
603
604const CElement* CElement::findChild(const string& strName) const
605{
606 uint32_t uiIndex;
607
608 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
609
610 const CElement* pElement = _childArray[uiIndex];
611
612 if (pElement->getPathName() == strName) {
613
614 return pElement;
615 }
616 }
617
618 return NULL;
619}
620
621CElement* CElement::findChildOfKind(const string& strKind)
622{
623 uint32_t uiIndex;
624
625 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
626
627 CElement* pElement = _childArray[uiIndex];
628
629 if (pElement->getKind() == strKind) {
630
631 return pElement;
632 }
633 }
634
635 return NULL;
636}
637
638const CElement* CElement::findChildOfKind(const string& strKind) const
639{
640 uint32_t uiIndex;
641
642 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
643
644 const CElement* pElement = _childArray[uiIndex];;
645
646 if (pElement->getKind() == strKind) {
647
648 return pElement;
649 }
650 }
651
652 return NULL;
653}
654
655CElement* CElement::getRoot()
656{
657 if (!_pParent) {
658
659 return this;
660 }
661 return _pParent->getRoot();
662}
663
664const CElement* CElement::getRoot() const
665{
666 if (!_pParent) {
667
668 return this;
669 }
670 return _pParent->getRoot();
671}
672
673string CElement::getPath() const
674{
675 // Take out root element from the path
676 if (_pParent && _pParent->_pParent) {
677
678 return _pParent->getPath() + "/" + getPathName();
679 }
680 return "/" + getPathName();
681}
682
683string CElement::getQualifiedPath() const
684{
685 return getPath() + " [" + getKind() + "]";
686}
687
688uint32_t CElement::getDepth() const
689{
690 if (_pParent) {
691
692 return _pParent->getDepth() + 1;
693 }
694
695 return 0;
696}
697
698// Checksum for integrity checks
699uint8_t CElement::computeStructureChecksum() const
700{
701 // Base checksum computation on element kind
702 string strKind = getKind();
703
704 // Get element kind
705 const char* pcData = strKind.c_str();
706
707 // Cumulate
708 uint8_t uiChecksum = 0;
709
710 while (*pcData) {
711
712 uiChecksum += *pcData++;
713 }
714
715 // Propagate
716 uint32_t uiIndex;
717 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
718
719 const CElement* pChild = _childArray[uiIndex];
720
721 uiChecksum += pChild->computeStructureChecksum();
722 }
723
724 return uiChecksum;
725}
726
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200727// Utility to underline
728void CElement::appendTitle(string& strTo, const string& strTitle)
729{
730 strTo += "\n" + strTitle + "\n";
731
732 uint32_t uiLength = strTitle.size();
733
734 while (uiLength--) {
735
Patrick Benavoli1387bda2011-08-31 11:23:24 +0200736 strTo += "=";
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200737 }
738 strTo += "\n";
739}