Prefer to use VS2013 for compiling and testing on AppVeyor
[TortoiseGit.git] / ext / OGDF / src / fileformats / DinoXmlScanner.cpp
blobd8f8e6518933855a3438514eb732c66d726291de
1 /*
2 * $Revision: 2565 $
4 * last checkin:
5 * $Author: gutwenger $
6 * $Date: 2012-07-07 17:14:54 +0200 (Sa, 07. Jul 2012) $
7 ***************************************************************/
9 /** \file
10 * \brief Implementation of the class DinoXmlScanner serving the
11 * class DinoXmlParser
13 * \author Dino Ahr
15 * \par License:
16 * This file is part of the Open Graph Drawing Framework (OGDF).
18 * \par
19 * Copyright (C)<br>
20 * See README.txt in the root directory of the OGDF installation for details.
22 * \par
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * Version 2 or 3 as published by the Free Software Foundation;
26 * see the file LICENSE.txt included in the packaging of this file
27 * for details.
29 * \par
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
35 * \par
36 * You should have received a copy of the GNU General Public
37 * License along with this program; if not, write to the Free
38 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
39 * Boston, MA 02110-1301, USA.
41 * \see http://www.gnu.org/copyleft/gpl.html
42 ***************************************************************/
45 #include <ogdf/fileformats/DinoXmlScanner.h>
47 #include <ctype.h>
48 #include <string.h>
50 extern ofstream os;
52 namespace ogdf {
55 // C o n s t r u c t o r
57 DinoXmlScanner::DinoXmlScanner(const char *fileName)
59 // Create line buffer
60 m_pLineBuffer = new DinoLineBuffer(fileName);
62 // Create current token string
63 m_pCurrentTokenString = new char[DinoLineBuffer::c_maxStringLength];
64 if (m_pCurrentTokenString == 0)
65 OGDF_THROW(InsufficientMemoryException);
66 for (int i = 0; i < DinoLineBuffer::c_maxStringLength; i++){
67 m_pCurrentTokenString[i] = '0';
70 } // DinoXmlScanner::DinoXmlScanner
73 // D e s t r u c t o r
75 DinoXmlScanner::~DinoXmlScanner()
77 // Destroy current token string
78 delete [] m_pCurrentTokenString;
80 // Destroy line buffer
81 delete m_pLineBuffer;
83 } // DinoXmlScanner::~DinoXmlScanner
86 // g e t N e x t T o k e n
88 // Take a look at the state machine of getNextToken() to understand
89 // what is going on here.
91 // TODO: It seems to be useful that this function throws an exception
92 // if something goes wrong.
93 XmlToken DinoXmlScanner::getNextToken(){
95 // First skip whitespaces
96 m_pLineBuffer->skipWhitespace();
98 // Let's have a look at the current character
99 char currentCharacter = m_pLineBuffer->getCurrentCharacter();
101 // End of file reached
102 if (currentCharacter == EOF){
103 return endOfFile;
106 // First we handle single characters with a switch statement
107 switch (currentCharacter){
109 // Opening Bracket
110 case '<':
112 m_pLineBuffer->moveToNextCharacter();
113 return openingBracket;
115 break;
117 // Closing Bracket
118 case '>':
120 m_pLineBuffer->moveToNextCharacter();
121 return closingBracket;
123 break;
125 // Question Mark
126 case '?':
128 m_pLineBuffer->moveToNextCharacter();
129 return questionMark;
131 break;
133 // Exclamation Mark
134 case '!':
136 m_pLineBuffer->moveToNextCharacter();
137 return exclamationMark;
139 break;
141 // Minus
142 case '-':
144 m_pLineBuffer->moveToNextCharacter();
145 return minus;
147 break;
149 // Slash
150 case '/':
152 m_pLineBuffer->moveToNextCharacter();
153 return slash;
155 break;
157 // Equal Sign
158 case '=':
160 m_pLineBuffer->moveToNextCharacter();
161 return equalSign;
163 break;
165 } // end of switch
167 // Now we handle more complex token
169 // Identifier
170 if (isalpha(currentCharacter)){
172 // Put a pointer to the beginning of the identifier
173 DinoLineBufferPosition startPosition = m_pLineBuffer->getCurrentPosition();
175 currentCharacter = m_pLineBuffer->moveToNextCharacter();
177 // Read valid identifier characters
178 while ((isalnum(currentCharacter)) || // a..z|A..Z|0..9
179 (currentCharacter == '.') ||
180 (currentCharacter == ':') ||
181 (currentCharacter == '_'))
183 currentCharacter = m_pLineBuffer->moveToNextCharacter();
186 // Copy identifier to currentTokenString
187 m_pLineBuffer->extractString(startPosition,
188 m_pLineBuffer->getCurrentPosition(),
189 m_pCurrentTokenString);
191 // Return identifier token
192 return identifier;
194 } // end of identifier
196 // Quoted characters " ... " or ' ... '
197 if ((currentCharacter == '\"') ||
198 (currentCharacter == '\''))
200 // Distinguish what kind of quote sign we have
201 bool doubleQuote;
202 if (currentCharacter == '\"')
203 doubleQuote = true;
204 else
205 doubleQuote = false;
207 // Skip quote sign
208 currentCharacter = m_pLineBuffer->moveToNextCharacter();
210 // Read until the closing quotation sign is found
211 // String is copied to m_pCurrentTokenString by readStringUntil()
212 if (doubleQuote){
213 readStringUntil('\"', false);
215 else{
216 readStringUntil('\'', false);
219 // Skip over the end quote character
220 m_pLineBuffer->moveToNextCharacter();
222 // Return token for quoted value
223 return quotedValue;
225 } // end of quoted characters
227 // An atributeValue, i.e. a sequence of characters, digits, minus - or dot .
228 if ((isalnum(currentCharacter)) ||
229 (currentCharacter == '-') ||
230 (currentCharacter == '.'))
232 // Put a pointer to the beginning of the quoted text
233 DinoLineBufferPosition startPosition = m_pLineBuffer->getCurrentPosition();;
235 // Read until until an invalid character occurs
236 currentCharacter = m_pLineBuffer->moveToNextCharacter();
237 while ((isalnum(currentCharacter)) ||
238 (currentCharacter == '-') ||
239 (currentCharacter == '.'))
241 currentCharacter = m_pLineBuffer->moveToNextCharacter();
244 // Copy attributeValue to currentTokenString
245 m_pLineBuffer->extractString(startPosition,
246 m_pLineBuffer->getCurrentPosition(),
247 m_pCurrentTokenString);
249 // Return token for attribute value
250 return attributeValue;
252 } // end of an attributeValue
254 // No valid token
255 m_pLineBuffer->moveToNextCharacter();
256 return invalidToken;
258 } // getNextToken
261 // t e s t N e x t T o k e n
263 XmlToken DinoXmlScanner::testNextToken(){
265 // Save pointer to the current position
266 DinoLineBufferPosition originalPosition = m_pLineBuffer->getCurrentPosition();
268 // Call getNextToken()
269 XmlToken returnToken = getNextToken();
271 // Set pointer back to the original position
272 m_pLineBuffer->setCurrentPosition(originalPosition);
274 // Return token
275 return returnToken;
277 } // testNextToken
280 // t e s t N e x t N e x t T o k e n
282 XmlToken DinoXmlScanner::testNextNextToken(){
284 // Save pointer to the current position
285 DinoLineBufferPosition originalPosition = m_pLineBuffer->getCurrentPosition();
287 // Call getNextToken()
288 getNextToken();
290 // Again Call getNextToken()
291 XmlToken returnToken = getNextToken();
293 // Set pointer back to the original position
294 m_pLineBuffer->setCurrentPosition(originalPosition);
296 // Return token
297 return returnToken;
299 } // testNextNextToken
302 // s k i p U n t i l
304 bool DinoXmlScanner::skipUntil(char searchCharacter, bool skipOverSearchCharacter){
306 while (m_pLineBuffer->getCurrentCharacter() != EOF){
308 // Search character has been found!
309 if (m_pLineBuffer->getCurrentCharacter() == searchCharacter){
311 // Move to the position behind the search character if desired
312 if (skipOverSearchCharacter){
313 m_pLineBuffer->moveToNextCharacter();
316 return true;
318 } // Search character has been found!
320 // Move to next character and proceed
321 m_pLineBuffer->moveToNextCharacter();
323 } // while (!EOF)
325 return false;
327 } // skipUntil
330 // s k i p U n t i l M a t c h i n g C l o s i n g B r a c k e t
332 bool DinoXmlScanner::skipUntilMatchingClosingBracket(){
334 // We assume that the opening bracket has already been read
335 int bracketParity = 1;
337 while ((m_pLineBuffer->getCurrentCharacter() != EOF) &&
338 (bracketParity != 0))
340 // Opening bracket has been found!
341 if (m_pLineBuffer->getCurrentCharacter() == '<'){
343 ++bracketParity;
346 // Closing bracket has been found!
347 if (m_pLineBuffer->getCurrentCharacter() == '>'){
349 --bracketParity;
352 // Move to next character and proceed
353 m_pLineBuffer->moveToNextCharacter();
355 } // while
357 if (bracketParity != 0 )
358 return false;
359 else
360 return true;
362 } // skipUntilMatchingClosingBracket
365 // r e a d S t r i n g U n t i l
367 bool DinoXmlScanner::readStringUntil(char searchCharacter,
368 bool includeSearchCharacter){
370 // Remember start position
371 DinoLineBufferPosition startPosition = m_pLineBuffer->getCurrentPosition();
373 // Use skipUntil()
374 if (skipUntil(searchCharacter, includeSearchCharacter)){
376 // Copy found string to m_pCurrentTokenString
377 m_pLineBuffer->extractString(startPosition,
378 m_pLineBuffer->getCurrentPosition(),
379 m_pCurrentTokenString);
381 return true;
384 // An error occurred
385 else{
386 return false;
389 } // getStringUntil
392 // t e s t
394 void DinoXmlScanner::test(){
396 bool terminate = false;
397 XmlToken currentToken;
399 while (!terminate){
401 cout << "Line " << getInputFileLineCounter() << ": ";
402 currentToken = getNextToken();
404 switch (currentToken){
405 case openingBracket:
406 cout << "<" << endl;
407 break;
408 case closingBracket:
409 cout << ">" << endl;
410 break;
411 case questionMark:
412 cout << "?" << endl;
413 break;
414 case exclamationMark:
415 cout << "!" << endl;
416 break;
417 case minus:
418 cout << "-" << endl;
419 break;
420 case slash:
421 cout << "/" << endl;
422 break;
423 case equalSign:
424 cout << "<" << endl;
425 break;
426 case identifier:
427 cout << "Identifier: " << m_pCurrentTokenString << endl;
428 break;
429 case attributeValue:
430 cout << "Attribute value: " << m_pCurrentTokenString << endl;
431 break;
432 case quotedValue:
433 cout << "Quoted value: \"" << m_pCurrentTokenString << "\"" << endl;
434 break;
435 case endOfFile:
436 cout << "EOF" << endl;
437 terminate = true;
438 break;
439 default:
440 cout << "Invalid token!" << endl;
442 } // switch
444 } // while
446 } // testScanner
448 } // namespace ogdf