packaging: Initial packaging
[platform/upstream/cmake.git] / Source / cmXMLParser.cxx
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4
5   Distributed under the OSI-approved BSD License (the "License");
6   see accompanying file Copyright.txt for details.
7
8   This software is distributed WITHOUT ANY WARRANTY; without even the
9   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   See the License for more information.
11 ============================================================================*/
12 #include "cmXMLParser.h"
13
14 #include <cm_expat.h>
15 #include <ctype.h>
16
17 //----------------------------------------------------------------------------
18 cmXMLParser::cmXMLParser()
19 {
20   this->Parser = 0;
21   this->ParseError = 0;
22 }
23
24 //----------------------------------------------------------------------------
25 cmXMLParser::~cmXMLParser()
26 {
27   if ( this->Parser )
28     {
29     this->CleanupParser();
30     }
31 }
32
33 //----------------------------------------------------------------------------
34 int cmXMLParser::Parse(const char* string)
35 {
36   return (int)this->InitializeParser() &&
37     this->ParseChunk(string, strlen(string)) &&
38     this->CleanupParser();
39 }
40
41 int cmXMLParser::ParseFile(const char* file)
42 {
43   if ( !file )
44     {
45     return 0;
46     }
47
48   std::ifstream ifs(file);
49   if ( !ifs )
50     {
51     return 0;
52     }
53
54   cmOStringStream str;
55   str << ifs.rdbuf();
56   return this->Parse(str.str().c_str());
57 }
58
59 //----------------------------------------------------------------------------
60 int cmXMLParser::InitializeParser()
61 {
62   if ( this->Parser )
63     {
64     std::cerr << "Parser already initialized" << std::endl;
65     this->ParseError = 1;
66     return 0;
67     }
68
69   // Create the expat XML parser.
70   this->Parser = XML_ParserCreate(0);
71   XML_SetElementHandler(static_cast<XML_Parser>(this->Parser),
72                         &cmXMLParserStartElement,
73                         &cmXMLParserEndElement);
74   XML_SetCharacterDataHandler(static_cast<XML_Parser>(this->Parser),
75                               &cmXMLParserCharacterDataHandler);
76   XML_SetUserData(static_cast<XML_Parser>(this->Parser), this);
77   this->ParseError = 0;
78   return 1;
79 }
80
81 //----------------------------------------------------------------------------
82 int cmXMLParser::ParseChunk(const char* inputString,
83                             std::string::size_type length)
84 {
85   if ( !this->Parser )
86     {
87     std::cerr << "Parser not initialized" << std::endl;
88     this->ParseError = 1;
89     return 0;
90     }
91   int res;
92   res = this->ParseBuffer(inputString, length);
93   if ( res == 0 )
94     {
95     this->ParseError = 1;
96     }
97   return res;
98 }
99
100 //----------------------------------------------------------------------------
101 int cmXMLParser::CleanupParser()
102 {
103   if ( !this->Parser )
104     {
105     std::cerr << "Parser not initialized" << std::endl;
106     this->ParseError = 1;
107     return 0;
108     }
109   int result = !this->ParseError;
110   if(result)
111     {
112     // Tell the expat XML parser about the end-of-input.
113     if(!XML_Parse(static_cast<XML_Parser>(this->Parser), "", 0, 1))
114       {
115       this->ReportXmlParseError();
116       result = 0;
117       }
118     }
119
120   // Clean up the parser.
121   XML_ParserFree(static_cast<XML_Parser>(this->Parser));
122   this->Parser = 0;
123
124   return result;
125 }
126
127 //----------------------------------------------------------------------------
128 int cmXMLParser::ParseBuffer(const char* buffer, std::string::size_type count)
129 {
130   // Pass the buffer to the expat XML parser.
131   if(!XML_Parse(static_cast<XML_Parser>(this->Parser), buffer,
132                 static_cast<int>(count), 0))
133     {
134     this->ReportXmlParseError();
135     return 0;
136     }
137   return 1;
138 }
139
140 //----------------------------------------------------------------------------
141 int cmXMLParser::ParseBuffer(const char* buffer)
142 {
143   return this->ParseBuffer(buffer, static_cast<int>(strlen(buffer)));
144 }
145
146 //----------------------------------------------------------------------------
147 int cmXMLParser::ParsingComplete()
148 {
149   // Default behavior is to parse to end of stream.
150   return 0;
151 }
152
153 //----------------------------------------------------------------------------
154 void cmXMLParser::StartElement(const char * name,
155   const char ** /*atts*/)
156 {
157   std::cout << "Start element: " << name << std::endl;
158 }
159
160 //----------------------------------------------------------------------------
161 void cmXMLParser::EndElement(const char * name)
162 {
163   std::cout << "End element: " << name << std::endl;
164 }
165
166 //----------------------------------------------------------------------------
167 void cmXMLParser::CharacterDataHandler(const char* /*inData*/,
168   int /*inLength*/)
169 {
170 }
171
172 //----------------------------------------------------------------------------
173 int cmXMLParser::IsSpace(char c)
174 {
175   return isspace(c);
176 }
177
178 //----------------------------------------------------------------------------
179 const char* cmXMLParser::FindAttribute(const char** atts,
180                                        const char* attribute)
181 {
182   if(atts && attribute)
183     {
184     for(const char** a = atts; *a && *(a+1); a += 2)
185       {
186       if(strcmp(*a, attribute) == 0)
187         {
188         return *(a+1);
189         }
190       }
191     }
192   return 0;
193 }
194
195 //----------------------------------------------------------------------------
196 void cmXMLParserStartElement(void* parser, const char *name,
197                               const char **atts)
198 {
199   // Begin element handler that is registered with the XML_Parser.
200   // This just casts the user data to a cmXMLParser and calls
201   // StartElement.
202   static_cast<cmXMLParser*>(parser)->StartElement(name, atts);
203 }
204
205 //----------------------------------------------------------------------------
206 void cmXMLParserEndElement(void* parser, const char *name)
207 {
208   // End element handler that is registered with the XML_Parser.  This
209   // just casts the user data to a cmXMLParser and calls EndElement.
210   static_cast<cmXMLParser*>(parser)->EndElement(name);
211 }
212
213 //----------------------------------------------------------------------------
214 void cmXMLParserCharacterDataHandler(void* parser, const char* data,
215                                       int length)
216 {
217   // Character data handler that is registered with the XML_Parser.
218   // This just casts the user data to a cmXMLParser and calls
219   // CharacterDataHandler.
220   static_cast<cmXMLParser*>(parser)->CharacterDataHandler(data, length);
221 }
222
223 //----------------------------------------------------------------------------
224 void cmXMLParser::ReportXmlParseError()
225 {
226   XML_Parser parser = static_cast<XML_Parser>(this->Parser);
227   this->ReportError(XML_GetCurrentLineNumber(parser),
228                     XML_GetCurrentColumnNumber(parser),
229                     XML_ErrorString(XML_GetErrorCode(parser)));
230 }
231
232 //----------------------------------------------------------------------------
233 void cmXMLParser::ReportError(int line, int, const char* msg)
234 {
235   std::cerr << "Error parsing XML in stream at line "
236             << line << ": " << msg << std::endl;
237 }