blob: 43f1c57aa11ddeec85e7d410a68ea4feba5e6080 [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
Guillaume Denneulin3ba083e2014-01-31 15:09:42 +0100266 pChild = createChild(childElement, serializingContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200267
Guillaume Denneulin3ba083e2014-01-31 15:09:42 +0100268 if (!pChild) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200269
270 return false;
271 }
272 }
273
274 // Dig
275 if (!pChild->fromXml(childElement, elementSerializingContext)) {
276
277 return false;
278 }
279 }
280
281 return true;
282}
283
284// From IXmlSource
285void CElement::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
286{
287 // Browse children and propagate
288 uint32_t uiNbChildren = getNbChildren();
289 uint32_t uiChild;
290
291 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
292
293 const CElement* pChild = _childArray[uiChild];
294
295 // Create corresponding child element
296 CXmlElement xmlChildElement;
297
298 xmlElement.createChild(xmlChildElement, pChild->getKind());
299
300 // Set attributes
301 pChild->setXmlNameAttribute(xmlChildElement);
302
303
304 // Propagate
305 pChild->toXml(xmlChildElement, serializingContext);
306 }
307}
308
309void CElement::setXmlNameAttribute(CXmlElement& xmlElement) const
310{
311 // By default, set Name attribute if any
312 string strName = getName();
313
314 if (!strName.empty()) {
315
316 xmlElement.setNameAttribute(strName);
317 }
318}
319
320// Name
321void CElement::setName(const string& strName)
322{
323 _strName = strName;
324}
325
326const string& CElement::getName() const
327{
328 return _strName;
329}
330
331bool CElement::rename(const string& strName, string& strError)
332{
333 // Check for conflict with brotherhood if relevant
334 if (_pParent && _pParent->childrenAreDynamic()) {
335
336 uint32_t uiParentChild;
337 uint32_t uiParentNbChildren = _pParent->getNbChildren();
338
339 for (uiParentChild = 0; uiParentChild < uiParentNbChildren; uiParentChild++) {
340
341 const CElement* pParentChild = _pParent->getChild(uiParentChild);
342
343 if (pParentChild != this && pParentChild->getName() == strName) {
344
345 // Conflict
346 strError = "Name conflicts with brother element";
347
348 return false;
349 }
350 }
351 }
352 // Change name
353 setName(strName);
354
355 return true;
356}
357
358string CElement::getPathName() const
359{
360 if (!_strName.empty()) {
361
362 return _strName;
363 } else {
364
365 return getKind();
366 }
367}
368
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200369// Hierarchy
Patrick Benavoli68a91282011-08-31 11:23:23 +0200370void CElement::addChild(CElement* pChild)
371{
372 _childArray.push_back(pChild);
373
374 pChild->_pParent = this;
375}
376
377CElement* CElement::getChild(uint32_t uiIndex)
378{
379 assert(uiIndex <= _childArray.size());
380
381 return _childArray[uiIndex];
382}
383
384const CElement* CElement::getChild(uint32_t uiIndex) const
385{
386 assert(uiIndex <= _childArray.size());
387
388 return _childArray[uiIndex];
389}
390
391CElement* CElement::getLastChild()
392{
393 uint32_t uiNbChildren = getNbChildren();
394
395 assert(uiNbChildren);
396
397 return _childArray[uiNbChildren - 1];
398}
399
Guillaume Denneulin3ba083e2014-01-31 15:09:42 +0100400CElement* CElement::createChild(const CXmlElement& childElement,
401 CXmlSerializingContext& serializingContext)
402{
403 // Context
404 CXmlElementSerializingContext& elementSerializingContext =
405 static_cast<CXmlElementSerializingContext&>(serializingContext);
406
407 // Child needs creation
408 CElement* pChild = elementSerializingContext.getElementLibrary()->createElement(childElement);
409
410 if (!pChild) {
411
412 elementSerializingContext.setError(
413 "Unable to create XML element " + childElement.getPath());
414
415 return NULL;
416 }
417 // Store created child!
418 addChild(pChild);
419
420 return pChild;
421}
422
Patrick Benavoli68a91282011-08-31 11:23:23 +0200423bool CElement::removeChild(CElement* pChild)
424{
425 ChildArrayIterator it;
426
427 for (it = _childArray.begin(); it != _childArray.end(); ++it) {
428
429 CElement* pElement = *it;
430
431 if (pElement == pChild) {
432
433 _childArray.erase(it);
434
435 return true;
436 }
437 }
438 return false;
439}
440
441void CElement::listChildren(string& strChildList) const
442{
443 strChildList = "\n";
444
445 // Get list of children names
446 uint32_t uiNbChildren = getNbChildren();
447 uint32_t uiChild;
448
449 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
450
451 const CElement* pChild = _childArray[uiChild];
452
453 strChildList += pChild->getName() + "\n";
454 }
455}
456
457string CElement::listQualifiedPaths(bool bDive, uint32_t uiLevel) const
458{
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200459 uint32_t uiNbChildren = getNbChildren();
460 string strResult;
461
462 // Dive Will cause only leaf nodes to be printed
463 if (!bDive || !uiNbChildren) {
464
465 strResult = getQualifiedPath() + "\n";
466 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200467
468 if (bDive || !uiLevel) {
469 // Get list of children paths
Patrick Benavoli68a91282011-08-31 11:23:23 +0200470 uint32_t uiChild;
471
472 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
473
474 const CElement* pChild = _childArray[uiChild];
475
476 strResult += pChild->listQualifiedPaths(bDive, uiLevel + 1);
477 }
478 }
479 return strResult;
480}
481
482void CElement::listChildrenPaths(string& strChildList) const
483{
Patrick Benavoli68a91282011-08-31 11:23:23 +0200484 // Get list of children paths
485 uint32_t uiNbChildren = getNbChildren();
486 uint32_t uiChild;
487
488 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
489
490 const CElement* pChild = _childArray[uiChild];
491
492 strChildList += pChild->getPath() + "\n";
493 }
494}
495
496uint32_t CElement::getNbChildren() const
497{
498 return _childArray.size();
499}
500
501const CElement* CElement::getParent() const
502{
503 return _pParent;
504}
505
506CElement* CElement::getParent()
507{
508 return _pParent;
509}
510
511void CElement::clean()
512{
513 if (childrenAreDynamic()) {
514
515 removeChildren();
516 } else {
517 // Just propagate
518 uint32_t uiIndex;
519
520 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
521
522 _childArray[uiIndex]->clean();
523 }
524 }
525}
526
527void CElement::removeChildren()
528{
529 // Delete in reverse order
530 ChildArrayReverseIterator it;
531
532 for (it = _childArray.rbegin(); it != _childArray.rend(); ++it) {
533
534 delete *it;
535 }
536 _childArray.clear();
537}
538
539const CElement* CElement::findDescendant(CPathNavigator& pathNavigator) const
540{
541 string* pStrChildName = pathNavigator.next();
542
543 if (!pStrChildName) {
544
545 return this;
546 }
547
548 const CElement* pChild = findChild(*pStrChildName);
549
550 if (!pChild) {
551
552 return NULL;
553 }
554
555 return pChild->findDescendant(pathNavigator);
556}
557
558CElement* CElement::findDescendant(CPathNavigator& pathNavigator)
559{
560 string* pStrChildName = pathNavigator.next();
561
562 if (!pStrChildName) {
563
564 return this;
565 }
566
567 CElement* pChild = findChild(*pStrChildName);
568
569 if (!pChild) {
570
571 return NULL;
572 }
573
574 return pChild->findDescendant(pathNavigator);
575}
576
577bool CElement::isDescendantOf(const CElement* pCandidateAscendant) const
578{
579 if (!_pParent) {
580
581 return false;
582 }
583 if (_pParent == pCandidateAscendant) {
584
585 return true;
586 }
587 return _pParent->isDescendantOf(pCandidateAscendant);
588}
589
590CElement* CElement::findAscendantOfKind(const string& strKind)
591{
592 if (!_pParent) {
593
594 return NULL;
595 }
596
597 if (_pParent->getKind() == strKind) {
598
599 return _pParent;
600 }
601 return _pParent->findAscendantOfKind(strKind);
602}
603
604CElement* CElement::findChild(const string& strName)
605{
606 uint32_t uiIndex;
607
608 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
609
610 CElement* pElement = _childArray[uiIndex];
611
612 if (pElement->getPathName() == strName) {
613
614 return pElement;
615 }
616 }
617
618 return NULL;
619}
620
621const CElement* CElement::findChild(const string& strName) const
622{
623 uint32_t uiIndex;
624
625 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
626
627 const CElement* pElement = _childArray[uiIndex];
628
629 if (pElement->getPathName() == strName) {
630
631 return pElement;
632 }
633 }
634
635 return NULL;
636}
637
638CElement* CElement::findChildOfKind(const string& strKind)
639{
640 uint32_t uiIndex;
641
642 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
643
644 CElement* pElement = _childArray[uiIndex];
645
646 if (pElement->getKind() == strKind) {
647
648 return pElement;
649 }
650 }
651
652 return NULL;
653}
654
655const CElement* CElement::findChildOfKind(const string& strKind) const
656{
657 uint32_t uiIndex;
658
659 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
660
661 const CElement* pElement = _childArray[uiIndex];;
662
663 if (pElement->getKind() == strKind) {
664
665 return pElement;
666 }
667 }
668
669 return NULL;
670}
671
672CElement* CElement::getRoot()
673{
674 if (!_pParent) {
675
676 return this;
677 }
678 return _pParent->getRoot();
679}
680
681const CElement* CElement::getRoot() const
682{
683 if (!_pParent) {
684
685 return this;
686 }
687 return _pParent->getRoot();
688}
689
690string CElement::getPath() const
691{
692 // Take out root element from the path
693 if (_pParent && _pParent->_pParent) {
694
695 return _pParent->getPath() + "/" + getPathName();
696 }
697 return "/" + getPathName();
698}
699
700string CElement::getQualifiedPath() const
701{
702 return getPath() + " [" + getKind() + "]";
703}
704
705uint32_t CElement::getDepth() const
706{
707 if (_pParent) {
708
709 return _pParent->getDepth() + 1;
710 }
711
712 return 0;
713}
714
715// Checksum for integrity checks
716uint8_t CElement::computeStructureChecksum() const
717{
718 // Base checksum computation on element kind
719 string strKind = getKind();
720
721 // Get element kind
722 const char* pcData = strKind.c_str();
723
724 // Cumulate
725 uint8_t uiChecksum = 0;
726
727 while (*pcData) {
728
729 uiChecksum += *pcData++;
730 }
731
732 // Propagate
733 uint32_t uiIndex;
734 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
735
736 const CElement* pChild = _childArray[uiIndex];
737
738 uiChecksum += pChild->computeStructureChecksum();
739 }
740
741 return uiChecksum;
742}
743
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200744// Utility to underline
745void CElement::appendTitle(string& strTo, const string& strTitle)
746{
747 strTo += "\n" + strTitle + "\n";
748
749 uint32_t uiLength = strTitle.size();
750
751 while (uiLength--) {
752
Patrick Benavoli1387bda2011-08-31 11:23:24 +0200753 strTo += "=";
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200754 }
755 strTo += "\n";
756}