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