0026576: Wrong result obtained by intersection algorithm.
[occt.git] / src / LDOM / LDOMParser.cxx
CommitLineData
b311480e 1// Created on: 2001-07-20
2// Created by: Alexander GRIGORIEV
973c2be1 3// Copyright (c) 2001-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
b311480e 15
16//AGV 060302: Input from istream
7fd59977 17// AGV 130302: Return error if there are data after the root element
18
19//#define LDOM_PARSER_TRACE
20
21#include <LDOMParser.hxx>
22#include <LDOM_MemManager.hxx>
23#include <LDOM_XmlReader.hxx>
24#include <LDOM_BasicText.hxx>
25#include <LDOM_CharReference.hxx>
d9ff84e8 26#include <TCollection_ExtendedString.hxx>
7fd59977 27
28#include <fcntl.h>
57c28b61 29#ifdef _MSC_VER
7fd59977 30#include <io.h>
31#else
32#include <unistd.h>
33#endif
34
35//=======================================================================
36//function : ~LDOMParser
37//purpose :
38//=======================================================================
39
40LDOMParser::~LDOMParser()
41{
42 if (myReader) delete myReader;
43}
44
45//=======================================================================
46//function : ReadRecord
47//purpose : Take the next lexical element from XML stream
48//=======================================================================
49
50#ifdef LDOM_PARSER_TRACE
51static
52#else
53inline
54#endif
55 LDOM_XmlReader::RecordType ReadRecord (LDOM_XmlReader& aReader,
56 LDOM_OSStream& aData)
57{
58#ifdef LDOM_PARSER_TRACE
59 static aCounter = 0;
60 ++ aCounter;
61#endif
62 const LDOM_XmlReader::RecordType aType = aReader.ReadRecord (aData);
63#ifdef LDOM_PARSER_TRACE
64 static FILE * ff = NULL;
65 TCollection_AsciiString aTraceFileName;
57c28b61 66#ifdef _WIN32
7fd59977 67 aTraceFileName = TCollection_AsciiString (getenv("TEMP")) + "\\ldom.trace";
68#else
69 aTraceFileName = "/tmp/ldom.trace";
70#endif
71 ff = fopen (aTraceFileName.ToCString(),ff ? "at": "wt");
72 const char * aDataType;
73 switch (aType) {
74 case LDOM_XmlReader::XML_UNKNOWN: aDataType= "XML_UNKNOWN "; break;
75 case LDOM_XmlReader::XML_HEADER: aDataType= "XML_HEADER "; break;
76 case LDOM_XmlReader::XML_DOCTYPE: aDataType= "XML_DOCTYPE "; break;
77 case LDOM_XmlReader::XML_COMMENT: aDataType= "XML_COMMENT "; break;
78 case LDOM_XmlReader::XML_START_ELEMENT: aDataType= "XML_START_ELEMENT"; break;
79 case LDOM_XmlReader::XML_END_ELEMENT: aDataType= "XML_END_ELEMENT "; break;
80 case LDOM_XmlReader::XML_FULL_ELEMENT: aDataType= "XML_FULL_ELEMENT "; break;
81 case LDOM_XmlReader::XML_TEXT: aDataType= "XML_TEXT "; break;
82 case LDOM_XmlReader::XML_CDATA: aDataType= "XML_CDATA "; break;
83 case LDOM_XmlReader::XML_EOF: aDataType= "XML_EOF ";
84 }
85 char * aStr = aData.str();
86 fprintf (ff, "%5d %s: %s\n", aCounter, aDataType, aStr);
87 delete [] aStr;
88 fclose (ff);
89#endif
90 return aType;
91}
92
93//=======================================================================
94//function : GetError
95//purpose : Return text describing a parsing error
96//=======================================================================
97
98const TCollection_AsciiString& LDOMParser::GetError
99 (TCollection_AsciiString& aData) const
100{
101 char * aStr =(char *)myCurrentData.str();
102 aData = aStr;
103 delete [] aStr;
104 return myError;
105}
106
107//=======================================================================
108//function : parse
109//purpose :
110//=======================================================================
111
112Standard_Boolean LDOMParser::parse (istream& anInput)
113{
114 // Open the DOM Document
115 myDocument = new LDOM_MemManager (20000);
116 myError.Clear();
117
118 // Create the Reader instance
119 if (myReader) delete myReader;
120 myReader = new LDOM_XmlReader (anInput, myDocument, myError);
121
122 // Parse
123 return ParseDocument();
124}
125
126//=======================================================================
127//function : parse
128//purpose :
129//=======================================================================
130
131Standard_Boolean LDOMParser::parse (const char * const aFileName)
132{
133 // Open the DOM Document
134 myDocument = new LDOM_MemManager (20000);
135 myError.Clear ();
136
137 // Open the file
d9ff84e8 138#ifdef _WIN32
139 TCollection_ExtendedString aFileNameW(aFileName, Standard_True);
140 int aFile = _wopen ((const wchar_t*) aFileNameW.ToExtString(), O_RDONLY);
141#else
7fd59977 142 int aFile = open (aFileName, O_RDONLY);
d9ff84e8 143#endif
7fd59977 144 if (aFile < 0) {
145 myError = "Fatal XML error: Cannot open XML file";
146 return Standard_True;
147 }
148
149 // Create the Reader instance
150 if (myReader) delete myReader;
151 myReader = new LDOM_XmlReader (aFile, myDocument, myError);
152
153 // Parse
154 Standard_Boolean isError = ParseDocument();
155 close (aFile);
156 return isError;
157}
158
159//=======================================================================
160//function : ParseDocument
161//purpose : parse the whole document (abstracted from the XML source)
162//=======================================================================
163
164Standard_Boolean LDOMParser::ParseDocument ()
165{
166 Standard_Boolean isError = Standard_False;
167 Standard_Boolean isElement = Standard_False;
7fd59977 168 Standard_Boolean isDoctype = Standard_False;
169
302f96fb 170 for(;;) {
7fd59977 171 LDOM_XmlReader::RecordType aType = ReadRecord (*myReader, myCurrentData);
172 switch (aType) {
173 case LDOM_XmlReader::XML_HEADER:
174 if (isDoctype || isElement) {
175 myError = "Unexpected XML declaration";
176 isError = Standard_True;
177 break;
178 }
7fd59977 179 continue;
180 case LDOM_XmlReader::XML_DOCTYPE:
181 if (isElement) {
182 myError = "Unexpected DOCTYPE declaration";
183 isError = Standard_True;
184 break;
185 }
186 isDoctype = Standard_True;
187 case LDOM_XmlReader::XML_COMMENT:
188 continue;
189 case LDOM_XmlReader::XML_FULL_ELEMENT:
190 if (isElement == Standard_False) {
191 isElement = Standard_True;
192 myDocument -> myRootElement = &myReader -> GetElement ();
193 if (startElement()) {
194 isError = Standard_True;
195 myError = "User abort at startElement()";
196 break;
197 }
198 if (endElement()) {
199 isError = Standard_True;
200 myError = "User abort at endElement()";
201 break;
202 }
203 continue;
204 }
205 case LDOM_XmlReader::XML_START_ELEMENT:
206 if (isElement == Standard_False) {
207 isElement = Standard_True;
208 myDocument -> myRootElement = &myReader -> GetElement ();
209 if (startElement()) {
210 isError = Standard_True;
211 myError = "User abort at startElement()";
212 break;
213 }
214 isError = ParseElement ();
215 if (isError) break;
216 continue;
217 }
218 isError = Standard_True;
219 myError = "Expected comment or end-of-file";
220 case LDOM_XmlReader::XML_END_ELEMENT:
221 if (endElement()) {
222 isError = Standard_True;
223 myError = "User abort at endElement()";
224 }
225 case LDOM_XmlReader::XML_EOF:
226 break;
227 case LDOM_XmlReader::XML_UNKNOWN:
228 if (isElement) {
229 default:
230 myError = "Unexpected data beyond the Document Element";
231 }
232 isError = Standard_True;
233 }
234 break;
235 }
236 return isError;
237}
238
239//=======================================================================
240//function : ParseElement
241//purpose : parse one element, given the type of its XML presentation
242//=======================================================================
243
244Standard_Boolean LDOMParser::ParseElement ()
245{
246 Standard_Boolean isError = Standard_False;
247 const LDOM_BasicElement * aParent = &myReader->GetElement();
248 const LDOM_BasicNode * aLastChild = NULL;
302f96fb 249 for(;;) {
7fd59977 250 LDOM_Node::NodeType aLocType;
251 LDOMBasicString aTextValue;
252 char *aTextStr;
253 LDOM_XmlReader::RecordType aType = ReadRecord (* myReader, myCurrentData);
254 switch (aType) {
255 case LDOM_XmlReader::XML_UNKNOWN:
256 isError = Standard_True;
257 break;
258 case LDOM_XmlReader::XML_FULL_ELEMENT:
259 aParent -> AppendChild (&myReader -> GetElement(), aLastChild);
260 if (startElement()) {
261 isError = Standard_True;
262 myError = "User abort at startElement()";
263 break;
264 }
265 if (endElement()) {
266 isError = Standard_True;
267 myError = "User abort at endElement()";
268 break;
269 }
270 break;
271 case LDOM_XmlReader::XML_START_ELEMENT:
272 aParent -> AppendChild (&myReader -> GetElement(), aLastChild);
273 if (startElement()) {
274 isError = Standard_True;
275 myError = "User abort at startElement()";
276 break;
277 }
278 isError = ParseElement ();
279 break;
280 case LDOM_XmlReader::XML_END_ELEMENT:
281 {
282 Standard_CString aParentName = Standard_CString(aParent->GetTagName());
283 aTextStr = (char *)myCurrentData.str();
284 if (strcmp(aTextStr, aParentName) != 0) {
285 myError = "Expected end tag \'";
286 myError += aParentName;
287 myError += "\'";
288 isError = Standard_True;
289 }
290 else if (endElement()) {
291 isError = Standard_True;
292 myError = "User abort at endElement()";
293 }
294 delete [] aTextStr;
295 }
296 return isError;
297 case LDOM_XmlReader::XML_TEXT:
298 aLocType = LDOM_Node::TEXT_NODE;
299 {
300 Standard_Integer aTextLen;
301 aTextStr = LDOM_CharReference::Decode ((char *)myCurrentData.str(), aTextLen);
302 // try to convert to integer
303 if (IsDigit(aTextStr[0])) {
304 if (LDOM_XmlReader::getInteger (aTextValue, aTextStr,
305 aTextStr + aTextLen))
306 aTextValue = LDOMBasicString (aTextStr, aTextLen, myDocument);
307 } else
308 aTextValue = LDOMBasicString (aTextStr, aTextLen, myDocument);
309 }
310 goto create_text_node;
311 case LDOM_XmlReader::XML_COMMENT:
312 aLocType = LDOM_Node::COMMENT_NODE;
313 {
314 Standard_Integer aTextLen;
315 aTextStr = LDOM_CharReference::Decode ((char *)myCurrentData.str(), aTextLen);
316 aTextValue = LDOMBasicString (aTextStr, aTextLen, myDocument);
317 }
318 goto create_text_node;
319 case LDOM_XmlReader::XML_CDATA:
320 aLocType = LDOM_Node::CDATA_SECTION_NODE;
321 aTextStr = (char *)myCurrentData.str();
322 aTextValue = LDOMBasicString(aTextStr,myCurrentData.Length(),myDocument);
323 create_text_node:
324 {
325 LDOM_BasicNode& aTextNode =
326 LDOM_BasicText::Create (aLocType, aTextValue, myDocument);
327 aParent -> AppendChild (&aTextNode, aLastChild);
328 }
329 delete [] aTextStr;
330 break;
331 case LDOM_XmlReader::XML_EOF:
332 myError = "Inexpected end of file";
333 isError = Standard_True;
334 break;
335 default: ;
336 }
337 if (isError) break;
338 }
339 return isError;
340}
341
342//=======================================================================
343//function : startElement
344//purpose : virtual hook on 'StartElement' event for descendant classes
345//=======================================================================
346
347Standard_Boolean LDOMParser::startElement ()
348{
349 return Standard_False;
350}
351
352//=======================================================================
353//function : endElement
354//purpose : virtual hook on 'EndElement' event for descendant classes
355//=======================================================================
356
357Standard_Boolean LDOMParser::endElement ()
358{
359 return Standard_False;
360}
361
362//=======================================================================
363//function : getCurrentElement
364//purpose :
365//=======================================================================
366
367LDOM_Element LDOMParser::getCurrentElement () const
368{
369 return LDOM_Element (myReader -> GetElement(), myDocument);
370}
371
372//=======================================================================
373//function : getDocument
374//purpose :
375//=======================================================================
376
377LDOM_Document LDOMParser::getDocument ()
378{
379 return myDocument -> Self();
380}
381