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