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