cmWIXPatchParser.cxx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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. delete *i;
  28. }
  29. }
  30. cmWIXPatchParser::cmWIXPatchParser(fragment_map_t& fragments,
  31. cmCPackLog* logger)
  32. : Logger(logger)
  33. , State(BEGIN_DOCUMENT)
  34. , Valid(true)
  35. , Fragments(fragments)
  36. {
  37. }
  38. void cmWIXPatchParser::StartElement(const std::string& name, const char** atts)
  39. {
  40. if (State == BEGIN_DOCUMENT) {
  41. if (name == "CPackWiXPatch") {
  42. State = BEGIN_FRAGMENTS;
  43. } else {
  44. ReportValidationError("Expected root element 'CPackWiXPatch'");
  45. }
  46. } else if (State == BEGIN_FRAGMENTS) {
  47. if (name == "CPackWiXFragment") {
  48. State = INSIDE_FRAGMENT;
  49. StartFragment(atts);
  50. } else {
  51. ReportValidationError("Expected 'CPackWixFragment' element");
  52. }
  53. } else if (State == INSIDE_FRAGMENT) {
  54. cmWIXPatchElement& parent = *ElementStack.back();
  55. cmWIXPatchElement* element = new cmWIXPatchElement;
  56. parent.children.push_back(element);
  57. element->name = name;
  58. for (size_t i = 0; atts[i]; i += 2) {
  59. std::string key = atts[i];
  60. std::string value = atts[i + 1];
  61. element->attributes[key] = value;
  62. }
  63. ElementStack.push_back(element);
  64. }
  65. }
  66. void cmWIXPatchParser::StartFragment(const char** attributes)
  67. {
  68. for (size_t i = 0; attributes[i]; i += 2) {
  69. std::string key = attributes[i];
  70. std::string value = attributes[i + 1];
  71. if (key == "Id") {
  72. if (Fragments.find(value) != Fragments.end()) {
  73. std::stringstream tmp;
  74. tmp << "Invalid reuse of 'CPackWixFragment' 'Id': " << value;
  75. ReportValidationError(tmp.str());
  76. }
  77. ElementStack.push_back(&Fragments[value]);
  78. } else {
  79. ReportValidationError(
  80. "The only allowed 'CPackWixFragment' attribute is 'Id'");
  81. }
  82. }
  83. }
  84. void cmWIXPatchParser::EndElement(const std::string& name)
  85. {
  86. if (State == INSIDE_FRAGMENT) {
  87. if (name == "CPackWiXFragment") {
  88. State = BEGIN_FRAGMENTS;
  89. ElementStack.clear();
  90. } else {
  91. ElementStack.pop_back();
  92. }
  93. }
  94. }
  95. void cmWIXPatchParser::CharacterDataHandler(const char* data, int length)
  96. {
  97. const char* whitespace = "\x20\x09\x0d\x0a";
  98. if (State == INSIDE_FRAGMENT) {
  99. cmWIXPatchElement& parent = *ElementStack.back();
  100. std::string text(data, length);
  101. std::string::size_type first = text.find_first_not_of(whitespace);
  102. std::string::size_type last = text.find_last_not_of(whitespace);
  103. if (first != std::string::npos && last != std::string::npos) {
  104. cmWIXPatchText* text_node = new cmWIXPatchText;
  105. text_node->text = text.substr(first, last - first + 1);
  106. parent.children.push_back(text_node);
  107. }
  108. }
  109. }
  110. void cmWIXPatchParser::ReportError(int line, int column, const char* msg)
  111. {
  112. cmCPackLogger(cmCPackLog::LOG_ERROR,
  113. "Error while processing XML patch file at "
  114. << line << ":" << column << ": " << msg << std::endl);
  115. Valid = false;
  116. }
  117. void cmWIXPatchParser::ReportValidationError(std::string const& message)
  118. {
  119. ReportError(
  120. XML_GetCurrentLineNumber(static_cast<XML_Parser>(this->Parser)),
  121. XML_GetCurrentColumnNumber(static_cast<XML_Parser>(this->Parser)),
  122. message.c_str());
  123. }
  124. bool cmWIXPatchParser::IsValid() const
  125. {
  126. return Valid;
  127. }