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