LCOV - code coverage report
Current view: top level - src/utils/options - OptionsIO.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 63 71 88.7 %
Date: 2024-05-01 15:34:42 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2001-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    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             : #ifdef HAVE_ZLIB
      42             : #include <foreign/zstr/zstr.hpp>
      43             : #endif
      44             : #include <utils/xml/IStreamInputSource.h>
      45             : 
      46             : 
      47             : // ===========================================================================
      48             : // static member definitions
      49             : // ===========================================================================
      50             : std::vector<std::string> OptionsIO::myArgs;
      51             : std::chrono::time_point<std::chrono::system_clock> OptionsIO::myLoadTime;
      52             : 
      53             : 
      54             : // ===========================================================================
      55             : // method definitions
      56             : // ===========================================================================
      57             : void
      58       47389 : OptionsIO::setArgs(int argc, char** argv) {
      59             :     myArgs.clear();
      60      681585 :     for (int i = 0; i < argc; i++) {
      61     1525572 :         myArgs.push_back(StringUtils::transcodeFromLocal(argv[i]));
      62             :     }
      63       47389 : }
      64             : 
      65             : 
      66             : void
      67        1034 : OptionsIO::setArgs(const std::vector<std::string>& args) {
      68        1034 :     myArgs.resize(1);  // will insert an empty string if no first element is there
      69        1034 :     myArgs.insert(myArgs.end(), args.begin(), args.end());
      70        1034 : }
      71             : 
      72             : 
      73             : void
      74       48423 : OptionsIO::getOptions(const bool commandLineOnly) {
      75       48423 :     myLoadTime = std::chrono::system_clock::now();
      76       48423 :     if (myArgs.size() == 2 && myArgs[1][0] != '-') {
      77             :         // special case only one parameter, check who can handle it
      78         104 :         if (OptionsCont::getOptions().setByRootElement(getRoot(myArgs[1]), myArgs[1])) {
      79          52 :             if (!commandLineOnly) {
      80          52 :                 loadConfiguration();
      81             :             }
      82          52 :             return;
      83             :         }
      84             :     }
      85             :     // preparse the options
      86             :     //  (maybe another configuration file was chosen)
      87       48371 :     if (!OptionsParser::parse(myArgs, true)) {
      88         142 :         throw ProcessError(TL("Could not parse commandline options."));
      89             :     }
      90       55545 :     if (!commandLineOnly || OptionsCont::getOptions().isSet("save-configuration", false)) {
      91             :         // read the configuration when everything's ok
      92       41055 :         loadConfiguration();
      93             :     }
      94             : }
      95             : 
      96             : 
      97             : void
      98       48351 : OptionsIO::loadConfiguration() {
      99       48351 :     OptionsCont& oc = OptionsCont::getOptions();
     100      183051 :     if (oc.exists("configuration-file") && oc.isSet("configuration-file")) {
     101       20706 :         const std::string path = oc.getString("configuration-file");
     102       20706 :         if (!FileHelpers::isReadable(path)) {
     103           0 :             throw ProcessError(TLF("Could not access configuration '%'.", oc.getString("configuration-file")));
     104             :         }
     105       20857 :         const bool verbose = !oc.exists("verbose") || oc.getBool("verbose");
     106       10353 :         if (verbose) {
     107         309 :             PROGRESS_BEGIN_MESSAGE(TL("Loading configuration"));
     108             :         }
     109       10353 :         oc.resetWritable();
     110             :         // build parser
     111       10353 :         XERCES_CPP_NAMESPACE::SAXParser parser;
     112       10353 :         parser.setValidationScheme(XERCES_CPP_NAMESPACE::SAXParser::Val_Never);
     113       10353 :         parser.setDisableDefaultEntityResolution(true);
     114             :         // start the parsing
     115       10353 :         OptionsLoader handler(OptionsCont::getOptions());
     116             :         try {
     117       10353 :             parser.setDocumentHandler(&handler);
     118       10353 :             parser.setErrorHandler(&handler);
     119       10353 :             parser.parse(StringUtils::transcodeToLocal(path).c_str());
     120       10353 :             if (handler.errorOccurred()) {
     121          28 :                 throw ProcessError(TLF("Could not load configuration '%'.", path));
     122             :             }
     123           7 :         } catch (const XERCES_CPP_NAMESPACE::XMLException& e) {
     124           0 :             throw ProcessError("Could not load configuration '" + path + "':\n " + StringUtils::transcode(e.getMessage()));
     125           0 :         }
     126       10346 :         oc.relocateFiles(path);
     127       10346 :         if (verbose) {
     128         151 :             PROGRESS_DONE_MESSAGE();
     129             :         }
     130       10360 :     }
     131       48344 :     if (myArgs.size() > 2) {
     132             :         // reparse the options (overwrite the settings from the configuration file)
     133       48028 :         oc.resetWritable();
     134       48028 :         if (!OptionsParser::parse(myArgs)) {
     135          16 :             throw ProcessError(TL("Could not parse commandline options."));
     136             :         }
     137             :     }
     138       48336 : }
     139             : 
     140             : 
     141             : std::string
     142          52 : OptionsIO::getRoot(const std::string& filename) {
     143             :     // build parser
     144          52 :     XERCES_CPP_NAMESPACE::SAXParser parser;
     145          52 :     parser.setValidationScheme(XERCES_CPP_NAMESPACE::SAXParser::Val_Never);
     146          52 :     parser.setDisableDefaultEntityResolution(true);
     147             :     // start the parsing
     148          52 :     OptionsLoader handler(OptionsCont::getOptions());
     149             :     try {
     150          52 :         parser.setDocumentHandler(&handler);
     151          52 :         parser.setErrorHandler(&handler);
     152             :         XERCES_CPP_NAMESPACE::XMLPScanToken token;
     153         177 :         if (!FileHelpers::isReadable(filename) || FileHelpers::isDirectory(filename)) {
     154           0 :             throw ProcessError(TLF("Could not open '%'.", filename));
     155             :         }
     156             : #ifdef HAVE_ZLIB
     157         125 :         zstr::ifstream istream(StringUtils::transcodeToLocal(filename).c_str(), std::fstream::in | std::fstream::binary);
     158             :         IStreamInputSource inputStream(istream);
     159          52 :         const bool result = parser.parseFirst(inputStream, token);
     160             : #else
     161             :         const bool result = parser.parseFirst(StringUtils::transcodeToLocal(filename).c_str(), token);
     162             : #endif
     163          52 :         if (!result) {
     164           0 :             throw ProcessError(TLF("Can not read XML-file '%'.", filename));
     165             :         }
     166         104 :         while (parser.parseNext(token) && handler.getItem() == "");
     167          52 :         if (handler.errorOccurred()) {
     168           0 :             throw ProcessError(TLF("Could not load '%'.", filename));
     169             :         }
     170          52 :     } catch (const XERCES_CPP_NAMESPACE::XMLException& e) {
     171           0 :         throw ProcessError("Could not load '" + filename + "':\n " + StringUtils::transcode(e.getMessage()));
     172           0 :     }
     173          52 :     return handler.getItem();
     174          52 : }
     175             : 
     176             : 
     177             : /****************************************************************************/

Generated by: LCOV version 1.14