Line data Source code
1 : /****************************************************************************/ 2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo 3 : // Copyright (C) 2002-2024 German Aerospace Center (DLR) and others. 4 : // This program and the accompanying materials are made available under the 5 : // terms of the Eclipse Public License 2.0 which is available at 6 : // https://www.eclipse.org/legal/epl-2.0/ 7 : // This Source Code may also be made available under the following Secondary 8 : // Licenses when the conditions for such availability set forth in the Eclipse 9 : // Public License 2.0 are satisfied: GNU General Public License, version 2 10 : // or later which is available at 11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html 12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later 13 : /****************************************************************************/ 14 : /// @file GenericSAXHandler.cpp 15 : /// @author Daniel Krajzewicz 16 : /// @author Jakob Erdmann 17 : /// @author Michael Behrisch 18 : /// @author Laura Bieker 19 : /// @date Sept 2002 20 : /// 21 : // A handler which converts occurring elements and attributes into enums 22 : /****************************************************************************/ 23 : #include <config.h> 24 : 25 : #include <cassert> 26 : #include "GenericSAXHandler.h" 27 : #include <utils/common/StringUtils.h> 28 : #include <utils/common/StringUtils.h> 29 : #include <utils/common/FileHelpers.h> 30 : #include <utils/common/MsgHandler.h> 31 : #include <utils/common/ToString.h> 32 : #include "SUMOSAXAttributesImpl_Xerces.h" 33 : #include "XMLSubSys.h" 34 : 35 : 36 : // =========================================================================== 37 : // class definitions 38 : // =========================================================================== 39 157919 : GenericSAXHandler::GenericSAXHandler( 40 : StringBijection<int>::Entry* tags, int terminatorTag, 41 : StringBijection<int>::Entry* attrs, int terminatorAttr, 42 157919 : const std::string& file, const std::string& expectedRoot) 43 157919 : : myParentHandler(nullptr), myParentIndicator(SUMO_TAG_NOTHING), myFileName(file), 44 473757 : myExpectedRoot(expectedRoot), myNextSectionStart(-1, nullptr) { 45 : int i = 0; 46 47834231 : while (tags[i].key != terminatorTag) { 47 47676312 : myTagMap.insert(TagMap::value_type(tags[i].str, tags[i].key)); 48 47676312 : i++; 49 : } 50 : i = 0; 51 104982085 : while (attrs[i].key != terminatorAttr) { 52 : int key = attrs[i].key; 53 : assert(key >= 0); 54 211069171 : while (key >= (int)myPredefinedTags.size()) { 55 106245005 : myPredefinedTags.push_back(nullptr); 56 212490010 : myPredefinedTagsMML.push_back(""); 57 : } 58 104824166 : myPredefinedTags[key] = convert(attrs[i].str); 59 104824166 : myPredefinedTagsMML[key] = attrs[i].str; 60 104824166 : i++; 61 : } 62 157919 : } 63 : 64 : 65 157466 : GenericSAXHandler::~GenericSAXHandler() { 66 106097602 : for (AttrMap::iterator i1 = myPredefinedTags.begin(); i1 != myPredefinedTags.end(); i1++) { 67 105940136 : delete[](*i1); 68 : } 69 157466 : delete myNextSectionStart.second; 70 314932 : } 71 : 72 : 73 : void 74 216687 : GenericSAXHandler::setFileName(const std::string& name) { 75 216687 : myFileName = name; 76 216687 : } 77 : 78 : 79 : const std::string& 80 807057 : GenericSAXHandler::getFileName() const { 81 807057 : return myFileName; 82 : } 83 : 84 : 85 : XMLCh* 86 104824166 : GenericSAXHandler::convert(const std::string& name) const { 87 104824166 : int len = (int)name.length(); 88 104824166 : XMLCh* ret = new XMLCh[len + 1]; 89 : int i = 0; 90 1235147164 : for (; i < len; i++) { 91 1130322998 : ret[i] = (XMLCh) name[i]; 92 : } 93 104824166 : ret[i] = 0; 94 104824166 : return ret; 95 : } 96 : 97 : 98 : void 99 16577464 : GenericSAXHandler::startElement(const XMLCh* const /*uri*/, 100 : const XMLCh* const /*localname*/, 101 : const XMLCh* const qname, 102 : const XERCES_CPP_NAMESPACE::Attributes& attrs) { 103 16577464 : std::string name = StringUtils::transcode(qname); 104 16577464 : if (!myRootSeen && myExpectedRoot != "" && name != myExpectedRoot) { 105 1470 : WRITE_WARNINGF(TL("Found root element '%' in file '%' (expected '%')."), name, getFileName(), myExpectedRoot); 106 : } 107 16577464 : myRootSeen = true; 108 : myCharactersVector.clear(); 109 16577464 : const int element = convertTag(name); 110 16577464 : if (mySectionSeen && !mySectionOpen && element != mySection) { 111 297 : mySectionEnded = true; 112 297 : myNextSectionStart.first = element; 113 297 : myNextSectionStart.second = new SUMOSAXAttributesImpl_Xerces(attrs, myPredefinedTags, myPredefinedTagsMML, name); 114 : return; 115 : } 116 16577167 : if (element == mySection) { 117 543563 : mySectionSeen = true; 118 543563 : mySectionOpen = true; 119 : } 120 16577167 : SUMOSAXAttributesImpl_Xerces na(attrs, myPredefinedTags, myPredefinedTagsMML, name); 121 16577167 : if (element == SUMO_TAG_INCLUDE) { 122 296 : std::string file = na.getString(SUMO_ATTR_HREF); 123 296 : if (!FileHelpers::isAbsolute(file)) { 124 592 : file = FileHelpers::getConfigurationRelative(getFileName(), file); 125 : } 126 296 : XMLSubSys::runParser(*this, file); 127 : } else { 128 16576871 : myStartElement(element, na); 129 : } 130 16577167 : } 131 : 132 : 133 : void 134 16571935 : GenericSAXHandler::endElement(const XMLCh* const /*uri*/, 135 : const XMLCh* const /*localname*/, 136 : const XMLCh* const qname) { 137 16571935 : std::string name = StringUtils::transcode(qname); 138 16571935 : int element = convertTag(name); 139 : // collect characters 140 16571935 : if (myCharactersVector.size() != 0) { 141 : int len = 0; 142 5335 : for (int i = 0; i < (int)myCharactersVector.size(); ++i) { 143 3146 : len += (int)myCharactersVector[i].length(); 144 : } 145 2189 : char* buf = new char[len + 1]; 146 : int pos = 0; 147 5335 : for (int i = 0; i < (int)myCharactersVector.size(); ++i) { 148 3146 : memcpy((unsigned char*) buf + pos, (unsigned char*) myCharactersVector[i].c_str(), 149 3146 : sizeof(char)*myCharactersVector[i].length()); 150 3146 : pos += (int)myCharactersVector[i].length(); 151 : } 152 2189 : buf[pos] = 0; 153 : 154 : // call user handler 155 : try { 156 2189 : myCharacters(element, buf); 157 0 : } catch (std::runtime_error&) { 158 0 : delete[] buf; 159 0 : throw; 160 0 : } 161 2189 : delete[] buf; 162 : } 163 16571935 : if (element == mySection) { 164 543859 : mySectionOpen = false; 165 : } 166 16571935 : if (element != SUMO_TAG_INCLUDE) { 167 16571639 : myEndElement(element); 168 16571384 : if (myParentHandler && myParentIndicator == element) { 169 4002 : XMLSubSys::setHandler(*myParentHandler); 170 4002 : myParentIndicator = SUMO_TAG_NOTHING; 171 4002 : myParentHandler = nullptr; 172 : } 173 : } 174 16571680 : } 175 : 176 : 177 : void 178 4002 : GenericSAXHandler::registerParent(const int tag, GenericSAXHandler* handler) { 179 4002 : myParentHandler = handler; 180 4002 : myParentIndicator = tag; 181 4002 : XMLSubSys::setHandler(*this); 182 4002 : } 183 : 184 : 185 : void 186 18006119 : GenericSAXHandler::characters(const XMLCh* const chars, 187 : const XERCES3_SIZE_t length) { 188 18006119 : if (myCollectCharacterData) { 189 12442 : myCharactersVector.push_back(StringUtils::transcode(chars, (int)length)); 190 : } 191 18006119 : } 192 : 193 : 194 : int 195 33149399 : GenericSAXHandler::convertTag(const std::string& tag) const { 196 : TagMap::const_iterator i = myTagMap.find(tag); 197 33149399 : if (i == myTagMap.end()) { 198 : return SUMO_TAG_NOTHING; 199 : } 200 32993384 : return (*i).second; 201 : } 202 : 203 : 204 : std::string 205 968 : GenericSAXHandler::buildErrorMessage(const XERCES_CPP_NAMESPACE::SAXParseException& exception) { 206 968 : std::ostringstream buf; 207 968 : char* pMsg = XERCES_CPP_NAMESPACE::XMLString::transcode(exception.getMessage()); 208 968 : buf << pMsg << std::endl; 209 968 : buf << TL(" In file '") << getFileName() << "'" << std::endl; 210 968 : buf << TL(" At line/column ") << exception.getLineNumber() + 1 211 968 : << '/' << exception.getColumnNumber() << "." << std::endl; 212 968 : XERCES_CPP_NAMESPACE::XMLString::release(&pMsg); 213 968 : return buf.str(); 214 968 : } 215 : 216 : 217 : void 218 0 : GenericSAXHandler::warning(const XERCES_CPP_NAMESPACE::SAXParseException& exception) { 219 0 : WRITE_WARNING(buildErrorMessage(exception)); 220 0 : } 221 : 222 : 223 : void 224 878 : GenericSAXHandler::error(const XERCES_CPP_NAMESPACE::SAXParseException& exception) { 225 1756 : throw ProcessError(buildErrorMessage(exception)); 226 : } 227 : 228 : 229 : void 230 90 : GenericSAXHandler::fatalError(const XERCES_CPP_NAMESPACE::SAXParseException& exception) { 231 180 : throw ProcessError(buildErrorMessage(exception)); 232 : } 233 : 234 : 235 : void 236 0 : GenericSAXHandler::myStartElement(int, const SUMOSAXAttributes&) {} 237 : 238 : 239 : void 240 0 : GenericSAXHandler::myCharacters(int, const std::string&) {} 241 : 242 : 243 : void 244 67681 : GenericSAXHandler::myEndElement(int) {} 245 : 246 : void 247 477 : GenericSAXHandler::callParentEnd(int element) { 248 477 : if (myParentHandler) { 249 435 : myParentHandler->myEndElement(element); 250 : } 251 477 : } 252 : 253 : /****************************************************************************/