Eclipse SUMO - Simulation of Urban MObility
OptionsIO.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2022 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 /****************************************************************************/
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/util/PlatformUtils.hpp>
32 #include <xercesc/sax/SAXParseException.hpp>
33 #include <xercesc/sax/SAXException.hpp>
34 #include "OptionsIO.h"
35 #include "OptionsCont.h"
36 #include "OptionsLoader.h"
37 #include "OptionsParser.h"
41 #ifdef HAVE_ZLIB
42 #include <foreign/zstr/zstr.hpp>
43 #endif
45 
46 
47 // ===========================================================================
48 // static member definitions
49 // ===========================================================================
50 int OptionsIO::myArgC = 0;
51 char** OptionsIO::myArgV;
52 
53 
54 // ===========================================================================
55 // method definitions
56 // ===========================================================================
57 void
58 OptionsIO::setArgs(int argc, char** argv) {
59  myArgC = argc;
60  char** codedArgv = new char* [myArgC];
61  for (int i = 0; i < argc; i++) {
62  const std::string& a = StringUtils::transcodeFromLocal(argv[i]);
63  codedArgv[i] = new char[a.size() + 1];
64  std::strcpy(codedArgv[i], a.c_str());
65  }
66  myArgV = codedArgv;
67 }
68 
69 
70 void
71 OptionsIO::setArgs(const std::vector<std::string>& args) {
72  char* const app = myArgC > 0 ? myArgV[0] : nullptr;
73  myArgC = (int)args.size() + 1;
74  char** argv = new char* [myArgC];
75  argv[0] = app;
76  for (int i = 1; i < myArgC; i++) {
77  argv[i] = new char[args[i - 1].size() + 1];
78  std::strcpy(argv[i], args[i - 1].c_str());
79  }
80  myArgV = argv;
81 }
82 
83 
84 void
85 OptionsIO::getOptions(const bool commandLineOnly) {
86  if (myArgC == 2 && myArgV[1][0] != '-') {
87  // special case only one parameter, check who can handle it
88  if (OptionsCont::getOptions().setByRootElement(getRoot(myArgV[1]), myArgV[1])) {
89  if (!commandLineOnly) {
91  }
92  return;
93  }
94  }
95  // preparse the options
96  // (maybe another configuration file was chosen)
98  throw ProcessError("Could not parse commandline options.");
99  }
100  if (!commandLineOnly || OptionsCont::getOptions().isSet("save-configuration", false)) {
101  // read the configuration when everything's ok
103  }
104 }
105 
106 
107 void
110  if (!oc.exists("configuration-file") || !oc.isSet("configuration-file")) {
111  return;
112  }
113  const std::string path = oc.getString("configuration-file");
114  if (!FileHelpers::isReadable(path)) {
115  throw ProcessError("Could not access configuration '" + oc.getString("configuration-file") + "'.");
116  }
117  const bool verbose = !oc.exists("verbose") || oc.getBool("verbose");
118  if (verbose) {
119  PROGRESS_BEGIN_MESSAGE("Loading configuration");
120  }
121  oc.resetWritable();
122  // build parser
123  XERCES_CPP_NAMESPACE::SAXParser parser;
124  parser.setValidationScheme(XERCES_CPP_NAMESPACE::SAXParser::Val_Auto);
125  parser.setDoNamespaces(false);
126  parser.setDoSchema(false);
127  // start the parsing
128  OptionsLoader handler;
129  try {
130  parser.setDocumentHandler(&handler);
131  parser.setErrorHandler(&handler);
132  parser.parse(StringUtils::transcodeToLocal(path).c_str());
133  if (handler.errorOccurred()) {
134  throw ProcessError("Could not load configuration '" + path + "'.");
135  }
136  } catch (const XERCES_CPP_NAMESPACE::XMLException& e) {
137  throw ProcessError("Could not load configuration '" + path + "':\n " + StringUtils::transcode(e.getMessage()));
138  }
139  oc.relocateFiles(path);
140  if (myArgC > 2) {
141  // reparse the options (overwrite the settings from the configuration file)
142  oc.resetWritable();
144  }
145  if (verbose) {
147  }
148 }
149 
150 
151 std::string
152 OptionsIO::getRoot(const std::string& filename) {
153  // build parser
154  XERCES_CPP_NAMESPACE::SAXParser parser;
155  // start the parsing
156  OptionsLoader handler;
157  try {
158  parser.setDocumentHandler(&handler);
159  parser.setErrorHandler(&handler);
160  XERCES_CPP_NAMESPACE::XMLPScanToken token;
161  if (!FileHelpers::isReadable(filename) || FileHelpers::isDirectory(filename)) {
162  throw ProcessError("Could not open '" + filename + "'.");
163  }
164 #ifdef HAVE_ZLIB
165  zstr::ifstream istream(StringUtils::transcodeToLocal(filename).c_str(), std::fstream::in | std::fstream::binary);
166  IStreamInputSource inputStream(istream);
167  const bool result = parser.parseFirst(inputStream, token);
168 #else
169  const bool result = parser.parseFirst(StringUtils::transcodeToLocal(filename).c_str(), token);
170 #endif
171  if (!result) {
172  throw ProcessError("Can not read XML-file '" + filename + "'.");
173  }
174  while (parser.parseNext(token) && handler.getItem() == "");
175  if (handler.errorOccurred()) {
176  throw ProcessError("Could not load '" + filename + "'.");
177  }
178  } catch (const XERCES_CPP_NAMESPACE::XMLException& e) {
179  throw ProcessError("Could not load '" + filename + "':\n " + StringUtils::transcode(e.getMessage()));
180  }
181  return handler.getItem();
182 }
183 
184 
185 /****************************************************************************/
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:284
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:283
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:49
static bool isDirectory(std::string path)
Checks whether the given file is a directory.
Definition: FileHelpers.cpp:63
Xerces InputSource reading from arbitrary std::istream.
A storage for options typed value containers)
Definition: OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool exists(const std::string &name) const
Returns the information whether the named option is known.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
void resetWritable()
Resets all options to be writeable.
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
void relocateFiles(const std::string &configuration) const
Modifies file name options according to the configuration path.
static void loadConfiguration()
Loads and parses the configuration.
Definition: OptionsIO.cpp:108
static void setArgs(int argc, char **argv)
Stores the command line arguments for later parsing.
Definition: OptionsIO.cpp:58
static void getOptions(const bool commandLineOnly=false)
Parses the command line arguments and loads the configuration.
Definition: OptionsIO.cpp:85
static std::string getRoot(const std::string &filename)
Retrieves the XML root element of a supposed configuration or net.
Definition: OptionsIO.cpp:152
static int myArgC
Definition: OptionsIO.h:101
static char ** myArgV
Definition: OptionsIO.h:102
A SAX-Handler for loading options.
Definition: OptionsLoader.h:44
const std::string & getItem() const
Returns the last item read.
bool errorOccurred() const
Returns the information whether an error occurred.
static bool parse(int argc, char **argv)
Parses the given command line arguments.
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:137
static std::string transcodeToLocal(const std::string &utf8String)
convert a string from UTF-8 to the local codepage
static std::string transcodeFromLocal(const std::string &localString)
convert a string from the local codepage to UTF-8