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