Eclipse SUMO - Simulation of Urban MObility
SUMOSAXReader.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2012-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
16 // SAX-reader encapsulation containing binary reader
17 /****************************************************************************/
18 
19 
20 // ===========================================================================
21 // included modules
22 // ===========================================================================
23 #include <config.h>
24 
25 #include <string>
26 #include <memory>
27 #include <iostream>
28 #include <xercesc/sax2/XMLReaderFactory.hpp>
29 #include <xercesc/framework/LocalFileInputSource.hpp>
30 #include <xercesc/framework/MemBufInputSource.hpp>
31 
33 #include <utils/common/ToString.h>
38 #include "GenericSAXHandler.h"
39 #ifdef HAVE_ZLIB
40 #include <foreign/zstr/zstr.hpp>
41 #endif
42 #include "IStreamInputSource.h"
43 #include "SUMOSAXReader.h"
44 
45 
46 // ===========================================================================
47 // method definitions
48 // ===========================================================================
49 SUMOSAXReader::SUMOSAXReader(GenericSAXHandler& handler, const XERCES_CPP_NAMESPACE::SAX2XMLReader::ValSchemes validationScheme)
50  : myHandler(nullptr), myValidationScheme(validationScheme), myXMLReader(nullptr), myBinaryInput(nullptr), myIStream(nullptr), myInputStream(nullptr) {
51  setHandler(handler);
52 }
53 
54 
56  delete myXMLReader;
57  delete myBinaryInput;
58 }
59 
60 
61 void
63  myHandler = &handler;
65  if (myXMLReader != nullptr) {
66  myXMLReader->setContentHandler(&handler);
67  myXMLReader->setErrorHandler(&handler);
68  }
69 }
70 
71 
72 void
73 SUMOSAXReader::setValidation(const XERCES_CPP_NAMESPACE::SAX2XMLReader::ValSchemes validationScheme) {
74  if (myXMLReader != nullptr && validationScheme != myValidationScheme) {
75  if (validationScheme == XERCES_CPP_NAMESPACE::SAX2XMLReader::Val_Never) {
76  myXMLReader->setEntityResolver(nullptr);
77  myXMLReader->setProperty(XERCES_CPP_NAMESPACE::XMLUni::fgXercesScannerName, (void*)XERCES_CPP_NAMESPACE::XMLUni::fgWFXMLScanner);
78  } else {
79  myXMLReader->setEntityResolver(&mySchemaResolver);
80  myXMLReader->setProperty(XERCES_CPP_NAMESPACE::XMLUni::fgXercesScannerName, (void*)XERCES_CPP_NAMESPACE::XMLUni::fgIGXMLScanner);
81  myXMLReader->setFeature(XERCES_CPP_NAMESPACE::XMLUni::fgXercesSchema, true);
82  myXMLReader->setFeature(XERCES_CPP_NAMESPACE::XMLUni::fgSAX2CoreValidation, true);
83  myXMLReader->setFeature(XERCES_CPP_NAMESPACE::XMLUni::fgXercesDynamic, validationScheme == XERCES_CPP_NAMESPACE::SAX2XMLReader::Val_Auto);
84  }
85  }
86  myValidationScheme = validationScheme;
87 }
88 
89 
90 void
91 SUMOSAXReader::parse(std::string systemID) {
92  if (systemID.length() >= 4 && systemID.substr(systemID.length() - 4) == ".sbx") {
93  if (parseFirst(systemID)) {
94  while (parseNext());
95  }
96  } else {
97  if (myXMLReader == nullptr) {
99  }
100  if (!FileHelpers::isReadable(systemID)) {
101  throw ProcessError("Cannot read file '" + systemID + "'!");
102  }
103  if (FileHelpers::isDirectory(systemID)) {
104  throw ProcessError("File '" + systemID + "' is a directory!");
105  }
106 #ifdef HAVE_ZLIB
107  zstr::ifstream istream(systemID.c_str(), std::fstream::in | std::fstream::binary);
108  myXMLReader->parse(IStreamInputSource(istream));
109 #else
110  myXMLReader->parse(systemID.c_str());
111 #endif
112  }
113 }
114 
115 
116 void
117 SUMOSAXReader::parseString(std::string content) {
118  if (myXMLReader == nullptr) {
120  }
121  XERCES_CPP_NAMESPACE::MemBufInputSource memBufIS((const XMLByte*)content.c_str(), content.size(), "registrySettings");
122  myXMLReader->parse(memBufIS);
123 }
124 
125 
126 bool
127 SUMOSAXReader::parseFirst(std::string systemID) {
128  if (systemID.length() >= 4 && systemID.substr(systemID.length() - 4) == ".sbx") {
129  myBinaryInput = new BinaryInputDevice(systemID, true, myValidationScheme == XERCES_CPP_NAMESPACE::SAX2XMLReader::Val_Always);
131  if (mySbxVersion < 1 || mySbxVersion > 2) {
132  throw ProcessError("Unknown sbx version");
133  }
134  std::string sumoVer;
135  *myBinaryInput >> sumoVer;
136  std::vector<std::string> elems;
137  *myBinaryInput >> elems;
138  // !!! check elems here
139  elems.clear();
140  *myBinaryInput >> elems;
141  // !!! check attrs here
142  elems.clear();
143  *myBinaryInput >> elems;
144  // !!! check node types here
145  elems.clear();
146  *myBinaryInput >> elems;
147  // !!! check edge types here
148  elems.clear();
149  *myBinaryInput >> elems;
150  // !!! check edges here
151  std::vector< std::vector<int> > followers;
152  *myBinaryInput >> followers;
153  // !!! check followers here
154  return parseNext();
155  } else {
156  if (!FileHelpers::isReadable(systemID)) {
157  throw ProcessError("Cannot read file '" + systemID + "'!");
158  }
159  if (myXMLReader == nullptr) {
161  }
162  myToken = XERCES_CPP_NAMESPACE::XMLPScanToken();
163 #ifdef HAVE_ZLIB
164  myIStream = std::unique_ptr<zstr::ifstream>(new zstr::ifstream(systemID.c_str(), std::fstream::in | std::fstream::binary));
165  myInputStream = std::unique_ptr<IStreamInputSource>(new IStreamInputSource(*myIStream));
166  return myXMLReader->parseFirst(*myInputStream, myToken);
167 #else
168  return myXMLReader->parseFirst(systemID.c_str(), myToken);
169 #endif
170  }
171 }
172 
173 
174 bool
176  if (myBinaryInput != nullptr) {
177  int next = myBinaryInput->peek();
178  switch (next) {
179  case EOF:
180  delete myBinaryInput;
181  myBinaryInput = nullptr;
182  return false;
184  int tag;
185  unsigned char tagByte;
186  *myBinaryInput >> tagByte;
187  tag = tagByte;
188  if (mySbxVersion > 1) {
190  *myBinaryInput >> tagByte;
191  tag += 256 * tagByte;
192  }
193  myXMLStack.push_back((SumoXMLTag)tag);
195  myHandler->myStartElement(tag, attrs);
196  break;
197  }
199  if (myXMLStack.empty()) {
200  throw ProcessError("Binary file is invalid, unexpected tag end.");
201  }
203  myXMLStack.pop_back();
204  myBinaryInput->read(mySbxVersion > 1 ? 1 : 2);
205  break;
206  }
207  default:
208  throw ProcessError("Binary file is invalid, expected tag start or tag end.");
209  }
210  return true;
211  } else {
212  if (myXMLReader == nullptr) {
213  throw ProcessError("The XML-parser was not initialized.");
214  }
215  return myXMLReader->parseNext(myToken);
216  }
217 }
218 
219 
220 XERCES_CPP_NAMESPACE::SAX2XMLReader*
222  XERCES_CPP_NAMESPACE::SAX2XMLReader* reader = XERCES_CPP_NAMESPACE::XMLReaderFactory::createXMLReader();
223  if (reader == nullptr) {
224  throw ProcessError("The XML-parser could not be build.");
225  }
226  // see here https://svn.apache.org/repos/asf/xerces/c/trunk/samples/src/SAX2Count/SAX2Count.cpp for the way to set features
227  if (myValidationScheme == XERCES_CPP_NAMESPACE::SAX2XMLReader::Val_Never) {
228  reader->setProperty(XERCES_CPP_NAMESPACE::XMLUni::fgXercesScannerName, (void*)XERCES_CPP_NAMESPACE::XMLUni::fgWFXMLScanner);
229  } else {
230  reader->setEntityResolver(&mySchemaResolver);
231  reader->setFeature(XERCES_CPP_NAMESPACE::XMLUni::fgXercesSchema, true);
232  reader->setFeature(XERCES_CPP_NAMESPACE::XMLUni::fgSAX2CoreValidation, true);
233  reader->setFeature(XERCES_CPP_NAMESPACE::XMLUni::fgXercesDynamic, myValidationScheme == XERCES_CPP_NAMESPACE::SAX2XMLReader::Val_Auto);
234  }
235  reader->setContentHandler(myHandler);
236  reader->setErrorHandler(myHandler);
237  return reader;
238 }
239 
240 
241 XERCES_CPP_NAMESPACE::InputSource*
242 SUMOSAXReader::LocalSchemaResolver::resolveEntity(const XMLCh* const /* publicId */, const XMLCh* const systemId) {
243  const std::string url = StringUtils::transcode(systemId);
244  const std::string::size_type pos = url.find("/xsd/");
245  if (pos != std::string::npos) {
247  const char* sumoPath = std::getenv("SUMO_HOME");
248  if (sumoPath == nullptr) {
249  WRITE_WARNING("Environment variable SUMO_HOME is not set, schema resolution will use slow website lookups.");
250  return nullptr;
251  }
252  const std::string file = sumoPath + std::string("/data") + url.substr(pos);
253  if (FileHelpers::isReadable(file)) {
254  XMLCh* t = XERCES_CPP_NAMESPACE::XMLString::transcode(file.c_str());
255  XERCES_CPP_NAMESPACE::InputSource* const result = new XERCES_CPP_NAMESPACE::LocalFileInputSource(t);
256  XERCES_CPP_NAMESPACE::XMLString::release(&t);
257  return result;
258  } else {
259  WRITE_WARNING("Cannot read local schema '" + file + "', will try website lookup.");
260  }
261  }
262  return nullptr;
263 }
264 
265 
266 void
268  myHandler = &handler;
269 }
270 
271 
272 /****************************************************************************/
GenericSAXHandler.h
ToString.h
WRITE_WARNING
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:275
SUMOSAXReader::myIStream
std::unique_ptr< std::istream > myIStream
Definition: SUMOSAXReader.h:119
SUMOSAXReader::setValidation
void setValidation(const XERCES_CPP_NAMESPACE::SAX2XMLReader::ValSchemes validationScheme)
Definition: SUMOSAXReader.cpp:73
MsgHandler.h
BinaryFormatter::BF_XML_TAG_START
Definition: BinaryFormatter.h:69
SUMOSAXReader::parseNext
bool parseNext()
Definition: SUMOSAXReader.cpp:175
SUMOSAXReader::setHandler
void setHandler(GenericSAXHandler &handler)
Sets the given handler as content and error handler for the reader.
Definition: SUMOSAXReader.cpp:62
SUMOSAXReader::myBinaryInput
BinaryInputDevice * myBinaryInput
Definition: SUMOSAXReader.h:117
SUMOSAXReader::~SUMOSAXReader
~SUMOSAXReader()
Destructor.
Definition: SUMOSAXReader.cpp:55
GenericSAXHandler::myStartElement
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Callback method for an opening tag to implement by derived classes.
Definition: GenericSAXHandler.cpp:217
BinaryFormatter::BF_BYTE
Definition: BinaryFormatter.h:59
BinaryFormatter::BF_XML_TAG_END
Definition: BinaryFormatter.h:71
SumoXMLTag
SumoXMLTag
Numbers representing SUMO-XML - element names.
Definition: SUMOXMLDefinitions.h:41
GenericSAXHandler::myPredefinedTagsMML
std::map< int, std::string > myPredefinedTagsMML
the map from ids to their string representation
Definition: GenericSAXHandler.h:291
BinaryInputDevice::putback
void putback(char c)
Pushes a character back into the stream to be read by the next actual parse.
Definition: BinaryInputDevice.cpp:68
SUMOSAXAttributesImpl_Binary.h
BinaryInputDevice.h
SUMOSAXReader::myValidationScheme
XERCES_CPP_NAMESPACE::SAX2XMLReader::ValSchemes myValidationScheme
Information whether built reader/parser shall validate XML-documents against schemata.
Definition: SUMOSAXReader.h:111
IStreamInputSource.h
SUMOSAXAttributesImpl_Binary
Encapsulated Xerces-SAX-attributes.
Definition: SUMOSAXAttributesImpl_Binary.h:47
ProcessError
Definition: UtilExceptions.h:39
zstr::ifstream
Definition: zstr.hpp:372
SUMOSAXReader::getSAXReader
XERCES_CPP_NAMESPACE::SAX2XMLReader * getSAXReader()
Builds a reader.
Definition: SUMOSAXReader.cpp:221
GenericSAXHandler::myEndElement
virtual void myEndElement(int element)
Callback method for a closing tag to implement by derived classes.
Definition: GenericSAXHandler.cpp:225
SUMOSAXReader::LocalSchemaResolver::setHandler
void setHandler(GenericSAXHandler &handler)
Definition: SUMOSAXReader.cpp:267
IStreamInputSource
Xerces InputSource reading from arbitrary std::istream.
Definition: IStreamInputSource.h:60
SUMOSAXReader::parseFirst
bool parseFirst(std::string systemID)
Definition: SUMOSAXReader.cpp:127
SUMOSAXReader::myToken
XERCES_CPP_NAMESPACE::XMLPScanToken myToken
Definition: SUMOSAXReader.h:113
SUMOSAXReader::parse
void parse(std::string systemID)
Definition: SUMOSAXReader.cpp:91
SUMOSAXReader::parseString
void parseString(std::string content)
Definition: SUMOSAXReader.cpp:117
SUMOSAXReader::myInputStream
std::unique_ptr< IStreamInputSource > myInputStream
Definition: SUMOSAXReader.h:121
SUMOSAXReader::mySbxVersion
char mySbxVersion
Definition: SUMOSAXReader.h:123
SUMOSAXReader::myHandler
GenericSAXHandler * myHandler
Definition: SUMOSAXReader.h:108
toString
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:47
StringUtils.h
StringUtils::transcode
static std::string transcode(const XMLCh *const data)
converts a 0-terminated XMLCh* array (usually UTF-16, stemming from Xerces) into std::string in UTF-8
Definition: StringUtils.h:136
SUMOSAXReader::LocalSchemaResolver::myHandler
GenericSAXHandler * myHandler
Definition: SUMOSAXReader.h:90
transcode
std::string transcode(const XMLCh *const qname)
Definition: VehicleEngineHandler.cpp:37
SUMOSAXReader::SUMOSAXReader
SUMOSAXReader(GenericSAXHandler &handler, const XERCES_CPP_NAMESPACE::SAX2XMLReader::ValSchemes validationScheme)
Constructor.
Definition: SUMOSAXReader.cpp:49
BinaryInputDevice::peek
int peek()
Returns the next character to be read by an actual parse.
Definition: BinaryInputDevice.cpp:55
FileHelpers::isDirectory
static bool isDirectory(std::string path)
Checks whether the given file is a directory.
Definition: FileHelpers.cpp:63
FileHelpers::isReadable
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:49
config.h
SUMOSAXReader.h
SUMOSAXReader::myXMLReader
XERCES_CPP_NAMESPACE::SAX2XMLReader * myXMLReader
Definition: SUMOSAXReader.h:115
SUMOSAXReader::myXMLStack
std::vector< SumoXMLTag > myXMLStack
The stack of begun xml elements.
Definition: SUMOSAXReader.h:126
GenericSAXHandler::setSchemaSeen
void setSchemaSeen(const bool schemaSeen=true)
Definition: GenericSAXHandler.h:254
GenericSAXHandler
A handler which converts occuring elements and attributes into enums.
Definition: GenericSAXHandler.h:67
BinaryInputDevice::read
std::string read(int numBytes)
Reads the defined number of bytes and returns them as a string.
Definition: BinaryInputDevice.cpp:61
zstr.hpp
SUMOSAXReader::LocalSchemaResolver::resolveEntity
XERCES_CPP_NAMESPACE::InputSource * resolveEntity(const XMLCh *const publicId, const XMLCh *const systemId)
Definition: SUMOSAXReader.cpp:242
BinaryFormatter.h
BinaryInputDevice
Encapsulates binary reading operations on a file.
Definition: BinaryInputDevice.h:57
SUMOSAXReader::mySchemaResolver
LocalSchemaResolver mySchemaResolver
Definition: SUMOSAXReader.h:128