Coverage Report

Created: 2024-07-27 06:44

/src/CMake/Source/cmXMLParser.cxx
Line
Count
Source (jump to first uncovered line)
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file Copyright.txt or https://cmake.org/licensing for details.  */
3
#include "cmXMLParser.h"
4
5
#include <cstring>
6
#include <iostream>
7
#include <sstream>
8
9
#include <cm3p/expat.h>
10
11
#include "cmsys/FStream.hxx"
12
13
cmXMLParser::cmXMLParser()
14
10.0k
{
15
10.0k
  this->Parser = nullptr;
16
10.0k
  this->ParseError = 0;
17
10.0k
  this->ReportCallback = nullptr;
18
10.0k
  this->ReportCallbackData = nullptr;
19
10.0k
}
20
21
cmXMLParser::~cmXMLParser()
22
10.0k
{
23
10.0k
  if (this->Parser) {
24
2.98k
    this->CleanupParser();
25
2.98k
  }
26
10.0k
}
27
28
int cmXMLParser::Parse(const char* string)
29
10.0k
{
30
10.0k
  return this->InitializeParser() &&
31
10.0k
    this->ParseChunk(string, strlen(string)) && this->CleanupParser();
32
10.0k
}
33
34
int cmXMLParser::ParseFile(const char* file)
35
10.0k
{
36
10.0k
  if (!file) {
37
0
    return 0;
38
0
  }
39
40
10.0k
  cmsys::ifstream ifs(file);
41
10.0k
  if (!ifs) {
42
0
    return 0;
43
0
  }
44
45
10.0k
  std::ostringstream str;
46
10.0k
  str << ifs.rdbuf();
47
10.0k
  return this->Parse(str.str().c_str());
48
10.0k
}
49
50
int cmXMLParser::InitializeParser()
51
10.0k
{
52
10.0k
  if (this->Parser) {
53
0
    std::cerr << "Parser already initialized" << std::endl;
54
0
    this->ParseError = 1;
55
0
    return 0;
56
0
  }
57
58
  // Create the expat XML parser.
59
10.0k
  this->Parser = XML_ParserCreate(nullptr);
60
10.0k
  XML_SetElementHandler(static_cast<XML_Parser>(this->Parser),
61
10.0k
                        &cmXMLParserStartElement, &cmXMLParserEndElement);
62
10.0k
  XML_SetCharacterDataHandler(static_cast<XML_Parser>(this->Parser),
63
10.0k
                              &cmXMLParserCharacterDataHandler);
64
10.0k
  XML_SetUserData(static_cast<XML_Parser>(this->Parser), this);
65
10.0k
  this->ParseError = 0;
66
10.0k
  return 1;
67
10.0k
}
68
69
int cmXMLParser::ParseChunk(const char* inputString,
70
                            std::string::size_type length)
71
10.0k
{
72
10.0k
  if (!this->Parser) {
73
0
    std::cerr << "Parser not initialized" << std::endl;
74
0
    this->ParseError = 1;
75
0
    return 0;
76
0
  }
77
10.0k
  int res;
78
10.0k
  res = this->ParseBuffer(inputString, length);
79
10.0k
  if (res == 0) {
80
2.98k
    this->ParseError = 1;
81
2.98k
  }
82
10.0k
  return res;
83
10.0k
}
84
85
int cmXMLParser::CleanupParser()
86
10.0k
{
87
10.0k
  if (!this->Parser) {
88
0
    std::cerr << "Parser not initialized" << std::endl;
89
0
    this->ParseError = 1;
90
0
    return 0;
91
0
  }
92
10.0k
  int result = !this->ParseError;
93
10.0k
  if (result) {
94
    // Tell the expat XML parser about the end-of-input.
95
7.03k
    if (!XML_Parse(static_cast<XML_Parser>(this->Parser), "", 0, 1)) {
96
4.92k
      this->ReportXmlParseError();
97
4.92k
      result = 0;
98
4.92k
    }
99
7.03k
  }
100
101
  // Clean up the parser.
102
10.0k
  XML_ParserFree(static_cast<XML_Parser>(this->Parser));
103
10.0k
  this->Parser = nullptr;
104
105
10.0k
  return result;
106
10.0k
}
107
108
int cmXMLParser::ParseBuffer(const char* buffer, std::string::size_type count)
109
10.0k
{
110
  // Pass the buffer to the expat XML parser.
111
10.0k
  if (!XML_Parse(static_cast<XML_Parser>(this->Parser), buffer,
112
10.0k
                 static_cast<int>(count), 0)) {
113
2.98k
    this->ReportXmlParseError();
114
2.98k
    return 0;
115
2.98k
  }
116
7.03k
  return 1;
117
10.0k
}
118
119
int cmXMLParser::ParseBuffer(const char* buffer)
120
0
{
121
0
  return this->ParseBuffer(buffer, static_cast<int>(strlen(buffer)));
122
0
}
123
124
int cmXMLParser::ParsingComplete()
125
0
{
126
  // Default behavior is to parse to end of stream.
127
0
  return 0;
128
0
}
129
130
void cmXMLParser::StartElement(const std::string& name, const char** /*atts*/)
131
2.37M
{
132
2.37M
  std::cout << "Start element: " << name << std::endl;
133
2.37M
}
134
135
void cmXMLParser::EndElement(const std::string& name)
136
179k
{
137
179k
  std::cout << "End element: " << name << std::endl;
138
179k
}
139
140
void cmXMLParser::CharacterDataHandler(const char* /*inData*/,
141
                                       int /*inLength*/)
142
6.54M
{
143
6.54M
}
144
145
const char* cmXMLParser::FindAttribute(const char** atts,
146
                                       const char* attribute)
147
0
{
148
0
  if (atts && attribute) {
149
0
    for (const char** a = atts; *a && *(a + 1); a += 2) {
150
0
      if (strcmp(*a, attribute) == 0) {
151
0
        return *(a + 1);
152
0
      }
153
0
    }
154
0
  }
155
0
  return nullptr;
156
0
}
157
158
void cmXMLParserStartElement(void* parser, const char* name, const char** atts)
159
2.37M
{
160
  // Begin element handler that is registered with the XML_Parser.
161
  // This just casts the user data to a cmXMLParser and calls
162
  // StartElement.
163
2.37M
  static_cast<cmXMLParser*>(parser)->StartElement(name, atts);
164
2.37M
}
165
166
void cmXMLParserEndElement(void* parser, const char* name)
167
179k
{
168
  // End element handler that is registered with the XML_Parser.  This
169
  // just casts the user data to a cmXMLParser and calls EndElement.
170
179k
  static_cast<cmXMLParser*>(parser)->EndElement(name);
171
179k
}
172
173
void cmXMLParserCharacterDataHandler(void* parser, const char* data,
174
                                     int length)
175
6.54M
{
176
  // Character data handler that is registered with the XML_Parser.
177
  // This just casts the user data to a cmXMLParser and calls
178
  // CharacterDataHandler.
179
6.54M
  static_cast<cmXMLParser*>(parser)->CharacterDataHandler(data, length);
180
6.54M
}
181
182
void cmXMLParser::ReportXmlParseError()
183
7.91k
{
184
7.91k
  XML_Parser parser = static_cast<XML_Parser>(this->Parser);
185
7.91k
  this->ReportError(static_cast<int>(XML_GetCurrentLineNumber(parser)),
186
7.91k
                    static_cast<int>(XML_GetCurrentColumnNumber(parser)),
187
7.91k
                    XML_ErrorString(XML_GetErrorCode(parser)));
188
7.91k
}
189
190
void cmXMLParser::ReportError(int line, int /*unused*/, const char* msg)
191
7.91k
{
192
7.91k
  if (this->ReportCallback) {
193
0
    this->ReportCallback(line, msg, this->ReportCallbackData);
194
7.91k
  } else {
195
7.91k
    std::cerr << "Error parsing XML in stream at line " << line << ": " << msg
196
7.91k
              << std::endl;
197
7.91k
  }
198
7.91k
}