Eclipse SUMO - Simulation of Urban MObility
OptionsCont.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-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
17 // A storage for options (typed value containers)
18 /****************************************************************************/
19 // ===========================================================================
20 // included modules
21 // ===========================================================================
22 #include <config.h>
23 
24 #include <map>
25 #include <string>
26 #include <exception>
27 #include <algorithm>
28 #include <vector>
29 #include <iostream>
30 #include <cstdlib>
31 #include <cassert>
32 #include <ctime>
33 #include <cstring>
34 #include <cerrno>
35 #include <iterator>
36 #include "Option.h"
37 #include "OptionsCont.h"
44 #include <sstream>
45 
46 
47 // ===========================================================================
48 // static member definitions
49 // ===========================================================================
51 
52 
53 // ===========================================================================
54 // method definitions
55 // ===========================================================================
58  return myOptions;
59 }
60 
61 
63  : myAddresses(), myValues(), myDeprecatedSynonymes() {
64  myCopyrightNotices.push_back("Copyright (C) 2001-2019 German Aerospace Center (DLR) and others; https://sumo.dlr.de");
65 }
66 
67 
69  clear();
70 }
71 
72 
73 void
74 OptionsCont::doRegister(const std::string& name, Option* v) {
75  assert(v != 0);
76  ItemAddressContType::iterator i = std::find(myAddresses.begin(), myAddresses.end(), v);
77  if (i == myAddresses.end()) {
78  myAddresses.push_back(v);
79  }
80  if (myValues.find(name) != myValues.end()) {
81  throw ProcessError(name + " is an already used option name.");
82  }
83  myValues[name] = v;
84 }
85 
86 
87 void
88 OptionsCont::doRegister(const std::string& name1, char abbr, Option* v) {
89  doRegister(name1, v);
90  doRegister(convertChar(abbr), v);
91 }
92 
93 
94 void
95 OptionsCont::addSynonyme(const std::string& name1, const std::string& name2, bool isDeprecated) {
96  KnownContType::iterator i1 = myValues.find(name1);
97  KnownContType::iterator i2 = myValues.find(name2);
98  if (i1 == myValues.end() && i2 == myValues.end()) {
99  throw ProcessError("Neither the option '" + name1 + "' nor the option '" + name2 + "' is known yet");
100  }
101  if (i1 != myValues.end() && i2 != myValues.end()) {
102  if ((*i1).second == (*i2).second) {
103  return;
104  }
105  throw ProcessError("Both options '" + name1 + "' and '" + name2 + "' do exist and differ.");
106  }
107  if (i1 == myValues.end() && i2 != myValues.end()) {
108  doRegister(name1, (*i2).second);
109  if (isDeprecated) {
110  myDeprecatedSynonymes[name1] = false;
111  }
112  }
113  if (i1 != myValues.end() && i2 == myValues.end()) {
114  doRegister(name2, (*i1).second);
115  if (isDeprecated) {
116  myDeprecatedSynonymes[name2] = false;
117  }
118  }
119 }
120 
121 
122 void
123 OptionsCont::addXMLDefault(const std::string& name, const std::string& xmlRoot) {
124  myXMLDefaults[xmlRoot] = name;
125 }
126 
127 
128 bool
129 OptionsCont::exists(const std::string& name) const {
130  return myValues.count(name) > 0;
131 }
132 
133 
134 bool
135 OptionsCont::isSet(const std::string& name, bool failOnNonExistant) const {
136  KnownContType::const_iterator i = myValues.find(name);
137  if (i == myValues.end()) {
138  if (failOnNonExistant) {
139  throw ProcessError("Internal request for unknown option '" + name + "'!");
140  } else {
141  return false;
142  }
143  }
144  return (*i).second->isSet();
145 }
146 
147 
148 void
149 OptionsCont::unSet(const std::string& name, bool failOnNonExistant) const {
150  KnownContType::const_iterator i = myValues.find(name);
151  if (i == myValues.end()) {
152  if (failOnNonExistant) {
153  throw ProcessError("Internal request for unknown option '" + name + "'!");
154  } else {
155  return;
156  }
157  }
158  (*i).second->unSet();
159 }
160 
161 
162 bool
163 OptionsCont::isDefault(const std::string& name) const {
164  KnownContType::const_iterator i = myValues.find(name);
165  if (i == myValues.end()) {
166  return false;
167  }
168  return (*i).second->isDefault();
169 }
170 
171 
172 Option*
173 OptionsCont::getSecure(const std::string& name) const {
174  KnownContType::const_iterator k = myValues.find(name);
175  if (k == myValues.end()) {
176  throw ProcessError("No option with the name '" + name + "' exists.");
177  }
178  std::map<std::string, bool>::iterator s = myDeprecatedSynonymes.find(name);
179  if (s != myDeprecatedSynonymes.end() && !s->second) {
180  std::string defaultName;
181  for (std::map<std::string, std::vector<std::string> >::const_iterator i = mySubTopicEntries.begin(); i != mySubTopicEntries.end(); ++i) {
182  for (std::vector<std::string>::const_iterator j = i->second.begin(); j != i->second.end(); ++j) {
183  KnownContType::const_iterator l = myValues.find(*j);
184  if (l != myValues.end() && l->second == k->second) {
185  defaultName = *j;
186  break;
187  }
188  }
189  if (defaultName != "") {
190  break;
191  }
192  }
193  WRITE_WARNING("Please note that '" + name + "' is deprecated.\n Use '" + defaultName + "' instead.");
194  s->second = true;
195  }
196  return k->second;
197 }
198 
199 
200 std::string
201 OptionsCont::getString(const std::string& name) const {
202  Option* o = getSecure(name);
203  return o->getString();
204 }
205 
206 
207 double
208 OptionsCont::getFloat(const std::string& name) const {
209  Option* o = getSecure(name);
210  return o->getFloat();
211 }
212 
213 
214 int
215 OptionsCont::getInt(const std::string& name) const {
216  Option* o = getSecure(name);
217  return o->getInt();
218 }
219 
220 
221 bool
222 OptionsCont::getBool(const std::string& name) const {
223  Option* o = getSecure(name);
224  return o->getBool();
225 }
226 
227 
228 const IntVector&
229 OptionsCont::getIntVector(const std::string& name) const {
230  Option* o = getSecure(name);
231  return o->getIntVector();
232 }
233 
234 const StringVector&
235 OptionsCont::getStringVector(const std::string& name) const {
236  Option* o = getSecure(name);
237  return o->getStringVector();
238 }
239 
240 bool
241 OptionsCont::set(const std::string& name, const std::string& value) {
242  Option* o = getSecure(name);
243  if (!o->isWriteable()) {
244  reportDoubleSetting(name);
245  return false;
246  }
247  try {
248  if (!o->set(value)) {
249  return false;
250  }
251  } catch (ProcessError& e) {
252  WRITE_ERROR("While processing option '" + name + "':\n " + e.what());
253  return false;
254  }
255  return true;
256 }
257 
258 
259 bool
260 OptionsCont::setDefault(const std::string& name, const std::string& value) {
261  if (set(name, value)) {
262  getSecure(name)->resetDefault();
263  return true;
264  }
265  return false;
266 }
267 
268 
269 bool
270 OptionsCont::setByRootElement(const std::string& root, const std::string& value) {
271  if (myXMLDefaults.count(root) > 0) {
272  return set(myXMLDefaults[root], value);
273  }
274  if (myXMLDefaults.count("") > 0) {
275  return set(myXMLDefaults[""], value);
276  }
277  return false;
278 }
279 
280 
281 std::vector<std::string>
282 OptionsCont::getSynonymes(const std::string& name) const {
283  Option* o = getSecure(name);
284  std::vector<std::string> v(0);
285  for (KnownContType::const_iterator i = myValues.begin(); i != myValues.end(); i++) {
286  if ((*i).second == o && name != (*i).first) {
287  v.push_back((*i).first);
288  }
289  }
290  return v;
291 }
292 
293 
294 const std::string&
295 OptionsCont::getDescription(const std::string& name) const {
296  return getSecure(name)->getDescription();
297 }
298 
299 
300 std::ostream&
301 operator<<(std::ostream& os, const OptionsCont& oc) {
302  std::vector<std::string> done;
303  os << "Options set:" << std::endl;
304  for (OptionsCont::KnownContType::const_iterator i = oc.myValues.begin();
305  i != oc.myValues.end(); i++) {
306  std::vector<std::string>::iterator j = std::find(done.begin(), done.end(), (*i).first);
307  if (j == done.end()) {
308  std::vector<std::string> synonymes = oc.getSynonymes((*i).first);
309  if (synonymes.size() != 0) {
310  os << (*i).first << " (";
311  for (j = synonymes.begin(); j != synonymes.end(); j++) {
312  if (j != synonymes.begin()) {
313  os << ", ";
314  }
315  os << (*j);
316  }
317  os << ")";
318  } else {
319  os << (*i).first;
320  }
321  if ((*i).second->isSet()) {
322  os << ": " << (*i).second->getValueString() << std::endl;
323  } else {
324  os << ": <INVALID>" << std::endl;
325  }
326  done.push_back((*i).first);
327  copy(synonymes.begin(), synonymes.end(), back_inserter(done));
328  }
329  }
330  return os;
331 }
332 
333 
334 void
335 OptionsCont::relocateFiles(const std::string& configuration) const {
336  for (Option* const option : myAddresses) {
337  if (option->isFileName() && option->isSet()) {
338  StringVector fileList = StringVector(option->getStringVector());
339  for (std::string& f : fileList) {
341  }
342  const std::string conv = joinToString(fileList, ',');
343  if (conv != joinToString(option->getStringVector(), ',')) {
344  const bool hadDefault = option->isDefault();
345  option->set(conv);
346  if (hadDefault) {
347  option->resetDefault();
348  }
349  }
350  }
351  }
352 }
353 
354 
355 bool
356 OptionsCont::isUsableFileList(const std::string& name) const {
357  Option* o = getSecure(name);
358  // check whether the option is set
359  // return false i not
360  if (!o->isSet()) {
361  return false;
362  }
363  // check whether the list of files is valid
364  bool ok = true;
365  std::vector<std::string> files = getStringVector(name);
366  if (files.size() == 0) {
367  WRITE_ERROR("The file list for '" + name + "' is empty.");
368  ok = false;
369  }
370  for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
371  if (!FileHelpers::isReadable(*fileIt)) {
372  if (*fileIt != "") {
373  WRITE_ERROR("File '" + *fileIt + "' is not accessible (" + std::strerror(errno) + ").");
374  ok = false;
375  } else {
376  WRITE_WARNING("Empty file name given; ignoring.");
377  }
378  }
379  }
380  return ok;
381 }
382 
383 
384 bool
385 OptionsCont::checkDependingSuboptions(const std::string& name, const std::string& prefix) const {
386  Option* o = getSecure(name);
387  if (o->isSet()) {
388  return true;
389  }
390  bool ok = true;
391  std::vector<std::string> seenSynonymes;
392  for (KnownContType::const_iterator i = myValues.begin(); i != myValues.end(); i++) {
393  if (std::find(seenSynonymes.begin(), seenSynonymes.end(), (*i).first) != seenSynonymes.end()) {
394  continue;
395  }
396  if ((*i).second->isSet() && !(*i).second->isDefault() && (*i).first.find(prefix) == 0) {
397  WRITE_ERROR("Option '" + (*i).first + "' needs option '" + name + "'.");
398  std::vector<std::string> synonymes = getSynonymes((*i).first);
399  std::copy(synonymes.begin(), synonymes.end(), std::back_inserter(seenSynonymes));
400  ok = false;
401  }
402  }
403  return ok;
404 }
405 
406 
407 void
408 OptionsCont::reportDoubleSetting(const std::string& arg) const {
409  std::vector<std::string> synonymes = getSynonymes(arg);
410  std::ostringstream s;
411  s << "A value for the option '" + arg + "' was already set.\n Possible synonymes: ";
412  for (std::vector<std::string>::iterator i = synonymes.begin(); i != synonymes.end();) {
413  s << (*i);
414  i++;
415  if (i != synonymes.end()) {
416  s << ", ";
417  }
418  }
419  WRITE_ERROR(s.str());
420 }
421 
422 
423 std::string
424 OptionsCont::convertChar(char abbr) const {
425  char buf[2];
426  buf[0] = abbr;
427  buf[1] = 0;
428  std::string s(buf);
429  return s;
430 }
431 
432 
433 bool
434 OptionsCont::isBool(const std::string& name) const {
435  Option* o = getSecure(name);
436  return o->isBool();
437 }
438 
439 
440 void
442  for (ItemAddressContType::iterator i = myAddresses.begin(); i != myAddresses.end(); i++) {
443  (*i)->resetWritable();
444  }
445 }
446 
447 
448 bool
449 OptionsCont::isWriteable(const std::string& name) {
450  Option* o = getSecure(name);
451  return o->isWriteable();
452 }
453 
454 
455 void
457  ItemAddressContType::iterator i;
458  for (i = myAddresses.begin(); i != myAddresses.end(); i++) {
459  delete (*i);
460  }
461  myAddresses.clear();
462  myValues.clear();
463  mySubTopics.clear();
464  mySubTopicEntries.clear();
465 }
466 
467 
468 void
469 OptionsCont::addDescription(const std::string& name,
470  const std::string& subtopic,
471  const std::string& description) {
472  Option* o = getSecure(name);
473  assert(o != 0);
474  assert(find(mySubTopics.begin(), mySubTopics.end(), subtopic) != mySubTopics.end());
475  o->setDescription(description);
476  mySubTopicEntries[subtopic].push_back(name);
477 }
478 
479 
480 void
481 OptionsCont::setApplicationName(const std::string& appName,
482  const std::string& fullName) {
483  myAppName = appName;
484  myFullName = fullName;
485 }
486 
487 
488 void
489 OptionsCont::setApplicationDescription(const std::string& appDesc) {
490  myAppDescription = appDesc;
491 }
492 
493 
494 void
495 OptionsCont::addCallExample(const std::string& example, const std::string& desc) {
496  myCallExamples.push_back(std::make_pair(example, desc));
497 }
498 
499 
500 void
501 OptionsCont::setAdditionalHelpMessage(const std::string& add) {
502  myAdditionalMessage = add;
503 }
504 
505 
506 void
507 OptionsCont::addCopyrightNotice(const std::string& copyrightLine) {
508  myCopyrightNotices.push_back(copyrightLine);
509 }
510 
511 
512 void
514  myCopyrightNotices.clear();
515 }
516 
517 
518 void
519 OptionsCont::addOptionSubTopic(const std::string& topic) {
520  mySubTopics.push_back(topic);
521  mySubTopicEntries[topic] = std::vector<std::string>();
522 }
523 
524 
525 void
526 OptionsCont::splitLines(std::ostream& os, std::string what,
527  int offset, int nextOffset) {
528  while (what.length() > 0) {
529  if ((int)what.length() > 79 - offset) {
530  std::string::size_type splitPos = what.rfind(';', 79 - offset);
531  if (splitPos == std::string::npos) {
532  splitPos = what.rfind(' ', 79 - offset);
533  } else {
534  splitPos++;
535  }
536  if (splitPos != std::string::npos) {
537  os << what.substr(0, splitPos) << std::endl;
538  what = what.substr(splitPos);
539  for (int r = 0; r < nextOffset + 1; ++r) {
540  os << ' ';
541  }
542  } else {
543  os << what;
544  what = "";
545  }
546  offset = nextOffset;
547  } else {
548  os << what;
549  what = "";
550  }
551  }
552  os << std::endl;
553 }
554 
555 
556 bool
557 OptionsCont::processMetaOptions(bool missingOptions) {
558  if (missingOptions) {
559  // no options are given
560  std::cout << myFullName << std::endl;
561  std::cout << " Build features: " << HAVE_ENABLED << std::endl;
562  for (std::vector<std::string>::const_iterator it =
563  myCopyrightNotices.begin(); it != myCopyrightNotices.end(); ++it) {
564  std::cout << " " << *it << std::endl;
565  }
566  std::cout << " License EPL-2.0: Eclipse Public License Version 2 <https://eclipse.org/legal/epl-v20.html>\n";
567  std::cout << " Use --help to get the list of options." << std::endl;
568  return true;
569  }
570 
571  myWriteLicense = getBool("write-license");
572  // check whether the help shall be printed
573  if (getBool("help")) {
574  std::cout << myFullName << std::endl;
575  for (std::vector<std::string>::const_iterator it =
576  myCopyrightNotices.begin(); it != myCopyrightNotices.end(); ++it) {
577  std::cout << " " << *it << std::endl;
578  }
579  printHelp(std::cout);
580  return true;
581  }
582  // check whether the help shall be printed
583  if (getBool("version")) {
584  std::cout << myFullName << std::endl;
585  std::cout << " Build features: " << HAVE_ENABLED << std::endl;
586  for (std::vector<std::string>::const_iterator it =
587  myCopyrightNotices.begin(); it != myCopyrightNotices.end(); ++it) {
588  std::cout << " " << *it << std::endl;
589  }
590  std::cout << "\n" << myFullName << " is part of SUMO.\n";
591  std::cout << "This program and the accompanying materials\n";
592  std::cout << "are made available under the terms of the Eclipse Public License v2.0\n";
593  std::cout << "which accompanies this distribution, and is available at\n";
594  std::cout << "http://www.eclipse.org/legal/epl-v20.html\n";
595  std::cout << "SPDX-License-Identifier: EPL-2.0" << std::endl;
596  return true;
597  }
598  // check whether the settings shall be printed
599  if (exists("print-options") && getBool("print-options")) {
600  std::cout << (*this);
601  }
602  // check whether something has to be done with options
603  // whether the current options shall be saved
604  if (isSet("save-configuration", false)) { // sumo-gui does not register these
605  if (getString("save-configuration") == "-" || getString("save-configuration") == "stdout") {
606  writeConfiguration(std::cout, true, false, getBool("save-commented"));
607  return true;
608  }
609  std::ofstream out(getString("save-configuration").c_str());
610  if (!out.good()) {
611  throw ProcessError("Could not save configuration to '" + getString("save-configuration") + "'");
612  } else {
613  writeConfiguration(out, true, false, getBool("save-commented"));
614  if (getBool("verbose")) {
615  WRITE_MESSAGE("Written configuration to '" + getString("save-configuration") + "'");
616  }
617  return true;
618  }
619  }
620  // whether the template shall be saved
621  if (isSet("save-template", false)) { // sumo-gui does not register these
622  if (getString("save-template") == "-" || getString("save-template") == "stdout") {
623  writeConfiguration(std::cout, false, true, getBool("save-commented"));
624  return true;
625  }
626  std::ofstream out(getString("save-template").c_str());
627  if (!out.good()) {
628  throw ProcessError("Could not save template to '" + getString("save-template") + "'");
629  } else {
630  writeConfiguration(out, false, true, getBool("save-commented"));
631  if (getBool("verbose")) {
632  WRITE_MESSAGE("Written template to '" + getString("save-template") + "'");
633  }
634  return true;
635  }
636  }
637  if (isSet("save-schema", false)) { // sumo-gui does not register these
638  if (getString("save-schema") == "-" || getString("save-schema") == "stdout") {
639  writeSchema(std::cout);
640  return true;
641  }
642  std::ofstream out(getString("save-schema").c_str());
643  if (!out.good()) {
644  throw ProcessError("Could not save schema to '" + getString("save-schema") + "'");
645  } else {
646  writeSchema(out);
647  if (getBool("verbose")) {
648  WRITE_MESSAGE("Written schema to '" + getString("save-schema") + "'");
649  }
650  return true;
651  }
652  }
653  return false;
654 }
655 
656 void
657 OptionsCont::printHelp(std::ostream& os) {
658  std::vector<std::string>::const_iterator i, j;
659  // print application description
660  splitLines(os, myAppDescription, 0, 0);
661  os << std::endl;
662 
663  // check option sizes first
664  // we want to know how large the largest not-too-large-entry will be
665  int tooLarge = 40;
666  int maxSize = 0;
667  for (i = mySubTopics.begin(); i != mySubTopics.end(); ++i) {
668  const std::vector<std::string>& entries = mySubTopicEntries[*i];
669  for (j = entries.begin(); j != entries.end(); ++j) {
670  Option* o = getSecure(*j);
671  // name, two leading spaces and "--"
672  int csize = (int)j->length() + 2 + 4;
673  // abbreviation length ("-X, "->4chars) if any
674  const std::vector<std::string> synonymes = getSynonymes(*j);
675  for (std::vector<std::string>::const_iterator s = synonymes.begin(); s != synonymes.end(); ++s) {
676  if (s->length() == 1 && myDeprecatedSynonymes.count(*s) == 0) {
677  csize += 4;
678  break;
679  }
680  }
681  // the type name
682  if (!o->isBool()) {
683  csize += 1 + (int)o->getTypeName().length();
684  }
685  // divider
686  csize += 2;
687  if (csize < tooLarge && maxSize < csize) {
688  maxSize = csize;
689  }
690  }
691  }
692 
693  const std::string helpTopic = StringUtils::to_lower_case(getSecure("help")->getValueString());
694  if (helpTopic != "") {
695  bool foundTopic = false;
696  for (const std::string& topic : mySubTopics) {
697  if (StringUtils::to_lower_case(topic).find(helpTopic) != std::string::npos) {
698  foundTopic = true;
699  printHelpOnTopic(topic, tooLarge, maxSize, os);
700  }
701  }
702  if (!foundTopic) {
703  // print topic list
704  os << "Help Topics:" << std::endl;
705  for (std::string t : mySubTopics) {
706  os << " " << t << std::endl;
707  }
708  }
709  return;
710  }
711  // print usage BNF
712  os << "Usage: " << myAppName << " [OPTION]*" << std::endl;
713  // print additional text if any
714  if (myAdditionalMessage.length() > 0) {
715  os << myAdditionalMessage << std::endl << ' ' << std::endl;
716  }
717  // print the options
718  for (i = mySubTopics.begin(); i != mySubTopics.end(); ++i) {
719  printHelpOnTopic(*i, tooLarge, maxSize, os);
720  }
721  os << std::endl;
722  // print usage examples, calc size first
723  if (myCallExamples.size() != 0) {
724  os << "Examples:" << std::endl;
725  for (std::vector<std::pair<std::string, std::string> >::const_iterator e = myCallExamples.begin(); e != myCallExamples.end(); ++e) {
726  os << " " << myAppName << ' ' << e->first << std::endl;
727  os << " " << e->second << std::endl;
728  }
729  }
730  os << std::endl;
731  os << "Report bugs at <https://github.com/eclipse/sumo/issues>." << std::endl;
732  os << "Get in contact via <sumo@dlr.de>." << std::endl;
733 }
734 
735 void
736 OptionsCont::printHelpOnTopic(const std::string& topic, int tooLarge, int maxSize, std::ostream& os) {
737  os << topic << " Options:" << std::endl;
738  for (std::string entry : mySubTopicEntries[topic]) {
739  // start length computation
740  int csize = (int)entry.length() + 2;
741  Option* o = getSecure(entry);
742  os << " ";
743  // write abbreviation if given
744  std::vector<std::string> synonymes = getSynonymes(entry);
745  for (std::vector<std::string>::const_iterator s = synonymes.begin(); s != synonymes.end(); ++s) {
746  if (s->length() == 1 && myDeprecatedSynonymes.count(*s) == 0) {
747  os << '-' << *s << ", ";
748  csize += 4;
749  break;
750  }
751  }
752  // write leading '-'/"--"
753  os << "--";
754  csize += 2;
755  // write the name
756  os << entry;
757  // write the type if not a bool option
758  if (!o->isBool()) {
759  os << ' ' << o->getTypeName();
760  csize += 1 + (int)o->getTypeName().length();
761  }
762  csize += 2;
763  // write the description formatting it
764  os << " ";
765  for (int r = maxSize; r > csize; --r) {
766  os << ' ';
767  }
768  int offset = csize > tooLarge ? csize : maxSize;
769  splitLines(os, o->getDescription(), offset, maxSize);
770  }
771  os << std::endl;
772 }
773 
774 void
775 OptionsCont::writeConfiguration(std::ostream& os, const bool filled,
776  const bool complete, const bool addComments,
777  const bool inComment) const {
778  if (!inComment) {
779  writeXMLHeader(os, false);
780  }
781  os << "<configuration xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.dlr.de/xsd/";
782  if (myAppName == "sumo-gui") {
783  os << "sumo";
784  } else if (myAppName == "netedit") {
785  os << "netconvert";
786  } else {
787  os << myAppName;
788  }
789  os << "Configuration.xsd\">" << std::endl << std::endl;
790  for (std::vector<std::string>::const_iterator i = mySubTopics.begin(); i != mySubTopics.end(); ++i) {
791  std::string subtopic = *i;
792  if (subtopic == "Configuration" && !complete) {
793  continue;
794  }
795  std::replace(subtopic.begin(), subtopic.end(), ' ', '_');
796  std::transform(subtopic.begin(), subtopic.end(), subtopic.begin(), tolower);
797  const std::vector<std::string>& entries = mySubTopicEntries.find(*i)->second;
798  bool hadOne = false;
799  for (std::vector<std::string>::const_iterator j = entries.begin(); j != entries.end(); ++j) {
800  Option* o = getSecure(*j);
801  bool write = complete || (filled && !o->isDefault());
802  if (!write) {
803  continue;
804  }
805  if (!hadOne) {
806  os << " <" << subtopic << ">" << std::endl;
807  }
808  // add the comment if wished
809  if (addComments) {
810  os << " <!-- " << StringUtils::escapeXML(o->getDescription(), inComment) << " -->" << std::endl;
811  }
812  // write the option and the value (if given)
813  os << " <" << *j << " value=\"";
814  if (o->isSet() && (filled || o->isDefault())) {
815  os << StringUtils::escapeXML(o->getValueString(), inComment);
816  }
817  if (complete) {
818  std::vector<std::string> synonymes = getSynonymes(*j);
819  if (!synonymes.empty()) {
820  os << "\" synonymes=\"";
821  for (std::vector<std::string>::const_iterator s = synonymes.begin(); s != synonymes.end(); ++s) {
822  if (s != synonymes.begin()) {
823  os << " ";
824  }
825  os << (*s);
826  }
827  }
828  os << "\" type=\"" << o->getTypeName();
829  if (!addComments) {
830  os << "\" help=\"" << StringUtils::escapeXML(o->getDescription());
831  }
832  }
833  os << "\"/>" << std::endl;
834  // append an endline if a comment was printed
835  if (addComments) {
836  os << std::endl;
837  }
838  hadOne = true;
839  }
840  if (hadOne) {
841  os << " </" << subtopic << ">" << std::endl << std::endl;
842  }
843  }
844  os << "</configuration>" << std::endl;
845 }
846 
847 
848 void
849 OptionsCont::writeSchema(std::ostream& os) {
850  writeXMLHeader(os, false);
851  os << "<xsd:schema elementFormDefault=\"qualified\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n\n";
852  os << " <xsd:include schemaLocation=\"baseTypes.xsd\"/>\n";
853  os << " <xsd:element name=\"configuration\" type=\"configurationType\"/>\n\n";
854  os << " <xsd:complexType name=\"configurationType\">\n";
855  os << " <xsd:all>\n";
856  for (std::vector<std::string>::const_iterator i = mySubTopics.begin(); i != mySubTopics.end(); ++i) {
857  std::string subtopic = *i;
858  if (subtopic == "Configuration") {
859  continue;
860  }
861  std::replace(subtopic.begin(), subtopic.end(), ' ', '_');
862  std::transform(subtopic.begin(), subtopic.end(), subtopic.begin(), tolower);
863  os << " <xsd:element name=\"" << subtopic << "\" type=\"" << subtopic << "TopicType\" minOccurs=\"0\"/>\n";
864  }
865  os << " </xsd:all>\n";
866  os << " </xsd:complexType>\n\n";
867  for (std::vector<std::string>::const_iterator i = mySubTopics.begin(); i != mySubTopics.end(); ++i) {
868  std::string subtopic = *i;
869  if (subtopic == "Configuration") {
870  continue;
871  }
872  std::replace(subtopic.begin(), subtopic.end(), ' ', '_');
873  std::transform(subtopic.begin(), subtopic.end(), subtopic.begin(), tolower);
874  os << " <xsd:complexType name=\"" << subtopic << "TopicType\">\n";
875  os << " <xsd:all>\n";
876  const std::vector<std::string>& entries = mySubTopicEntries[*i];
877  for (std::vector<std::string>::const_iterator j = entries.begin(); j != entries.end(); ++j) {
878  Option* o = getSecure(*j);
879  std::string type = o->getTypeName();
880  std::transform(type.begin(), type.end(), type.begin(), tolower);
881  if (type == "int[]") {
882  type = "intArray";
883  }
884  if (type == "str[]") {
885  type = "strArray";
886  }
887  os << " <xsd:element name=\"" << *j << "\" type=\"" << type << "OptionType\" minOccurs=\"0\"/>\n";
888  }
889  os << " </xsd:all>\n";
890  os << " </xsd:complexType>\n\n";
891  }
892  os << "</xsd:schema>\n";
893 }
894 
895 
896 void
897 OptionsCont::writeXMLHeader(std::ostream& os, const bool includeConfig) const {
898  time_t rawtime;
899  char buffer [80];
900 
901  os << "<?xml version=\"1.0\"" << SUMOSAXAttributes::ENCODING << "?>\n\n";
902  time(&rawtime);
903  strftime(buffer, 80, "<!-- generated on %c by ", localtime(&rawtime));
904  os << buffer << myFullName << "\n";
905  if (myWriteLicense) {
906  os << "This data file and the accompanying materials\n";
907  os << "are made available under the terms of the Eclipse Public License v2.0\n";
908  os << "which accompanies this distribution, and is available at\n";
909  os << "http://www.eclipse.org/legal/epl-v20.html\n";
910  os << "SPDX-License-Identifier: EPL-2.0\n";
911  }
912  if (includeConfig) {
913  writeConfiguration(os, true, false, false, true);
914  }
915  os << "-->\n\n";
916 }
917 
918 
919 bool
920 OptionsCont::isInStringVector(const std::string& optionName,
921  const std::string& itemName) const {
922  if (isSet(optionName)) {
923  std::vector<std::string> values = getStringVector(optionName);
924  return std::find(values.begin(), values.end(), itemName) != values.end();
925  }
926  return false;
927 }
928 
929 
930 /****************************************************************************/
OptionsCont::isSet
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
Definition: OptionsCont.cpp:135
OptionsCont::myCopyrightNotices
std::vector< std::string > myCopyrightNotices
Definition: OptionsCont.h:731
OptionsCont::myDeprecatedSynonymes
std::map< std::string, bool > myDeprecatedSynonymes
A map from deprecated options to a bool indicating whether we warned about deprecation.
Definition: OptionsCont.h:740
OptionsCont::getInt
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
Definition: OptionsCont.cpp:215
OptionsCont::processMetaOptions
bool processMetaOptions(bool missingOptions)
Checks for help and configuration output, returns whether we should exit.
Definition: OptionsCont.cpp:557
StringUtils::urlDecode
static std::string urlDecode(const std::string &encoded)
Definition: StringUtils.cpp:231
OptionsCont::getIntVector
const IntVector & getIntVector(const std::string &name) const
Returns the list of integer-value of the named option (only for Option_IntVector)
Definition: OptionsCont.cpp:229
OptionsCont::checkDependingSuboptions
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.
Definition: OptionsCont.cpp:385
WRITE_WARNING
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:275
OptionsCont::setByRootElement
bool setByRootElement(const std::string &name, const std::string &value)
Sets the given value for the option which can handle the given XML root.
Definition: OptionsCont.cpp:270
OptionsCont::writeXMLHeader
void writeXMLHeader(std::ostream &os, const bool includeConfig=true) const
Writes a standard XML header, including the configuration.
Definition: OptionsCont.cpp:897
Option
A class representing a single program option.
Definition: Option.h:75
OptionsCont::getSynonymes
std::vector< std::string > getSynonymes(const std::string &name) const
Returns the synonymes of an option name.
Definition: OptionsCont.cpp:282
OptionsCont::reportDoubleSetting
void reportDoubleSetting(const std::string &arg) const
Reports an error that the option has already been set.
Definition: OptionsCont.cpp:408
OptionsCont::myFullName
std::string myFullName
Definition: OptionsCont.h:725
Option::isWriteable
bool isWriteable() const
Returns the information whether the option may be set a further time.
Definition: Option.cpp:143
OptionsCont::relocateFiles
void relocateFiles(const std::string &configuration) const
Modifies file name options according to the configuration path.
Definition: OptionsCont.cpp:335
Option::resetDefault
void resetDefault()
Resets the option to be on its default value.
Definition: Option.cpp:155
OptionsCont.h
OptionsCont::resetWritable
void resetWritable()
Resets all options to be writeable.
Definition: OptionsCont.cpp:441
OptionsCont::set
bool set(const std::string &name, const std::string &value)
Sets the given value for the named option.
Definition: OptionsCont.cpp:241
OptionsCont::mySubTopics
std::vector< std::string > mySubTopics
lists of option subtopics and copyright notices
Definition: OptionsCont.h:731
MsgHandler.h
strict_fstream::strerror
static std::string strerror()
Definition: strict_fstream.hpp:29
OptionsCont::getString
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
Definition: OptionsCont.cpp:201
FileHelpers.h
HAVE_ENABLED
#define HAVE_ENABLED
Definition: config.h:29
StringUtils::to_lower_case
static std::string to_lower_case(std::string str)
Transfers the content to lower case.
Definition: StringUtils.cpp:59
OptionsCont::exists
bool exists(const std::string &name) const
Returns the information whether the named option is known.
Definition: OptionsCont.cpp:129
OptionsCont::getBool
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
Definition: OptionsCont.cpp:222
OptionsCont::myValues
KnownContType myValues
Definition: OptionsCont.h:722
OptionsCont::getOptions
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:57
OptionsCont::myAdditionalMessage
std::string myAdditionalMessage
Definition: OptionsCont.h:725
FileHelpers::checkForRelativity
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.
Definition: FileHelpers.cpp:152
OptionsCont::unSet
void unSet(const std::string &name, bool failOnNonExistant=true) const
Marks the option as unset.
Definition: OptionsCont.cpp:149
Option::isBool
virtual bool isBool() const
Returns the information whether the option is a bool option.
Definition: Option.cpp:125
OptionsCont::getDescription
const std::string & getDescription(const std::string &name) const
Returns the option description.
Definition: OptionsCont.cpp:295
Option::setDescription
void setDescription(const std::string &desc)
Sets the description of what this option does.
Definition: Option.cpp:167
Option::isDefault
virtual bool isDefault() const
Returns the information whether the option holds the default value.
Definition: Option.cpp:131
OptionsCont::printHelp
void printHelp(std::ostream &os)
Prints the help.
Definition: OptionsCont.cpp:657
OptionsCont::addCopyrightNotice
void addCopyrightNotice(const std::string &copyrightLine)
Adds a copyright notice to the help output.
Definition: OptionsCont.cpp:507
OptionsCont::mySubTopicEntries
std::map< std::string, std::vector< std::string > > mySubTopicEntries
A map from subtopic to option.
Definition: OptionsCont.h:734
OptionsCont::myAddresses
ItemAddressContType myAddresses
Definition: OptionsCont.h:719
IntVector
std::vector< int > IntVector
Definition of a vector of ints.
Definition: Option.h:40
OptionsCont::getStringVector
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
Definition: OptionsCont.cpp:235
Option::getTypeName
virtual const std::string & getTypeName() const
Returns the mml-type name of this option.
Definition: Option.cpp:173
OptionsCont::convertChar
std::string convertChar(char abbr) const
Converts an abbreviation into a name.
Definition: OptionsCont.cpp:424
OptionsCont::myCallExamples
std::vector< std::pair< std::string, std::string > > myCallExamples
list of call examples
Definition: OptionsCont.h:728
OptionsCont::addDescription
void addDescription(const std::string &name, const std::string &subtopic, const std::string &description)
Adds a description for an option.
Definition: OptionsCont.cpp:469
OptionsCont::isUsableFileList
bool isUsableFileList(const std::string &name) const
Checks whether the named option is usable as a file list (with at least a single file)
Definition: OptionsCont.cpp:356
StringVector
std::vector< std::string > StringVector
Definition of a vector of strings.
Definition: Option.h:45
OptionsCont::setApplicationName
void setApplicationName(const std::string &appName, const std::string &fullName)
Sets the application name.
Definition: OptionsCont.cpp:481
OptionsCont::addSynonyme
void addSynonyme(const std::string &name1, const std::string &name2, bool isDeprecated=false)
Adds a synonyme for an options name (any order)
Definition: OptionsCont.cpp:95
operator<<
std::ostream & operator<<(std::ostream &os, const OptionsCont &oc)
Definition: OptionsCont.cpp:301
OptionsCont::myWriteLicense
bool myWriteLicense
Information whether we should always include license information in file headers.
Definition: OptionsCont.h:743
StringUtils::escapeXML
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.
Definition: StringUtils.cpp:190
Option::getDescription
const std::string & getDescription() const
Returns the description of what this option does.
Definition: Option.cpp:161
OptionsCont::doRegister
void doRegister(const std::string &name, Option *v)
Adds an option under the given name.
Definition: OptionsCont.cpp:74
ProcessError
Definition: UtilExceptions.h:39
OptionsCont::isInStringVector
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.
Definition: OptionsCont.cpp:920
Option::isSet
bool isSet() const
returns the information whether this options holds a valid value
Definition: Option.cpp:68
OptionsCont::setAdditionalHelpMessage
void setAdditionalHelpMessage(const std::string &add)
Sets an additional message to be printed at the begin of the help screen.
Definition: OptionsCont.cpp:501
UtilExceptions.h
OptionsCont
A storage for options typed value containers)
Definition: OptionsCont.h:89
Option::set
virtual bool set(const std::string &v)=0
Stores the given value.
Option::getFloat
virtual double getFloat() const
Returns the stored double value.
Definition: Option.cpp:74
OptionsCont::addXMLDefault
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.
Definition: OptionsCont.cpp:123
OptionsCont::isBool
bool isBool(const std::string &name) const
Returns the information whether the option is a boolean option.
Definition: OptionsCont.cpp:434
OptionsCont::isDefault
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
Definition: OptionsCont.cpp:163
OptionsCont::splitLines
void splitLines(std::ostream &os, std::string what, int offset, int nextOffset)
Writes the given string 'formatted'.
Definition: OptionsCont.cpp:526
OptionsCont::addOptionSubTopic
void addOptionSubTopic(const std::string &topic)
Adds an option subtopic.
Definition: OptionsCont.cpp:519
OptionsCont::setApplicationDescription
void setApplicationDescription(const std::string &appDesc)
Sets the application description.
Definition: OptionsCont.cpp:489
OptionsCont::getFloat
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
Definition: OptionsCont.cpp:208
StringUtils.h
OptionsCont::myAppName
std::string myAppName
some information on the application
Definition: OptionsCont.h:725
OptionsCont::myOptions
static OptionsCont myOptions
The static options container used.
Definition: OptionsCont.h:710
Option.h
OptionsCont::writeSchema
void writeSchema(std::ostream &os)
Writes the xml schema for the configuration.
Definition: OptionsCont.cpp:849
OptionsCont::addCallExample
void addCallExample(const std::string &example, const std::string &desc)
Add a call example.
Definition: OptionsCont.cpp:495
OptionsCont::getSecure
Option * getSecure(const std::string &name) const
Returns the named option.
Definition: OptionsCont.cpp:173
OptionsCont::printHelpOnTopic
void printHelpOnTopic(const std::string &topic, int tooLarge, int maxSize, std::ostream &os)
Prints help on the given topic.
Definition: OptionsCont.cpp:736
SUMOSAXAttributes::ENCODING
static const std::string ENCODING
The encoding of parsed strings.
Definition: SUMOSAXAttributes.h:407
Option::getString
virtual std::string getString() const
Returns the stored string value.
Definition: Option.cpp:86
SUMOSAXAttributes.h
joinToString
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:246
OptionsCont::~OptionsCont
~OptionsCont()
Destructor.
Definition: OptionsCont.cpp:68
OptionsCont::clearCopyrightNotices
void clearCopyrightNotices()
Removes all copyright information.
Definition: OptionsCont.cpp:513
FileHelpers::isReadable
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:49
Option::getIntVector
virtual const IntVector & getIntVector() const
Returns the stored integer vector.
Definition: Option.cpp:98
config.h
OptionsCont::OptionsCont
OptionsCont()
Constructor.
Definition: OptionsCont.cpp:62
StringTokenizer.h
Option::getBool
virtual bool getBool() const
Returns the stored boolean value.
Definition: Option.cpp:92
OptionsCont::writeConfiguration
void writeConfiguration(std::ostream &os, const bool filled, const bool complete, const bool addComments, const bool inComment=false) const
Writes the configuration.
Definition: OptionsCont.cpp:775
Option::getStringVector
virtual const StringVector & getStringVector() const
Returns the stored string vector.
Definition: Option.cpp:103
OptionsCont::isWriteable
bool isWriteable(const std::string &name)
Returns the information whether the named option may be set.
Definition: OptionsCont.cpp:449
OptionsCont::myXMLDefaults
std::map< std::string, std::string > myXMLDefaults
A map from XML root element to option.
Definition: OptionsCont.h:737
Option::getInt
virtual int getInt() const
Returns the stored integer value.
Definition: Option.cpp:80
OptionsCont::clear
void clear()
Removes all information from the container.
Definition: OptionsCont.cpp:456
WRITE_ERROR
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:283
WRITE_MESSAGE
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:277
Option::getValueString
virtual std::string getValueString() const =0
Returns the string-representation of the value.
OptionsCont::setDefault
bool setDefault(const std::string &name, const std::string &value)
Sets the given value for the named option as new default value.
Definition: OptionsCont.cpp:260
OptionsCont::myAppDescription
std::string myAppDescription
Definition: OptionsCont.h:725