65 : myAddresses(), myValues(), myDeprecatedSynonymes() {
66 myCopyrightNotices.push_back(
"Copyright (C) 2001-2022 German Aerospace Center (DLR) and others; https://sumo.dlr.de");
83 throw ProcessError(name +
" is an already used option name.");
98 KnownContType::iterator i1 =
myValues.find(name1);
99 KnownContType::iterator i2 =
myValues.find(name2);
101 throw ProcessError(
"Neither the option '" + name1 +
"' nor the option '" + name2 +
"' is known yet");
104 if ((*i1).second == (*i2).second) {
107 throw ProcessError(
"Both options '" + name1 +
"' and '" + name2 +
"' do exist and differ.");
138 KnownContType::const_iterator i =
myValues.find(name);
140 if (failOnNonExistant) {
141 throw ProcessError(
"Internal request for unknown option '" + name +
"'!");
146 return (*i).second->isSet();
152 KnownContType::const_iterator i =
myValues.find(name);
156 return (*i).second->isDefault();
162 KnownContType::const_iterator k =
myValues.find(name);
164 throw ProcessError(
"No option with the name '" + name +
"' exists.");
168 std::string defaultName;
170 for (std::vector<std::string>::const_iterator j = i->second.begin(); j != i->second.end(); ++j) {
171 KnownContType::const_iterator l =
myValues.find(*j);
172 if (l !=
myValues.end() && l->second == k->second) {
177 if (defaultName !=
"") {
181 WRITE_WARNING(
"Please note that '" + name +
"' is deprecated.\n Use '" + defaultName +
"' instead.");
249 WRITE_ERROR(
"While processing option '" + name +
"':\n " + e.what());
279std::vector<std::string>
282 std::vector<std::string> v(0);
283 for (KnownContType::const_iterator i =
myValues.begin(); i !=
myValues.end(); i++) {
284 if ((*i).second == o && name != (*i).first) {
285 v.push_back((*i).first);
300 std::vector<std::string> done;
301 os <<
"Options set:" << std::endl;
302 for (OptionsCont::KnownContType::const_iterator i = oc.
myValues.begin();
304 std::vector<std::string>::iterator j = std::find(done.begin(), done.end(), (*i).first);
305 if (j == done.end()) {
306 std::vector<std::string> synonymes = oc.
getSynonymes((*i).first);
307 if (synonymes.size() != 0) {
308 os << (*i).first <<
" (";
309 for (j = synonymes.begin(); j != synonymes.end(); j++) {
310 if (j != synonymes.begin()) {
319 if ((*i).second->isSet()) {
320 os <<
": " << (*i).second->getValueString() << std::endl;
322 os <<
": <INVALID>" << std::endl;
324 done.push_back((*i).first);
325 copy(synonymes.begin(), synonymes.end(), back_inserter(done));
335 if (option->isFileName() && option->isSet()) {
337 for (std::string& f : fileList) {
346 for (std::string& f : rawList) {
350 if (conv !=
joinToString(option->getStringVector(),
',')) {
351 const bool hadDefault = option->isDefault();
354 option->resetDefault();
371 if (files.size() == 0) {
372 WRITE_ERROR(
"The file list for '" + name +
"' is empty.");
375 for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
396 std::vector<std::string> seenSynonymes;
397 for (KnownContType::const_iterator i =
myValues.begin(); i !=
myValues.end(); i++) {
398 if (std::find(seenSynonymes.begin(), seenSynonymes.end(), (*i).first) != seenSynonymes.end()) {
401 if ((*i).second->isSet() && !(*i).second->isDefault() && (*i).first.find(prefix) == 0) {
402 WRITE_ERROR(
"Option '" + (*i).first +
"' needs option '" + name +
"'.");
403 std::vector<std::string> synonymes =
getSynonymes((*i).first);
404 std::copy(synonymes.begin(), synonymes.end(), std::back_inserter(seenSynonymes));
415 std::ostringstream s;
416 s <<
"A value for the option '" + arg +
"' was already set.\n Possible synonymes: ";
417 for (std::vector<std::string>::iterator i = synonymes.begin(); i != synonymes.end();) {
420 if (i != synonymes.end()) {
448 (*i)->resetWritable();
462 ItemAddressContType::iterator i;
475 const std::string& subtopic,
476 const std::string& description) {
487 const std::string& fullName) {
532 int offset,
int nextOffset) {
533 while (what.length() > 0) {
534 if ((
int)what.length() > 79 - offset) {
535 std::string::size_type splitPos = what.rfind(
';', 79 - offset);
536 if (splitPos == std::string::npos) {
537 splitPos = what.rfind(
' ', 79 - offset);
541 if (splitPos != std::string::npos) {
542 os << what.substr(0, splitPos) << std::endl;
543 what = what.substr(splitPos + 1);
544 for (
int r = 0; r < nextOffset + 1; ++r) {
563 if (missingOptions) {
566 std::cout <<
" Build features: " << HAVE_ENABLED << std::endl;
567 for (std::vector<std::string>::const_iterator it =
569 std::cout <<
" " << *it << std::endl;
571 std::cout <<
" License EPL-2.0: Eclipse Public License Version 2 <https://eclipse.org/legal/epl-v20.html>\n";
572 std::cout <<
" Use --help to get the list of options." << std::endl;
580 for (std::vector<std::string>::const_iterator it =
582 std::cout <<
" " << *it << std::endl;
590 std::cout <<
" Build features: " << HAVE_ENABLED << std::endl;
591 for (std::vector<std::string>::const_iterator it =
593 std::cout <<
" " << *it << std::endl;
595 std::cout <<
"\n" <<
myFullName <<
" is part of SUMO.\n";
596 std::cout <<
"This program and the accompanying materials\n";
597 std::cout <<
"are made available under the terms of the Eclipse Public License v2.0\n";
598 std::cout <<
"which accompanies this distribution, and is available at\n";
599 std::cout <<
"http://www.eclipse.org/legal/epl-v20.html\n";
600 std::cout <<
"This program may also be made available under the following Secondary\n";
601 std::cout <<
"Licenses when the conditions for such availability set forth in the Eclipse\n";
602 std::cout <<
"Public License 2.0 are satisfied: GNU General Public License, version 2\n";
603 std::cout <<
"or later which is available at\n";
604 std::cout <<
"https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html\n";
605 std::cout <<
"SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later" << std::endl;
610 std::cout << (*this);
614 if (
isSet(
"save-configuration",
false)) {
615 const std::string& configPath =
getString(
"save-configuration");
616 if (configPath ==
"-" || configPath ==
"stdout") {
622 throw ProcessError(
"Could not save configuration to '" + configPath +
"'");
626 WRITE_MESSAGE(
"Written configuration to '" + configPath +
"'");
632 if (
isSet(
"save-template",
false)) {
648 if (
isSet(
"save-schema",
false)) {
670 std::vector<std::string>::const_iterator i, j;
681 for (j = entries.begin(); j != entries.end(); ++j) {
684 int csize = (int)j->length() + 2 + 4;
686 const std::vector<std::string> synonymes =
getSynonymes(*j);
687 for (std::vector<std::string>::const_iterator s = synonymes.begin(); s != synonymes.end(); ++s) {
699 if (csize < tooLarge && maxSize < csize) {
706 if (helpTopic !=
"") {
707 bool foundTopic =
false;
716 os <<
"Help Topics:" << std::endl;
718 os <<
" " << t << std::endl;
724 os <<
"Usage: " <<
myAppName <<
" [OPTION]*" << std::endl;
736 os <<
"Examples:" << std::endl;
738 os <<
" " <<
myAppName <<
' ' << e->first << std::endl;
739 os <<
" " << e->second << std::endl;
743 os <<
"Report bugs at <https://github.com/eclipse/sumo/issues>." << std::endl;
744 os <<
"Get in contact via <sumo@dlr.de>." << std::endl;
750 os << topic <<
" Options:" << std::endl;
753 int csize = (int)entry.length() + 2;
757 std::vector<std::string> synonymes =
getSynonymes(entry);
758 for (std::vector<std::string>::const_iterator s = synonymes.begin(); s != synonymes.end(); ++s) {
760 os <<
'-' << *s <<
", ";
778 for (
int r = maxSize; r > csize; --r) {
781 int offset = csize > tooLarge ? csize : maxSize;
790 const bool complete,
const bool addComments,
const std::string& relativeTo,
791 const bool forceRelative,
const bool inComment)
const {
795 os <<
"<configuration xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.dlr.de/xsd/";
803 os <<
"Configuration.xsd\">" << std::endl << std::endl;
805 if (subtopic ==
"Configuration" && !complete) {
808 const std::vector<std::string>& entries =
mySubTopicEntries.find(subtopic)->second;
809 std::replace(subtopic.begin(), subtopic.end(),
' ',
'_');
812 for (
const std::string& name : entries) {
814 bool write = complete || (filled && !o->
isDefault());
818 if (name ==
"registry-viewport" && !complete) {
822 os <<
" <" << subtopic <<
">" << std::endl;
829 os <<
" <" << name <<
" value=\"";
833 for (std::string& f : fileList) {
835 forceRelative ||
getBool(
"save-configuration.relative"));
843 std::vector<std::string> synonymes =
getSynonymes(name);
844 if (!synonymes.empty()) {
845 os <<
"\" synonymes=\"";
846 for (std::vector<std::string>::const_iterator s = synonymes.begin(); s != synonymes.end(); ++s) {
847 if (s != synonymes.begin()) {
858 os <<
"\"/>" << std::endl;
866 os <<
" </" << subtopic <<
">" << std::endl << std::endl;
869 os <<
"</configuration>" << std::endl;
876 os <<
"<xsd:schema elementFormDefault=\"qualified\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n\n";
877 os <<
" <xsd:include schemaLocation=\"baseTypes.xsd\"/>\n";
878 os <<
" <xsd:element name=\"configuration\" type=\"configurationType\"/>\n\n";
879 os <<
" <xsd:complexType name=\"configurationType\">\n";
880 os <<
" <xsd:all>\n";
882 std::string subtopic = *i;
883 if (subtopic ==
"Configuration") {
886 std::replace(subtopic.begin(), subtopic.end(),
' ',
'_');
888 os <<
" <xsd:element name=\"" << subtopic <<
"\" type=\"" << subtopic <<
"TopicType\" minOccurs=\"0\"/>\n";
890 os <<
" </xsd:all>\n";
891 os <<
" </xsd:complexType>\n\n";
893 std::string subtopic = *i;
894 if (subtopic ==
"Configuration") {
897 std::replace(subtopic.begin(), subtopic.end(),
' ',
'_');
899 os <<
" <xsd:complexType name=\"" << subtopic <<
"TopicType\">\n";
900 os <<
" <xsd:all>\n";
902 for (std::vector<std::string>::const_iterator j = entries.begin(); j != entries.end(); ++j) {
906 if (type ==
"int[]") {
909 if (type ==
"str[]") {
912 os <<
" <xsd:element name=\"" << *j <<
"\" type=\"" << type <<
"OptionType\" minOccurs=\"0\"/>\n";
914 os <<
" </xsd:all>\n";
915 os <<
" </xsd:complexType>\n\n";
917 os <<
"</xsd:schema>\n";
928 strftime(buffer, 80,
"<!-- generated on %F %T by ", localtime(&rawtime));
931 os <<
"This data file and the accompanying materials\n"
932 "are made available under the terms of the Eclipse Public License v2.0\n"
933 "which accompanies this distribution, and is available at\n"
934 "http://www.eclipse.org/legal/epl-v20.html\n"
935 "This file may also be made available under the following Secondary\n"
936 "Licenses when the conditions for such availability set forth in the Eclipse\n"
937 "Public License 2.0 are satisfied: GNU General Public License, version 2\n"
938 "or later which is available at\n"
939 "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html\n"
940 "SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n";
951 const std::string& itemName)
const {
952 if (
isSet(optionName)) {
954 return std::find(values.begin(), values.end(), itemName) != values.end();
#define WRITE_MESSAGE(msg)
#define WRITE_WARNING(msg)
std::vector< std::string > StringVector
Definition of a vector of strings.
std::vector< int > IntVector
Definition of a vector of ints.
std::ostream & operator<<(std::ostream &os, const OptionsCont &oc)
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
static std::string fixRelative(const std::string &filename, const std::string &basePath, const bool force, std::string curDir="")
Fixes the relative path for the given filename in relation to the basePath (usually a config file).
static std::string checkForRelativity(const std::string &filename, const std::string &basePath)
Returns the path from a configuration so that it is accessable from the current working directory.
static bool isReadable(std::string path)
Checks whether the given file is readable.
A class representing a single program option.
bool isWriteable() const
Returns the information whether the option may be set a further time.
bool isSet() const
returns the information whether this options holds a valid value
virtual bool isDefault() const
Returns the information whether the option holds the default value.
virtual std::string getString() const
Returns the stored string value.
virtual const IntVector & getIntVector() const
Returns the stored integer vector.
const std::string & getDescription() const
Returns the description of what this option does.
virtual bool isFileName() const
Returns the information whether this option is a file name.
virtual const StringVector & getStringVector() const
Returns the stored string vector.
void setDescription(const std::string &desc)
Sets the description of what this option does.
virtual const std::string & getTypeName() const
Returns the mml-type name of this option.
virtual int getInt() const
Returns the stored integer value.
virtual double getFloat() const
Returns the stored double value.
virtual bool getBool() const
Returns the stored boolean value.
void resetDefault()
Resets the option to be on its default value.
virtual bool set(const std::string &v, const std::string &orig, const bool append)=0
Stores the given value.
virtual bool isBool() const
Returns the information whether the option is a bool option.
const std::string & getValueString() const
Returns the string-representation of the value.
A storage for options typed value containers)
void setAdditionalHelpMessage(const std::string &add)
Sets an additional message to be printed at the begin of the help screen.
~OptionsCont()
Destructor.
void addDescription(const std::string &name, const std::string &subtopic, const std::string &description)
Adds a description for an option.
void doRegister(const std::string &name, Option *v)
Adds an option under the given name.
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
std::vector< std::pair< std::string, std::string > > myCallExamples
list of call examples
bool isWriteable(const std::string &name)
Returns the information whether the named option may be set.
std::map< std::string, std::vector< std::string > > mySubTopicEntries
A map from subtopic to option.
void writeXMLHeader(std::ostream &os, const bool includeConfig=true) const
Writes a standard XML header, including the configuration.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
void splitLines(std::ostream &os, std::string what, int offset, int nextOffset)
Writes the given string 'formatted'.
void setApplicationName(const std::string &appName, const std::string &fullName)
Sets the application name.
void printHelpOnTopic(const std::string &topic, int tooLarge, int maxSize, std::ostream &os)
Prints help on the given topic.
std::string myAdditionalMessage
std::vector< std::string > myCopyrightNotices
const IntVector & getIntVector(const std::string &name) const
Returns the list of integer-value of the named option (only for Option_IntVector)
std::vector< std::string > getSynonymes(const std::string &name) const
Returns the synonymes of an option name.
void reportDoubleSetting(const std::string &arg) const
Reports an error that the option has already been set.
std::vector< std::string > mySubTopics
lists of option subtopics and copyright notices
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool myWriteLicense
Information whether we should always include license information in file headers.
ItemAddressContType myAddresses
void addSynonyme(const std::string &name1, const std::string &name2, bool isDeprecated=false)
Adds a synonyme for an options name (any order)
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
bool setDefault(const std::string &name, const std::string &value)
Sets the given value for the named option as new default value.
bool exists(const std::string &name) const
Returns the information whether the named option is known.
bool isBool(const std::string &name) const
Returns the information whether the option is a boolean option.
void addCopyrightNotice(const std::string ©rightLine)
Adds a copyright notice to the help output.
void writeSchema(std::ostream &os)
Writes the xml schema for the configuration.
void clear()
Removes all information from the container.
void setApplicationDescription(const std::string &appDesc)
Sets the application description.
bool set(const std::string &name, const std::string &value, const bool append=false)
Sets the given value for the named option.
void writeConfiguration(std::ostream &os, const bool filled, const bool complete, const bool addComments, const std::string &relativeTo="", const bool forceRelative=false, const bool inComment=false) const
Writes the configuration.
void clearCopyrightNotices()
Removes all copyright information.
std::string convertChar(char abbr) const
Converts an abbreviation into a name.
void addOptionSubTopic(const std::string &topic)
Adds an option subtopic.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
OptionsCont()
Constructor.
void printHelp(std::ostream &os)
Prints the help.
std::string getValueString(const std::string &name) const
Returns the string-value of the named option (all options)
std::string myAppDescription
const std::string & getDescription(const std::string &name) const
Returns the option description.
bool setByRootElement(const std::string &name, const std::string &value)
Sets the given value for the option which can handle the given XML root.
std::map< std::string, bool > myDeprecatedSynonymes
A map from deprecated options to a bool indicating whether we warned about deprecation.
static OptionsCont myOptions
The static options container used.
bool checkDependingSuboptions(const std::string &name, const std::string &prefix) const
Checks whether an option is set, which has options with a prefix depending on it.
std::map< std::string, std::string > myXMLDefaults
A map from XML root element to option.
std::string myAppName
some information on the application
void resetWritable()
Resets all options to be writeable.
void addXMLDefault(const std::string &name, const std::string &xmlRoot="")
Adds an XML root element to handle by default. The special root "" denotes the default handler.
static OptionsCont & getOptions()
Retrieves the options.
Option * getSecure(const std::string &name) const
Returns the named option.
void relocateFiles(const std::string &configuration) const
Modifies file name options according to the configuration path.
bool isInStringVector(const std::string &optionName, const std::string &itemName) const
Returns the named option is a list of string values containing the specified item.
bool processMetaOptions(bool missingOptions)
Checks for help and configuration output, returns whether we should exit.
bool isUsableFileList(const std::string &name) const
Checks whether the named option is usable as a file list (with at least a single file)
void addCallExample(const std::string &example, const std::string &desc)
Add a call example.
static const std::chrono::time_point< std::chrono::system_clock > & getLoadTime()
Return the time stamp of the last init.
static const std::string ENCODING
The encoding of parsed strings.
std::vector< std::string > getVector()
return vector of strings
static std::string urlEncode(const std::string &url, const std::string encodeWhich="")
static std::string urlDecode(const std::string &encoded)
static std::string to_lower_case(const std::string &str)
Transfers the content to lower case.
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.
static std::string substituteEnvironment(const std::string &str, const std::chrono::time_point< std::chrono::system_clock > *const timeRef=nullptr)
static std::string transcodeToLocal(const std::string &utf8String)
convert a string from UTF-8 to the local codepage
static std::string strerror()