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