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