1 /*
2 http://code.google.com/p/ticpp/
3 Copyright (c) 2006 Ryan Pusztai, Ryan Mulder
4 
5 Permission is hereby granted, free of charge, to any person obtaining a copy of
6 this software and associated documentation files (the "Software"), to deal in
7 the Software without restriction, including without limitation the rights to
8 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 the Software, and to permit persons to whom the Software is furnished to do so,
10 subject to the following conditions:
11 
12 The above copyright notice and this permission notice shall be included in all
13 copies or substantial portions of the Software.
14 
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22 #define TIXML_USE_TICPP
23 #ifdef TIXML_USE_TICPP
24 
25 #include "ticpp.h"
26 #include "ticpprc.h"
27 #include "tinyxml.h"
28 #include <sstream>
29 
30 using namespace ticpp;
31 
32 // In the following Visitor functions, casting away const should be safe, as the
33 // object can only be referred to by a const &
VisitEnter(const TiXmlDocument & doc)34 bool Visitor::VisitEnter(const TiXmlDocument& doc) {
35   return VisitEnter(Document(const_cast< TiXmlDocument* >(&doc)));
36 }
37 
VisitExit(const TiXmlDocument & doc)38 bool Visitor::VisitExit(const TiXmlDocument& doc) {
39   return VisitEnter(Document(const_cast< TiXmlDocument* >(&doc)));
40 }
41 
VisitEnter(const TiXmlElement & element,const TiXmlAttribute * firstAttribute)42 bool Visitor::VisitEnter(const TiXmlElement&   element,
43                          const TiXmlAttribute* firstAttribute) {
44   if (0 != firstAttribute) {
45     Attribute attribute(const_cast< TiXmlAttribute* >(firstAttribute));
46     return VisitEnter(Element(const_cast< TiXmlElement* >(&element)), &attribute);
47   } else {
48     return VisitEnter(Element(const_cast< TiXmlElement* >(&element)), 0);
49   }
50 }
51 
VisitExit(const TiXmlElement & element)52 bool Visitor::VisitExit(const TiXmlElement& element) {
53   return VisitExit(Element(const_cast< TiXmlElement* >(&element)));
54 }
55 
Visit(const TiXmlDeclaration & declaration)56 bool Visitor::Visit(const TiXmlDeclaration& declaration) {
57   return Visit(Declaration(const_cast< TiXmlDeclaration* >(&declaration)));
58 }
59 
Visit(const TiXmlStylesheetReference & stylesheet)60 bool Visitor::Visit(const TiXmlStylesheetReference& stylesheet) {
61   return Visit(
62     StylesheetReference(const_cast< TiXmlStylesheetReference* >(&stylesheet)));
63 }
64 
Visit(const TiXmlText & text)65 bool Visitor::Visit(const TiXmlText& text) {
66   return Visit(Text(const_cast< TiXmlText* >(&text)));
67 }
68 
Visit(const TiXmlComment & comment)69 bool Visitor::Visit(const TiXmlComment& comment) {
70   return Visit(Comment(const_cast< TiXmlComment* >(&comment)));
71 }
72 
Visit(const TiXmlUnknown & x)73 bool Visitor::Visit(const TiXmlUnknown& x) { return TiXmlVisitor::Visit(x); }
74 
Attribute()75 Attribute::Attribute() {
76   SetTiXmlPointer(new TiXmlAttribute());
77   m_impRC->InitRef();
78 }
79 
Attribute(TiXmlAttribute * attribute)80 Attribute::Attribute(TiXmlAttribute* attribute) {
81   SetTiXmlPointer(attribute);
82   m_impRC->IncRef();
83 }
84 
Attribute(const std::string & name,const std::string & value)85 Attribute::Attribute(const std::string& name, const std::string& value) {
86   SetTiXmlPointer(new TiXmlAttribute(name, value));
87   m_impRC->InitRef();
88 }
89 
operator =(const Attribute & copy)90 void Attribute::operator=(const Attribute& copy) {
91   // Dropping the reference to the old object
92   this->m_impRC->DecRef();
93 
94   // Pointing to the new Object
95   SetTiXmlPointer(copy.m_tiXmlPointer);
96 
97   // The internal tixml pointer changed in the above line
98   this->m_impRC->IncRef();
99 }
100 
Attribute(const Attribute & copy)101 Attribute::Attribute(const Attribute& copy)
102     : Base() {
103   // Dropping the reference to the old object
104   this->m_impRC->DecRef();
105 
106   // Pointing to the new Object
107   SetTiXmlPointer(copy.m_tiXmlPointer);
108 
109   // The internal tixml pointer changed in the above line
110   this->m_impRC->IncRef();
111 }
112 
~Attribute()113 Attribute::~Attribute() { m_impRC->DecRef(); }
114 
Value() const115 std::string Attribute::Value() const {
116   ValidatePointer();
117   return m_tiXmlPointer->ValueStr();
118 }
119 
Name() const120 std::string Attribute::Name() const {
121   ValidatePointer();
122   return m_tiXmlPointer->Name();
123 }
124 
Next(bool throwIfNoAttribute) const125 Attribute* Attribute::Next(bool throwIfNoAttribute) const {
126   ValidatePointer();
127   TiXmlAttribute* attribute = m_tiXmlPointer->Next();
128 
129   if (0 == attribute) {
130     if (throwIfNoAttribute) {
131       TICPPTHROW("No more attributes found")
132     } else {
133       return 0;
134     }
135   }
136 
137   Attribute* temp = new Attribute(attribute);
138   attribute->m_spawnedWrappers.push_back(temp);
139 
140   return temp;
141 }
142 
Previous(bool throwIfNoAttribute) const143 Attribute* Attribute::Previous(bool throwIfNoAttribute) const {
144   ValidatePointer();
145   TiXmlAttribute* attribute = m_tiXmlPointer->Previous();
146 
147   if (0 == attribute) {
148     if (throwIfNoAttribute) {
149       TICPPTHROW("No more attributes found")
150     } else {
151       return 0;
152     }
153   }
154 
155   Attribute* temp = new Attribute(attribute);
156   attribute->m_spawnedWrappers.push_back(temp);
157 
158   return temp;
159 }
160 
IterateNext(const std::string &,Attribute ** next) const161 void Attribute::IterateNext(const std::string&, Attribute** next) const {
162   *next = Next(false);
163 }
164 
IteratePrevious(const std::string &,Attribute ** previous) const165 void Attribute::IteratePrevious(const std::string&, Attribute** previous) const {
166   *previous = Previous(false);
167 }
168 
Print(FILE * file,int depth) const169 void Attribute::Print(FILE* file, int depth) const {
170   ValidatePointer();
171   m_tiXmlPointer->Print(file, depth);
172 }
173 
SetTiXmlPointer(TiXmlAttribute * newPointer)174 void Attribute::SetTiXmlPointer(TiXmlAttribute* newPointer) {
175   m_tiXmlPointer = newPointer;
176   SetImpRC(newPointer);
177 }
178 
179 //*****************************************************************************
180 
NodeFactory(TiXmlNode * tiXmlNode,bool throwIfNull,bool rememberSpawnedWrapper) const181 Node* Node::NodeFactory(TiXmlNode* tiXmlNode,
182                         bool       throwIfNull,
183                         bool       rememberSpawnedWrapper) const {
184   if (0 == tiXmlNode) {
185     if (throwIfNull) {
186       TICPPTHROW("tiXmlNode is nullptr")
187     } else {
188       return 0;
189     }
190   }
191 
192   Node* temp;
193 
194   switch (tiXmlNode->Type()) {
195     case TiXmlNode::DOCUMENT:
196       temp = new Document(tiXmlNode->ToDocument());
197       break;
198 
199     case TiXmlNode::ELEMENT:
200       temp = new Element(tiXmlNode->ToElement());
201       break;
202 
203     case TiXmlNode::COMMENT:
204       temp = new Comment(tiXmlNode->ToComment());
205       break;
206 
207     case TiXmlNode::TEXT:
208       temp = new Text(tiXmlNode->ToText());
209       break;
210 
211     case TiXmlNode::DECLARATION:
212       temp = new Declaration(tiXmlNode->ToDeclaration());
213       break;
214 
215     case TiXmlNode::STYLESHEETREFERENCE:
216       temp = new StylesheetReference(tiXmlNode->ToStylesheetReference());
217       break;
218 
219     default:
220       TICPPTHROW("Type is unsupported")
221   }
222 
223   if (rememberSpawnedWrapper) {
224     tiXmlNode->m_spawnedWrappers.push_back(temp);
225   }
226 
227   return temp;
228 }
229 
Value() const230 std::string Node::Value() const { return GetTiXmlPointer()->ValueStr(); }
231 
Clear()232 void Node::Clear() { GetTiXmlPointer()->Clear(); }
233 
Parent(bool throwIfNoParent) const234 Node* Node::Parent(bool throwIfNoParent) const {
235   TiXmlNode* parent = GetTiXmlPointer()->Parent();
236 
237   if ((0 == parent) && throwIfNoParent) {
238     TICPPTHROW("No parent exists");
239   }
240 
241   return NodeFactory(parent, false);
242 }
243 
FirstChild(bool throwIfNoChildren) const244 Node* Node::FirstChild(bool throwIfNoChildren) const {
245   return FirstChild("", throwIfNoChildren);
246 }
247 
FirstChild(const std::string & value,bool throwIfNoChildren) const248 Node* Node::FirstChild(const std::string& value, bool throwIfNoChildren) const {
249   return FirstChild(value.c_str(), throwIfNoChildren);
250 }
251 
FirstChild(const char * value,bool throwIfNoChildren) const252 Node* Node::FirstChild(const char* value, bool throwIfNoChildren) const {
253   TiXmlNode* childNode;
254 
255   if (0 == strlen(value)) {
256     childNode = GetTiXmlPointer()->FirstChild();
257   } else {
258     childNode = GetTiXmlPointer()->FirstChild(value);
259   }
260 
261   if ((0 == childNode) && throwIfNoChildren) {
262     TICPPTHROW("Child with the value of \"" << value << "\" not found");
263   }
264 
265   return NodeFactory(childNode, false);
266 }
267 
LastChild(bool throwIfNoChildren) const268 Node* Node::LastChild(bool throwIfNoChildren) const {
269   return LastChild("", throwIfNoChildren);
270 }
271 
LastChild(const std::string & value,bool throwIfNoChildren) const272 Node* Node::LastChild(const std::string& value, bool throwIfNoChildren) const {
273   return LastChild(value.c_str(), throwIfNoChildren);
274 }
275 
LastChild(const char * value,bool throwIfNoChildren) const276 Node* Node::LastChild(const char* value, bool throwIfNoChildren) const {
277   TiXmlNode* childNode;
278 
279   if (0 == strlen(value)) {
280     childNode = GetTiXmlPointer()->LastChild();
281   } else {
282     childNode = GetTiXmlPointer()->LastChild(value);
283   }
284 
285   if ((0 == childNode) && throwIfNoChildren) {
286     TICPPTHROW("Child with the value of \"" << value << "\" not found");
287   }
288 
289   return NodeFactory(childNode, false);
290 }
291 
IterateChildren(Node * previous) const292 Node* Node::IterateChildren(Node* previous) const {
293   TiXmlNode* pointer;
294 
295   if (0 == previous) {
296     pointer = GetTiXmlPointer()->IterateChildren(0);
297   } else {
298     pointer = GetTiXmlPointer()->IterateChildren(previous->GetTiXmlPointer());
299   }
300 
301   return NodeFactory(pointer, false);
302 }
303 
IterateChildren(const std::string & value,Node * previous) const304 Node* Node::IterateChildren(const std::string& value, Node* previous) const {
305   TiXmlNode* pointer;
306 
307   if (0 == previous) {
308     pointer = GetTiXmlPointer()->IterateChildren(value, 0);
309   } else {
310     pointer =
311       GetTiXmlPointer()->IterateChildren(value, previous->GetTiXmlPointer());
312   }
313 
314   return NodeFactory(pointer, false);
315 }
316 
InsertEndChild(Node & addThis)317 Node* Node::InsertEndChild(Node& addThis) {
318   if (addThis.Type() == TiXmlNode::DOCUMENT) {
319     TICPPTHROW("Node is a Document and can't be inserted");
320   }
321 
322   TiXmlNode* pointer =
323     GetTiXmlPointer()->InsertEndChild(*addThis.GetTiXmlPointer());
324 
325   if (0 == pointer) {
326     TICPPTHROW("Node can't be inserted");
327   }
328 
329   return NodeFactory(pointer);
330 }
331 
LinkEndChild(Node * childNode)332 Node* Node::LinkEndChild(Node* childNode) {
333   if (childNode->Type() == TiXmlNode::DOCUMENT) {
334     TICPPTHROW("Node is a Document and can't be linked");
335   }
336 
337   // Increment reference count when adding to the tree
338   childNode->m_impRC->IncRef();
339 
340   if (0 == GetTiXmlPointer()->LinkEndChild(childNode->GetTiXmlPointer())) {
341     TICPPTHROW("Node can't be linked");
342   }
343 
344   return childNode;
345 }
346 
InsertBeforeChild(Node * beforeThis,Node & addThis)347 Node* Node::InsertBeforeChild(Node* beforeThis, Node& addThis) {
348   if (addThis.Type() == TiXmlNode::DOCUMENT) {
349     TICPPTHROW("Node is a Document and can't be inserted");
350   }
351 
352   // Increment reference count when adding to the tree
353   addThis.m_impRC->IncRef();
354 
355   TiXmlNode* pointer = GetTiXmlPointer()->InsertBeforeChild(
356     beforeThis->GetTiXmlPointer(), *addThis.GetTiXmlPointer());
357 
358   if (0 == pointer) {
359     TICPPTHROW("Node can't be inserted");
360   }
361 
362   return NodeFactory(pointer);
363 }
364 
InsertAfterChild(Node * afterThis,Node & addThis)365 Node* Node::InsertAfterChild(Node* afterThis, Node& addThis) {
366   if (addThis.Type() == TiXmlNode::DOCUMENT) {
367     TICPPTHROW("Node is a Document and can't be inserted");
368   }
369 
370   // Increment reference count when adding to the tree
371   addThis.m_impRC->IncRef();
372 
373   TiXmlNode* pointer = GetTiXmlPointer()->InsertAfterChild(
374     afterThis->GetTiXmlPointer(), *addThis.GetTiXmlPointer());
375 
376   if (0 == pointer) {
377     TICPPTHROW("Node can't be inserted");
378   }
379 
380   return NodeFactory(pointer);
381 }
382 
ReplaceChild(Node * replaceThis,Node & withThis)383 Node* Node::ReplaceChild(Node* replaceThis, Node& withThis) {
384   if (withThis.Type() == TiXmlNode::DOCUMENT) {
385     TICPPTHROW("Node is a Document and can't be inserted");
386   }
387 
388   // Increment reference count when adding to the tree
389   withThis.m_impRC->IncRef();
390 
391   TiXmlNode* pointer = GetTiXmlPointer()->ReplaceChild(
392     replaceThis->GetTiXmlPointer(), *withThis.GetTiXmlPointer());
393 
394   if (0 == pointer) {
395     TICPPTHROW("Node can't be inserted");
396   }
397 
398   return NodeFactory(pointer);
399 }
400 
RemoveChild(Node * removeThis)401 void Node::RemoveChild(Node* removeThis) {
402   if (!GetTiXmlPointer()->RemoveChild(removeThis->GetTiXmlPointer())) {
403     TICPPTHROW("Node to remove (" << removeThis->Value()
404                                   << ") is not a child of this Node ("
405                                   << Value()
406                                   << ")")
407   }
408 }
409 
PreviousSibling(bool throwIfNoSiblings) const410 Node* Node::PreviousSibling(bool throwIfNoSiblings) const {
411   return PreviousSibling("", throwIfNoSiblings);
412 }
413 
PreviousSibling(const std::string & value,bool throwIfNoSiblings) const414 Node* Node::PreviousSibling(const std::string& value,
415                             bool               throwIfNoSiblings) const {
416   return PreviousSibling(value.c_str(), throwIfNoSiblings);
417 }
418 
PreviousSibling(const char * value,bool throwIfNoSiblings) const419 Node* Node::PreviousSibling(const char* value, bool throwIfNoSiblings) const {
420   TiXmlNode* sibling;
421 
422   if (0 == strlen(value)) {
423     sibling = GetTiXmlPointer()->PreviousSibling();
424   } else {
425     sibling = GetTiXmlPointer()->PreviousSibling(value);
426   }
427 
428   if ((0 == sibling) && throwIfNoSiblings) {
429     TICPPTHROW("No Siblings found with value, '" << value
430                                                  << "', Prior to this Node ("
431                                                  << Value()
432                                                  << ")")
433   }
434 
435   return NodeFactory(sibling, false);
436 }
437 
NextSibling(bool throwIfNoSiblings) const438 Node* Node::NextSibling(bool throwIfNoSiblings) const {
439   return NextSibling("", throwIfNoSiblings);
440 }
441 
NextSibling(const std::string & value,bool throwIfNoSiblings) const442 Node* Node::NextSibling(const std::string& value, bool throwIfNoSiblings) const {
443   return NextSibling(value.c_str(), throwIfNoSiblings);
444 }
445 
NextSibling(const char * value,bool throwIfNoSiblings) const446 Node* Node::NextSibling(const char* value, bool throwIfNoSiblings) const {
447   TiXmlNode* sibling;
448 
449   if (0 == strlen(value)) {
450     sibling = GetTiXmlPointer()->NextSibling();
451   } else {
452     sibling = GetTiXmlPointer()->NextSibling(value);
453   }
454 
455   if ((0 == sibling) && throwIfNoSiblings) {
456     TICPPTHROW("No Siblings found with value, '" << value << "', After this Node ("
457                                                  << Value()
458                                                  << ")")
459   }
460 
461   return NodeFactory(sibling, false);
462 }
463 
NextSiblingElement(bool throwIfNoSiblings) const464 Element* Node::NextSiblingElement(bool throwIfNoSiblings) const {
465   return NextSiblingElement("", throwIfNoSiblings);
466 }
467 
NextSiblingElement(const std::string & value,bool throwIfNoSiblings) const468 Element* Node::NextSiblingElement(const std::string& value,
469                                   bool               throwIfNoSiblings) const {
470   return NextSiblingElement(value.c_str(), throwIfNoSiblings);
471 }
472 
NextSiblingElement(const char * value,bool throwIfNoSiblings) const473 Element* Node::NextSiblingElement(const char* value,
474                                   bool        throwIfNoSiblings) const {
475   TiXmlElement* sibling;
476 
477   if (0 == strlen(value)) {
478     sibling = GetTiXmlPointer()->NextSiblingElement();
479   } else {
480     sibling = GetTiXmlPointer()->NextSiblingElement(value);
481   }
482 
483   if (0 == sibling) {
484     if (throwIfNoSiblings) {
485       TICPPTHROW("No Element Siblings found with value, '"
486                  << value
487                  << "', After this Node ("
488                  << Value()
489                  << ")")
490     } else {
491       return 0;
492     }
493   }
494 
495   Element* temp = new Element(sibling);
496   sibling->m_spawnedWrappers.push_back(temp);
497 
498   return temp;
499 }
500 
FirstChildElement(bool throwIfNoChildren) const501 Element* Node::FirstChildElement(bool throwIfNoChildren) const {
502   return FirstChildElement("", throwIfNoChildren);
503 }
504 
FirstChildElement(const std::string & value,bool throwIfNoChildren) const505 Element* Node::FirstChildElement(const std::string& value,
506                                  bool               throwIfNoChildren) const {
507   return FirstChildElement(value.c_str(), throwIfNoChildren);
508 }
509 
FirstChildElement(const char * value,bool throwIfNoChildren) const510 Element* Node::FirstChildElement(const char* value, bool throwIfNoChildren) const {
511   TiXmlElement* element;
512 
513   if (0 == strlen(value)) {
514     element = GetTiXmlPointer()->FirstChildElement();
515   } else {
516     element = GetTiXmlPointer()->FirstChildElement(value);
517   }
518 
519   if (0 == element) {
520     if (throwIfNoChildren) {
521       TICPPTHROW("Element (" << Value()
522                              << ") does NOT contain a child with the value of '"
523                              << value
524                              << "'")
525     } else {
526       return 0;
527     }
528   }
529 
530   Element* temp = new Element(element);
531   element->m_spawnedWrappers.push_back(temp);
532 
533   return temp;
534 }
535 
Type() const536 int Node::Type() const { return GetTiXmlPointer()->Type(); }
537 
GetDocument(bool throwIfNoDocument) const538 Document* Node::GetDocument(bool throwIfNoDocument) const {
539   TiXmlDocument* doc = GetTiXmlPointer()->GetDocument();
540 
541   if (0 == doc) {
542     if (throwIfNoDocument) {
543       TICPPTHROW("This node (" << Value() << ") is not linked under a document")
544     } else {
545       return 0;
546     }
547   }
548 
549   Document* temp = new Document(doc);
550   doc->m_spawnedWrappers.push_back(temp);
551 
552   return temp;
553 }
554 
NoChildren() const555 bool Node::NoChildren() const { return GetTiXmlPointer()->NoChildren(); }
556 
ToDocument() const557 Document* Node::ToDocument() const {
558   TiXmlDocument* doc = GetTiXmlPointer()->ToDocument();
559 
560   if (0 == doc) {
561     TICPPTHROW("This node (" << Value() << ") is not a Document")
562   }
563 
564   Document* temp = new Document(doc);
565   doc->m_spawnedWrappers.push_back(temp);
566 
567   return temp;
568 }
569 
ToElement() const570 Element* Node::ToElement() const {
571   TiXmlElement* doc = GetTiXmlPointer()->ToElement();
572 
573   if (0 == doc) {
574     TICPPTHROW("This node (" << Value() << ") is not a Element")
575   }
576 
577   Element* temp = new Element(doc);
578   doc->m_spawnedWrappers.push_back(temp);
579 
580   return temp;
581 }
582 
ToComment() const583 Comment* Node::ToComment() const {
584   TiXmlComment* doc = GetTiXmlPointer()->ToComment();
585 
586   if (0 == doc) {
587     TICPPTHROW("This node (" << Value() << ") is not a Comment")
588   }
589 
590   Comment* temp = new Comment(doc);
591   doc->m_spawnedWrappers.push_back(temp);
592 
593   return temp;
594 }
595 
ToText() const596 Text* Node::ToText() const {
597   TiXmlText* doc = GetTiXmlPointer()->ToText();
598 
599   if (0 == doc) {
600     TICPPTHROW("This node (" << Value() << ") is not a Text")
601   }
602 
603   Text* temp = new Text(doc);
604   doc->m_spawnedWrappers.push_back(temp);
605 
606   return temp;
607 }
608 
ToDeclaration() const609 Declaration* Node::ToDeclaration() const {
610   TiXmlDeclaration* doc = GetTiXmlPointer()->ToDeclaration();
611 
612   if (0 == doc) {
613     TICPPTHROW("This node (" << Value() << ") is not a Declaration")
614   }
615 
616   Declaration* temp = new Declaration(doc);
617   doc->m_spawnedWrappers.push_back(temp);
618 
619   return temp;
620 }
621 
ToStylesheetReference() const622 StylesheetReference* Node::ToStylesheetReference() const {
623   TiXmlStylesheetReference* doc = GetTiXmlPointer()->ToStylesheetReference();
624 
625   if (0 == doc) {
626     TICPPTHROW("This node (" << Value() << ") is not a StylesheetReference")
627   }
628 
629   StylesheetReference* temp = new StylesheetReference(doc);
630   doc->m_spawnedWrappers.push_back(temp);
631 
632   return temp;
633 }
634 
Clone() const635 std::unique_ptr< Node > Node::Clone() const {
636   TiXmlNode* node = GetTiXmlPointer()->Clone();
637 
638   if (0 == node) {
639     TICPPTHROW("Node could not be cloned");
640   }
641 
642   std::unique_ptr< Node > temp(NodeFactory(node, false, false));
643 
644   // Take ownership of the memory from TiXml
645   temp->m_impRC->InitRef();
646 
647   return temp;
648 }
649 
Accept(TiXmlVisitor * visitor) const650 bool Node::Accept(TiXmlVisitor* visitor) const {
651   return GetTiXmlPointer()->Accept(visitor);
652 }
653 
654 //*****************************************************************************
655 
Comment()656 Comment::Comment()
657     : NodeImp< TiXmlComment >(new TiXmlComment()) {
658   m_impRC->InitRef();
659 }
660 
Comment(TiXmlComment * comment)661 Comment::Comment(TiXmlComment* comment)
662     : NodeImp< TiXmlComment >(comment) {}
663 
Comment(const std::string & comment)664 Comment::Comment(const std::string& comment)
665     : NodeImp< TiXmlComment >(new TiXmlComment()) {
666   m_impRC->InitRef();
667   m_tiXmlPointer->SetValue(comment);
668 }
669 
670 //*****************************************************************************
671 
Text()672 Text::Text()
673     : NodeImp< TiXmlText >(new TiXmlText("")) {
674   m_impRC->InitRef();
675 }
676 
Text(const std::string & value)677 Text::Text(const std::string& value)
678     : NodeImp< TiXmlText >(new TiXmlText(value)) {
679   m_impRC->InitRef();
680 }
681 
Text(TiXmlText * text)682 Text::Text(TiXmlText* text)
683     : NodeImp< TiXmlText >(text) {}
684 
685 //*****************************************************************************
686 
Document()687 Document::Document()
688     : NodeImp< TiXmlDocument >(new TiXmlDocument()) {
689   m_impRC->InitRef();
690 }
691 
Document(TiXmlDocument * document)692 Document::Document(TiXmlDocument* document)
693     : NodeImp< TiXmlDocument >(document) {}
694 
Document(const char * documentName)695 Document::Document(const char* documentName)
696     : NodeImp< TiXmlDocument >(new TiXmlDocument(documentName)) {
697   m_impRC->InitRef();
698 }
699 
Document(const std::string & documentName)700 Document::Document(const std::string& documentName)
701     : NodeImp< TiXmlDocument >(new TiXmlDocument(documentName)) {
702   m_impRC->InitRef();
703 }
704 
LoadFile(TiXmlEncoding encoding)705 void Document::LoadFile(TiXmlEncoding encoding) {
706   if (!m_tiXmlPointer->LoadFile(encoding)) {
707     TICPPTHROW("Couldn't load " << m_tiXmlPointer->Value());
708   }
709 }
710 
SaveFile() const711 void Document::SaveFile() const {
712   if (!m_tiXmlPointer->SaveFile()) {
713     TICPPTHROW("Couldn't save " << m_tiXmlPointer->Value());
714   }
715 }
716 
LoadFile(const std::string & filename,TiXmlEncoding encoding)717 void Document::LoadFile(const std::string& filename, TiXmlEncoding encoding) {
718   if (!m_tiXmlPointer->LoadFile(filename.c_str(), encoding)) {
719     TICPPTHROW("Couldn't load " << filename);
720   }
721 }
722 
LoadFile(const char * filename,TiXmlEncoding encoding)723 void Document::LoadFile(const char* filename, TiXmlEncoding encoding) {
724   if (!m_tiXmlPointer->LoadFile(filename, encoding)) {
725     TICPPTHROW("Couldn't load " << filename);
726   }
727 }
728 
SaveFile(const std::string & filename) const729 void Document::SaveFile(const std::string& filename) const {
730   if (!m_tiXmlPointer->SaveFile(filename.c_str())) {
731     TICPPTHROW("Couldn't save " << filename);
732   }
733 }
734 
Parse(const std::string & xml,bool throwIfParseError,TiXmlEncoding encoding)735 void Document::Parse(const std::string& xml,
736                      bool               throwIfParseError,
737                      TiXmlEncoding      encoding) {
738   m_tiXmlPointer->Parse(xml.c_str(), 0, encoding);
739 
740   if (throwIfParseError && m_tiXmlPointer->Error()) {
741     TICPPTHROW("Error parsing xml.");
742   }
743 }
744 
745 //*****************************************************************************
746 
Element()747 Element::Element()
748     : NodeImp< TiXmlElement >(new TiXmlElement(
749         "DefaultValueCausedByCreatingAnElementWithNoParameters")) {
750   m_impRC->InitRef();
751 }
752 
Element(const std::string & value)753 Element::Element(const std::string& value)
754     : NodeImp< TiXmlElement >(new TiXmlElement(value)) {
755   m_impRC->InitRef();
756 }
757 
Element(const char * value)758 Element::Element(const char* value)
759     : NodeImp< TiXmlElement >(new TiXmlElement(value)) {
760   m_impRC->InitRef();
761 }
762 
Element(TiXmlElement * element)763 Element::Element(TiXmlElement* element)
764     : NodeImp< TiXmlElement >(element) {}
765 
FirstAttribute(bool throwIfNoAttributes) const766 Attribute* Element::FirstAttribute(bool throwIfNoAttributes) const {
767   ValidatePointer();
768   TiXmlAttribute* attribute = m_tiXmlPointer->FirstAttribute();
769 
770   if ((0 == attribute) && throwIfNoAttributes) {
771     TICPPTHROW("This Element (" << Value() << ") has no attributes")
772   }
773 
774   if (0 == attribute) {
775     if (throwIfNoAttributes) {
776       TICPPTHROW("Element (" << Value() << ") has no attributes")
777     } else {
778       return 0;
779     }
780   }
781 
782   Attribute* temp = new Attribute(attribute);
783   attribute->m_spawnedWrappers.push_back(temp);
784 
785   return temp;
786 }
787 
LastAttribute(bool throwIfNoAttributes) const788 Attribute* Element::LastAttribute(bool throwIfNoAttributes) const {
789   ValidatePointer();
790   TiXmlAttribute* attribute = m_tiXmlPointer->LastAttribute();
791 
792   if ((0 == attribute) && throwIfNoAttributes) {
793     TICPPTHROW("This Element (" << Value() << ") has no attributes")
794   }
795 
796   if (0 == attribute) {
797     if (throwIfNoAttributes) {
798       TICPPTHROW("Element (" << Value() << ") has no attributes")
799     } else {
800       return 0;
801     }
802   }
803 
804   Attribute* temp = new Attribute(attribute);
805   attribute->m_spawnedWrappers.push_back(temp);
806 
807   return temp;
808 }
809 
GetAttributeOrDefault(const std::string & name,const std::string & defaultValue) const810 std::string Element::GetAttributeOrDefault(const std::string& name,
811                                            const std::string& defaultValue) const {
812   std::string value;
813 
814   if (!GetAttributeImp(name, &value)) {
815     return defaultValue;
816   }
817 
818   return value;
819 }
820 
GetAttribute(const std::string & name) const821 std::string Element::GetAttribute(const std::string& name) const {
822   return GetAttributeOrDefault(name, std::string());
823 }
824 
HasAttribute(const std::string & name) const825 bool Element::HasAttribute(const std::string& name) const {
826   ValidatePointer();
827   return (0 != m_tiXmlPointer->Attribute(name.c_str()));
828 }
829 
RemoveAttribute(const std::string & name)830 void Element::RemoveAttribute(const std::string& name) {
831   ValidatePointer();
832   m_tiXmlPointer->RemoveAttribute(name.c_str());
833 }
834 
GetAttributeImp(const std::string & name,std::string * value) const835 bool Element::GetAttributeImp(const std::string& name, std::string* value) const {
836   ValidatePointer();
837 
838   // Get value from TinyXML, if the attribute exists
839   const char* retVal = m_tiXmlPointer->Attribute(name.c_str());
840 
841   // TinyXML returns nullptr if the attribute doesn't exist
842   if (0 == retVal) {
843     return false;
844   } else {
845     *value = retVal;
846     return true;
847   }
848 }
849 
GetTextImp(std::string * value) const850 bool Element::GetTextImp(std::string* value) const {
851   ValidatePointer();
852 
853   // Get value from TinyXML, if the attribute exists
854   const char* retVal = m_tiXmlPointer->GetText();
855 
856   // TinyXML returns nullptr if the attribute doesn't exist
857   if (0 == retVal) {
858     return false;
859   } else {
860     *value = retVal;
861     return true;
862   }
863 }
864 
865 //*****************************************************************************
866 
Declaration()867 Declaration::Declaration()
868     : NodeImp< TiXmlDeclaration >(new TiXmlDeclaration()) {
869   m_impRC->InitRef();
870 }
871 
Declaration(TiXmlDeclaration * declaration)872 Declaration::Declaration(TiXmlDeclaration* declaration)
873     : NodeImp< TiXmlDeclaration >(declaration) {}
874 
Declaration(const std::string & version,const std::string & encoding,const std::string & standalone)875 Declaration::Declaration(const std::string& version,
876                          const std::string& encoding,
877                          const std::string& standalone)
878     : NodeImp< TiXmlDeclaration >(
879         new TiXmlDeclaration(version, encoding, standalone)) {
880   m_impRC->InitRef();
881 }
882 
Version() const883 std::string Declaration::Version() const { return m_tiXmlPointer->Version(); }
884 
Encoding() const885 std::string Declaration::Encoding() const { return m_tiXmlPointer->Encoding(); }
886 
Standalone() const887 std::string Declaration::Standalone() const {
888   return m_tiXmlPointer->Standalone();
889 }
890 
891 //*****************************************************************************
892 
StylesheetReference()893 StylesheetReference::StylesheetReference()
894     : NodeImp< TiXmlStylesheetReference >(new TiXmlStylesheetReference()) {
895   m_impRC->InitRef();
896 }
897 
StylesheetReference(TiXmlStylesheetReference * stylesheetReference)898 StylesheetReference::StylesheetReference(
899   TiXmlStylesheetReference* stylesheetReference)
900     : NodeImp< TiXmlStylesheetReference >(stylesheetReference) {}
901 
StylesheetReference(const std::string & type,const std::string & href)902 StylesheetReference::StylesheetReference(const std::string& type,
903                                          const std::string& href)
904     : NodeImp< TiXmlStylesheetReference >(
905         new TiXmlStylesheetReference(type, href)) {
906   m_impRC->InitRef();
907 }
908 
Type() const909 std::string StylesheetReference::Type() const { return m_tiXmlPointer->Type(); }
910 
Href() const911 std::string StylesheetReference::Href() const { return m_tiXmlPointer->Href(); }
912 
913 //*****************************************************************************
914 
Exception(const std::string & details)915 Exception::Exception(const std::string& details)
916     : m_details(details) {}
917 
~Exception()918 Exception::~Exception() throw() {}
919 
what() const920 const char* Exception::what() const throw() { return m_details.c_str(); }
921 
922 //*****************************************************************************
923 
TiCppRC()924 TiCppRC::TiCppRC() {
925   // Spawn reference counter for this object
926   m_tiRC = new TiCppRCImp(this);
927 }
928 
DeleteSpawnedWrappers()929 void TiCppRC::DeleteSpawnedWrappers() {
930   std::vector< Base* >::reverse_iterator wrapper;
931 
932   for (wrapper = m_spawnedWrappers.rbegin(); wrapper != m_spawnedWrappers.rend();
933        ++wrapper) {
934     delete *wrapper;
935   }
936 
937   m_spawnedWrappers.clear();
938 }
939 
~TiCppRC()940 TiCppRC::~TiCppRC() {
941   DeleteSpawnedWrappers();
942 
943   // Set pointer held by reference counter to nullptr
944   this->m_tiRC->Nullify();
945 
946   // Decrement reference - so reference counter will delete itself if necessary
947   this->m_tiRC->DecRef();
948 }
949 
950 //*****************************************************************************
951 
TiCppRCImp(TiCppRC * tiCppRC)952 TiCppRCImp::TiCppRCImp(TiCppRC* tiCppRC)
953     : m_count(1)
954     , m_tiCppRC(tiCppRC) {}
955 
IncRef()956 void TiCppRCImp::IncRef() { m_count++; }
957 
DecRef()958 void TiCppRCImp::DecRef() {
959   m_count--;
960 
961   if (0 == m_count) {
962     delete m_tiCppRC;
963     delete this;
964   }
965 }
966 
InitRef()967 void TiCppRCImp::InitRef() { m_count = 1; }
968 
Nullify()969 void TiCppRCImp::Nullify() { m_tiCppRC = 0; }
970 
Get()971 TiCppRC* TiCppRCImp::Get() { return m_tiCppRC; }
972 
IsNull()973 bool TiCppRCImp::IsNull() { return 0 == m_tiCppRC; }
974 
975 #endif  // TIXML_USE_TICPP
976