cmWIXPatchParser.cxx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2013 Kitware, Inc.
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmWIXPatchParser.h"
  11. #include <CPack/cmCPackGenerator.h>
  12. #include <cm_expat.h>
  13. cmWIXPatchNode::Type cmWIXPatchText::type()
  14. {
  15. return cmWIXPatchNode::TEXT;
  16. }
  17. cmWIXPatchNode::Type cmWIXPatchElement::type()
  18. {
  19. return cmWIXPatchNode::ELEMENT;
  20. }
  21. cmWIXPatchNode::~cmWIXPatchNode()
  22. {
  23. }
  24. cmWIXPatchElement::~cmWIXPatchElement()
  25. {
  26. for(child_list_t::iterator i = children.begin(); i != children.end(); ++i)
  27. {
  28. delete *i;
  29. }
  30. }
  31. cmWIXPatchParser::cmWIXPatchParser(
  32. fragment_map_t& fragments, cmCPackLog* logger):
  33. Logger(logger),
  34. State(BEGIN_DOCUMENT),
  35. Valid(true),
  36. Fragments(fragments)
  37. {
  38. }
  39. void cmWIXPatchParser::StartElement(const std::string& name, const char **atts)
  40. {
  41. if(State == BEGIN_DOCUMENT)
  42. {
  43. if(name == "CPackWiXPatch")
  44. {
  45. State = BEGIN_FRAGMENTS;
  46. }
  47. else
  48. {
  49. ReportValidationError("Expected root element 'CPackWiXPatch'");
  50. }
  51. }
  52. else if(State == BEGIN_FRAGMENTS)
  53. {
  54. if(name == "CPackWiXFragment")
  55. {
  56. State = INSIDE_FRAGMENT;
  57. StartFragment(atts);
  58. }
  59. else
  60. {
  61. ReportValidationError("Expected 'CPackWixFragment' element");
  62. }
  63. }
  64. else if(State == INSIDE_FRAGMENT)
  65. {
  66. cmWIXPatchElement &parent = *ElementStack.back();
  67. cmWIXPatchElement *element = new cmWIXPatchElement;
  68. parent.children.push_back(element);
  69. element->name = name;
  70. for(size_t i = 0; atts[i]; i += 2)
  71. {
  72. std::string key = atts[i];
  73. std::string value = atts[i+1];
  74. element->attributes[key] = value;
  75. }
  76. ElementStack.push_back(element);
  77. }
  78. }
  79. void cmWIXPatchParser::StartFragment(const char **attributes)
  80. {
  81. for(size_t i = 0; attributes[i]; i += 2)
  82. {
  83. std::string key = attributes[i];
  84. std::string value = attributes[i+1];
  85. if(key == "Id")
  86. {
  87. if(Fragments.find(value) != Fragments.end())
  88. {
  89. std::stringstream tmp;
  90. tmp << "Invalid reuse of 'CPackWixFragment' 'Id': " << value;
  91. ReportValidationError(tmp.str());
  92. }
  93. ElementStack.push_back(&Fragments[value]);
  94. }
  95. else
  96. {
  97. ReportValidationError(
  98. "The only allowed 'CPackWixFragment' attribute is 'Id'");
  99. }
  100. }
  101. }
  102. void cmWIXPatchParser::EndElement(const std::string& name)
  103. {
  104. if(State == INSIDE_FRAGMENT)
  105. {
  106. if(name == "CPackWiXFragment")
  107. {
  108. State = BEGIN_FRAGMENTS;
  109. ElementStack.clear();
  110. }
  111. else
  112. {
  113. ElementStack.pop_back();
  114. }
  115. }
  116. }
  117. void cmWIXPatchParser::CharacterDataHandler(const char* data, int length)
  118. {
  119. const char* whitespace = "\x20\x09\x0d\x0a";
  120. if(State == INSIDE_FRAGMENT)
  121. {
  122. cmWIXPatchElement &parent = *ElementStack.back();
  123. std::string text(data, length);
  124. std::string::size_type first = text.find_first_not_of(whitespace);
  125. std::string::size_type last = text.find_last_not_of(whitespace);
  126. if(first != std::string::npos && last != std::string::npos)
  127. {
  128. cmWIXPatchText *text_node = new cmWIXPatchText;
  129. text_node->text = text.substr(first, last - first + 1);
  130. parent.children.push_back(text_node);
  131. }
  132. }
  133. }
  134. void cmWIXPatchParser::ReportError(int line, int column, const char* msg)
  135. {
  136. cmCPackLogger(cmCPackLog::LOG_ERROR,
  137. "Error while processing XML patch file at " << line << ":" << column <<
  138. ": "<< msg << std::endl);
  139. Valid = false;
  140. }
  141. void cmWIXPatchParser::ReportValidationError(std::string const& message)
  142. {
  143. ReportError(XML_GetCurrentLineNumber(static_cast<XML_Parser>(this->Parser)),
  144. XML_GetCurrentColumnNumber(static_cast<XML_Parser>(this->Parser)),
  145. message.c_str());
  146. }
  147. bool cmWIXPatchParser::IsValid() const
  148. {
  149. return Valid;
  150. }