LCOV - code coverage report
Current view: top level - src/utils/options - OptionsIO.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 90.1 % 71 64
Test Date: 2026-06-15 15:46:12 Functions: 100.0 % 5 5

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2026 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    OptionsIO.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Michael Behrisch
      17              : /// @date    Mon, 17 Dec 2001
      18              : ///
      19              : // Helper for parsing command line arguments and reading configuration files
      20              : /****************************************************************************/
      21              : #include <config.h>
      22              : 
      23              : #include <string>
      24              : #include <iostream>
      25              : #include <cstdlib>
      26              : #include <cstring>
      27              : #include <xercesc/framework/XMLPScanToken.hpp>
      28              : #include <xercesc/parsers/SAXParser.hpp>
      29              : #include <xercesc/sax/HandlerBase.hpp>
      30              : #include <xercesc/sax/AttributeList.hpp>
      31              : #include <xercesc/sax/SAXParseException.hpp>
      32              : #include <xercesc/sax/SAXException.hpp>
      33              : #include <xercesc/util/PlatformUtils.hpp>
      34              : #include "OptionsIO.h"
      35              : #include "OptionsCont.h"
      36              : #include "OptionsLoader.h"
      37              : #include "OptionsParser.h"
      38              : #include <utils/common/FileHelpers.h>
      39              : #include <utils/common/MsgHandler.h>
      40              : #include <utils/common/StringUtils.h>
      41              : #include <utils/xml/XMLSubSys.h>
      42              : #ifdef HAVE_ZLIB
      43              : #include <foreign/zstr/zstr.hpp>
      44              : #endif
      45              : #include <utils/xml/IStreamInputSource.h>
      46              : 
      47              : 
      48              : // ===========================================================================
      49              : // static member definitions
      50              : // ===========================================================================
      51              : std::vector<std::string> OptionsIO::myArgs;
      52              : std::chrono::time_point<std::chrono::system_clock> OptionsIO::myLoadTime;
      53              : 
      54              : 
      55              : // ===========================================================================
      56              : // method definitions
      57              : // ===========================================================================
      58              : void
      59        53587 : OptionsIO::setArgs(int argc, char** argv) {
      60              :     myArgs.clear();
      61       909128 :     for (int i = 0; i < argc; i++) {
      62      1711082 :         myArgs.push_back(XMLSubSys::transcodeFromLocal(argv[i]));
      63              :     }
      64        53587 : }
      65              : 
      66              : 
      67              : void
      68         1161 : OptionsIO::setArgs(const std::vector<std::string>& args) {
      69         1161 :     myArgs.resize(1);  // will insert an empty string if no first element is there
      70         1161 :     myArgs.insert(myArgs.end(), args.begin(), args.end());
      71         1161 : }
      72              : 
      73              : 
      74              : void
      75        54748 : OptionsIO::getOptions(const bool commandLineOnly) {
      76        54748 :     myLoadTime = std::chrono::system_clock::now();
      77        54748 :     if (myArgs.size() == 2 && myArgs[1][0] != '-') {
      78              :         // special case only one parameter, check who can handle it
      79           34 :         if (OptionsCont::getOptions().setByRootElement(getRoot(myArgs[1]), myArgs[1])) {
      80           17 :             if (!commandLineOnly) {
      81           17 :                 loadConfiguration();
      82              :             }
      83           17 :             return;
      84              :         }
      85              :     }
      86              :     // preparse the options
      87              :     //  (maybe another configuration file was chosen)
      88        54731 :     if (!OptionsParser::parse(myArgs, true)) {
      89          132 :         throw ProcessError(TL("Could not parse commandline options."));
      90              :     }
      91        63486 :     if (!commandLineOnly || OptionsCont::getOptions().isSet("save-configuration", false)) {
      92              :         // read the configuration when everything's ok
      93        45844 :         loadConfiguration();
      94              :     }
      95              : }
      96              : 
      97              : 
      98              : void
      99        54682 : OptionsIO::loadConfiguration() {
     100        54682 :     OptionsCont& oc = OptionsCont::getOptions();
     101       109364 :     if (oc.exists("configuration-file") && oc.isSet("configuration-file")) {
     102        27892 :         const std::string path = oc.getString("configuration-file");
     103        27892 :         if (!FileHelpers::isReadable(path)) {
     104          717 :             throw ProcessError(TLF("Could not access configuration '%'.", oc.getString("configuration-file")));
     105              :         }
     106        27414 :         const bool verbose = !oc.exists("verbose") || oc.getBool("verbose");
     107        13707 :         if (verbose) {
     108          666 :             PROGRESS_BEGIN_MESSAGE(TL("Loading configuration"));
     109              :         }
     110        13707 :         oc.resetWritable();
     111              :         // build parser
     112        13707 :         XERCES_CPP_NAMESPACE::SAXParser parser;
     113        13707 :         parser.setValidationScheme(XERCES_CPP_NAMESPACE::SAXParser::Val_Never);
     114        13707 :         parser.setDisableDefaultEntityResolution(true);
     115              :         // start the parsing
     116        13707 :         OptionsLoader handler(OptionsCont::getOptions());
     117              :         try {
     118        13707 :             parser.setDocumentHandler(&handler);
     119        13707 :             parser.setErrorHandler(&handler);
     120        13707 :             parser.parse(XMLSubSys::transcodeToLocal(path).c_str());
     121        13707 :             if (handler.errorOccurred()) {
     122           21 :                 throw ProcessError(TLF("Could not load configuration '%'.", path));
     123              :             }
     124            7 :         } catch (const XERCES_CPP_NAMESPACE::XMLException& e) {
     125            0 :             throw ProcessError("Could not load configuration '" + path + "':\n " + XMLSubSys::transcode(e.getMessage()));
     126            0 :         }
     127        13700 :         oc.relocateFiles(path);
     128        13700 :         if (verbose) {
     129          140 :             PROGRESS_DONE_MESSAGE();
     130              :         }
     131        13714 :     }
     132        54436 :     if (myArgs.size() > 2) {
     133              :         // reparse the options (overwrite the settings from the configuration file)
     134        54269 :         oc.resetWritable();
     135        54269 :         if (!OptionsParser::parse(myArgs)) {
     136            8 :             throw ProcessError(TL("Could not parse commandline options."));
     137              :         }
     138              :     }
     139        54432 : }
     140              : 
     141              : 
     142              : std::string
     143           17 : OptionsIO::getRoot(const std::string& filename) {
     144              :     // build parser
     145           17 :     XERCES_CPP_NAMESPACE::SAXParser parser;
     146           17 :     parser.setValidationScheme(XERCES_CPP_NAMESPACE::SAXParser::Val_Never);
     147           17 :     parser.setDisableDefaultEntityResolution(true);
     148              :     // start the parsing
     149           17 :     OptionsLoader handler(OptionsCont::getOptions());
     150              :     try {
     151           17 :         parser.setDocumentHandler(&handler);
     152           17 :         parser.setErrorHandler(&handler);
     153              :         XERCES_CPP_NAMESPACE::XMLPScanToken token;
     154           51 :         if (!FileHelpers::isReadable(filename) || FileHelpers::isDirectory(filename)) {
     155            0 :             throw ProcessError(TLF("Could not open '%'.", filename));
     156              :         }
     157              : #ifdef HAVE_ZLIB
     158           34 :         zstr::ifstream istream(XMLSubSys::transcodeToLocal(filename).c_str(), std::fstream::in | std::fstream::binary);
     159              :         IStreamInputSource inputStream(istream);
     160           17 :         const bool result = parser.parseFirst(inputStream, token);
     161              : #else
     162              :         const bool result = parser.parseFirst(XMLSubSys::transcodeToLocal(filename).c_str(), token);
     163              : #endif
     164           17 :         if (!result) {
     165            0 :             throw ProcessError(TLF("Can not read XML-file '%'.", filename));
     166              :         }
     167           17 :         while (parser.parseNext(token) && handler.getItem() == "");
     168           17 :         if (handler.errorOccurred()) {
     169            0 :             throw ProcessError(TLF("Could not load '%'.", filename));
     170              :         }
     171           17 :     } catch (const XERCES_CPP_NAMESPACE::XMLException& e) {
     172            0 :         throw ProcessError("Could not load '" + filename + "':\n " + XMLSubSys::transcode(e.getMessage()));
     173            0 :     }
     174           17 :     return handler.getItem();
     175           17 : }
     176              : 
     177              : 
     178              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1