SUMO - Simulation of Urban MObility

OptionsCont.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // A storage for options (typed value containers)
00008 /****************************************************************************/
00009 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00010 // Copyright (C) 2001-2011 DLR (http://www.dlr.de/) and contributors
00011 /****************************************************************************/
00012 //
00013 //   This program is free software; you can redistribute it and/or modify
00014 //   it under the terms of the GNU General Public License as published by
00015 //   the Free Software Foundation; either version 2 of the License, or
00016 //   (at your option) any later version.
00017 //
00018 /****************************************************************************/
00019 // ===========================================================================
00020 // included modules
00021 // ===========================================================================
00022 #ifdef _MSC_VER
00023 #include <windows_config.h>
00024 #else
00025 #include <config.h>
00026 #endif
00027 
00028 #include <map>
00029 #include <string>
00030 #include <exception>
00031 #include <algorithm>
00032 #include <vector>
00033 #include <iostream>
00034 #include <cstdlib>
00035 #include <cassert>
00036 #include <ctime>
00037 #include <iterator>
00038 #include "Option.h"
00039 #include "OptionsCont.h"
00040 #include <utils/common/UtilExceptions.h>
00041 #include <utils/common/FileHelpers.h>
00042 #include <utils/common/MsgHandler.h>
00043 #include <utils/common/StringTokenizer.h>
00044 #include <utils/common/StringUtils.h>
00045 #include <sstream>
00046 
00047 #ifdef CHECK_MEMORY_LEAKS
00048 #include <foreign/nvwa/debug_new.h>
00049 #endif // CHECK_MEMORY_LEAKS
00050 
00051 
00052 // ===========================================================================
00053 // static member definitions
00054 // ===========================================================================
00055 OptionsCont OptionsCont::myOptions;
00056 
00057 
00058 // ===========================================================================
00059 // method definitions
00060 // ===========================================================================
00061 OptionsCont&
00062 OptionsCont::getOptions() {
00063     return myOptions;
00064 }
00065 
00066 
00067 OptionsCont::OptionsCont()
00068     : myAddresses(), myValues(), myDeprecatedSynonymes(), myHaveInformedAboutDeprecatedDivider(false) {
00069     myCopyrightNotices.push_back("Copyright (C) 2001-2011 DLR and contributors; http://sumo.sourceforge.net");
00070 }
00071 
00072 
00073 OptionsCont::~OptionsCont() {
00074     clear();
00075 }
00076 
00077 
00078 void
00079 OptionsCont::doRegister(const std::string& name, Option* v) {
00080     assert(v!=0);
00081     ItemAddressContType::iterator i = find(myAddresses.begin(), myAddresses.end(), v);
00082     if (i==myAddresses.end()) {
00083         myAddresses.push_back(v);
00084     }
00085     if (myValues.find(name)!=myValues.end()) {
00086         throw ProcessError(name + " is an already used option name.");
00087     }
00088     myValues[name] = v;
00089 }
00090 
00091 
00092 void
00093 OptionsCont::doRegister(const std::string& name1, char abbr, Option* v) {
00094     doRegister(name1, v);
00095     doRegister(convertChar(abbr), v);
00096 }
00097 
00098 
00099 void
00100 OptionsCont::addSynonyme(const std::string& name1, const std::string& name2, bool isDeprecated) {
00101     KnownContType::iterator i1 = myValues.find(name1);
00102     KnownContType::iterator i2 = myValues.find(name2);
00103     if (i1==myValues.end()&&i2==myValues.end()) {
00104         throw ProcessError("Neither the option '" + name1 + "' nor the option '" + name2 + "' is known yet");
00105     }
00106     if (i1!=myValues.end()&&i2!=myValues.end()) {
00107         if ((*i1).second==(*i2).second) {
00108             return;
00109         }
00110         throw ProcessError("Both options '" + name1 + "' and '" + name2 + "' do exist and differ.");
00111     }
00112     if (i1==myValues.end()&&i2!=myValues.end()) {
00113         doRegister(name1, (*i2).second);
00114         if (isDeprecated) {
00115             myDeprecatedSynonymes[name1] = false;
00116         }
00117     }
00118     if (i1!=myValues.end()&&i2==myValues.end()) {
00119         doRegister(name2, (*i1).second);
00120         if (isDeprecated) {
00121             myDeprecatedSynonymes[name2] = false;
00122         }
00123     }
00124 }
00125 
00126 
00127 bool
00128 OptionsCont::exists(const std::string& name) const {
00129     return myValues.count(name) > 0;
00130 }
00131 
00132 
00133 bool
00134 OptionsCont::isSet(const std::string& name, bool failOnNonExistant) const {
00135     KnownContType::const_iterator i = myValues.find(name);
00136     if (i==myValues.end()) {
00137         if (failOnNonExistant) {
00138             throw ProcessError("Internal request for unknown option '" + name + "'!");
00139         } else {
00140             return false;
00141         }
00142     }
00143     return (*i).second->isSet();
00144 }
00145 
00146 
00147 bool
00148 OptionsCont::isDefault(const std::string& name) const {
00149     KnownContType::const_iterator i = myValues.find(name);
00150     if (i==myValues.end()) {
00151         return false;
00152     }
00153     return (*i).second->isDefault();
00154 }
00155 
00156 
00157 Option*
00158 OptionsCont::getSecure(const std::string& name) const {
00159     KnownContType::const_iterator k = myValues.find(name);
00160     if (k==myValues.end()) {
00161         throw ProcessError("No option with the name '" + name + "' exists.");
00162     }
00163     std::map<std::string, bool>::iterator s = myDeprecatedSynonymes.find(name);
00164     if (s != myDeprecatedSynonymes.end() && !s->second) {
00165         std::string defaultName;
00166         for (std::map<std::string, std::vector<std::string> >::const_iterator i=mySubTopicEntries.begin(); i!=mySubTopicEntries.end(); ++i) {
00167             for (std::vector<std::string>::const_iterator j=i->second.begin(); j!=i->second.end(); ++j) {
00168                 KnownContType::const_iterator l = myValues.find(*j);
00169                 if (l != myValues.end() && l->second == k->second) {
00170                     defaultName = *j;
00171                     break;
00172                 }
00173             }
00174             if (defaultName != "") {
00175                 break;
00176             }
00177         }
00178         WRITE_WARNING("Please note that '" + name + "' is deprecated.\n Use '" + defaultName + "' instead.");
00179         s->second = true;
00180     }
00181     return k->second;
00182 }
00183 
00184 
00185 std::string
00186 OptionsCont::getString(const std::string& name) const {
00187     Option* o = getSecure(name);
00188     return o->getString();
00189 }
00190 
00191 
00192 SUMOReal
00193 OptionsCont::getFloat(const std::string& name) const {
00194     Option* o = getSecure(name);
00195     return o->getFloat();
00196 }
00197 
00198 
00199 int
00200 OptionsCont::getInt(const std::string& name) const {
00201     Option* o = getSecure(name);
00202     return o->getInt();
00203 }
00204 
00205 
00206 bool
00207 OptionsCont::getBool(const std::string& name) const {
00208     Option* o = getSecure(name);
00209     return o->getBool();
00210 }
00211 
00212 
00213 const IntVector&
00214 OptionsCont::getIntVector(const std::string& name) const {
00215     Option* o = getSecure(name);
00216     return o->getIntVector();
00217 }
00218 
00219 
00220 bool
00221 OptionsCont::set(const std::string& name, const std::string& value) {
00222     Option* o = getSecure(name);
00223     if (!o->isWriteable()) {
00224         reportDoubleSetting(name);
00225         return false;
00226     }
00227     try {
00228         if (!o->set(value)) {
00229             return false;
00230         }
00231     } catch (ProcessError& e) {
00232         WRITE_ERROR("While processing option '" + name + "':\n " + e.what());
00233         return false;
00234     }
00235     return true;
00236 }
00237 
00238 
00239 std::vector<std::string>
00240 OptionsCont::getSynonymes(const std::string& name) const {
00241     Option* o = getSecure(name);
00242     std::vector<std::string> v(0);
00243     for (KnownContType::const_iterator i=myValues.begin(); i!=myValues.end(); i++) {
00244         if ((*i).second==o&&name!=(*i).first) {
00245             v.push_back((*i).first);
00246         }
00247     }
00248     return v;
00249 }
00250 
00251 
00252 std::ostream&
00253 operator<<(std::ostream& os, const OptionsCont& oc) {
00254     std::vector<std::string> done;
00255     os << "Options set:" << std::endl;
00256     for (OptionsCont::KnownContType::const_iterator i=oc.myValues.begin();
00257             i!=oc.myValues.end(); i++) {
00258         std::vector<std::string>::iterator j = find(done.begin(), done.end(), (*i).first);
00259         if (j==done.end()) {
00260             std::vector<std::string> synonymes = oc.getSynonymes((*i).first);
00261             if (synonymes.size()!=0) {
00262                 os << (*i).first << " (";
00263                 for (j=synonymes.begin(); j!=synonymes.end(); j++) {
00264                     if (j!=synonymes.begin()) {
00265                         os << ", ";
00266                     }
00267                     os << (*j);
00268                 }
00269                 os << ")";
00270             } else {
00271                 os << (*i).first;
00272             }
00273             if ((*i).second->isSet()) {
00274                 os << ": " << (*i).second->getValueString() << std::endl;
00275             } else {
00276                 os << ": <INVALID>" << std::endl;
00277             }
00278             done.push_back((*i).first);
00279             copy(synonymes.begin(), synonymes.end(), back_inserter(done));
00280         }
00281     }
00282     return os;
00283 }
00284 
00285 
00286 void
00287 OptionsCont::relocateFiles(const std::string& configuration) const {
00288     for (ItemAddressContType::const_iterator i=myAddresses.begin(); i!=myAddresses.end(); i++) {
00289         if ((*i)->isFileName() && (*i)->isSet()) {
00290             StringTokenizer st((*i)->getString(), ";, ", true);
00291             std::string conv;
00292             while (st.hasNext()) {
00293                 if (conv.length()!=0) {
00294                     conv += ',';
00295                 }
00296                 std::string tmp = st.next();
00297                 if (!FileHelpers::isAbsolute(tmp)) {
00298                     tmp = FileHelpers::getConfigurationRelative(configuration, tmp);
00299                 }
00300                 conv += tmp;
00301             }
00302             (*i)->set(conv);
00303         }
00304     }
00305 }
00306 
00307 
00308 bool
00309 OptionsCont::isUsableFileList(const std::string& name) const {
00310     Option* o = getSecure(name);
00311     // check whether the option is set
00312     //  return false i not
00313     if (!o->isSet()) {
00314         return false;
00315     }
00316     // check whether the list of files is valid
00317     bool ok = true;
00318     std::vector<std::string> files = getStringVector(name);
00319     if (files.size()==0) {
00320         WRITE_ERROR("The file list for '" + name + "' is empty.");
00321         ok = false;
00322     }
00323     for (std::vector<std::string>::const_iterator fileIt=files.begin(); fileIt!=files.end(); ++fileIt) {
00324         if (!FileHelpers::exists(*fileIt)) {
00325             if (*fileIt!="") {
00326                 WRITE_ERROR("File '" + *fileIt + "' does not exist.");
00327                 ok = false;
00328             } else {
00329                 WRITE_WARNING("Empty file name given; ignoring.");
00330             }
00331         }
00332     }
00333     return ok;
00334 }
00335 
00336 
00337 bool
00338 OptionsCont::checkDependingSuboptions(const std::string& name, const std::string& prefix) const {
00339     Option* o = getSecure(name);
00340     if (o->isSet()) {
00341         return true;
00342     }
00343     bool ok = true;
00344     std::vector<std::string> seenSynonymes;
00345     for (KnownContType::const_iterator i=myValues.begin(); i!=myValues.end(); i++) {
00346         if (std::find(seenSynonymes.begin(), seenSynonymes.end(), (*i).first)!=seenSynonymes.end()) {
00347             continue;
00348         }
00349         if ((*i).second->isSet() && !(*i).second->isDefault() && (*i).first.find(prefix) == 0) {
00350             WRITE_ERROR("Option '" + (*i).first + "' needs option '" + name + "'.");
00351             std::vector<std::string> synonymes = getSynonymes((*i).first);
00352             std::copy(synonymes.begin(), synonymes.end(), std::back_inserter(seenSynonymes));
00353             ok = false;
00354         }
00355     }
00356     return ok;
00357 }
00358 
00359 
00360 void
00361 OptionsCont::reportDoubleSetting(const std::string& arg) const {
00362     std::vector<std::string> synonymes = getSynonymes(arg);
00363     std::ostringstream s;
00364     s << "A value for the option '" + arg + "' was already set.\n Possible synonymes: ";
00365     for (std::vector<std::string>::iterator i=synonymes.begin(); i!=synonymes.end();) {
00366         s << (*i);
00367         i++;
00368         if (i!=synonymes.end()) {
00369             s << ", ";
00370         }
00371     }
00372     WRITE_ERROR(s.str());
00373 }
00374 
00375 
00376 std::string
00377 OptionsCont::convertChar(char abbr) const {
00378     char buf[2];
00379     buf[0] = abbr;
00380     buf[1] = 0;
00381     std::string s(buf);
00382     return s;
00383 }
00384 
00385 
00386 bool
00387 OptionsCont::isBool(const std::string& name) const {
00388     Option* o = getSecure(name);
00389     return o->isBool();
00390 }
00391 
00392 
00393 void
00394 OptionsCont::resetWritable() {
00395     for (ItemAddressContType::iterator i=myAddresses.begin(); i!=myAddresses.end(); i++) {
00396         (*i)->resetWritable();
00397     }
00398 }
00399 
00400 
00401 bool
00402 OptionsCont::isWriteable(const std::string& name) {
00403     Option* o = getSecure(name);
00404     return o->isWriteable();
00405 }
00406 
00407 
00408 void
00409 OptionsCont::clear() {
00410     ItemAddressContType::iterator i;
00411     for (i=myAddresses.begin(); i!=myAddresses.end(); i++) {
00412         delete(*i);
00413     }
00414     myAddresses.clear();
00415     myValues.clear();
00416     mySubTopics.clear();
00417     mySubTopicEntries.clear();
00418 }
00419 
00420 
00421 void
00422 OptionsCont::addDescription(const std::string& name,
00423                             const std::string& subtopic,
00424                             const std::string& description) {
00425     Option* o = getSecure(name);
00426     assert(o!=0);
00427     assert(find(mySubTopics.begin(), mySubTopics.end(), subtopic)!=mySubTopics.end());
00428     o->setDescription(description);
00429     mySubTopicEntries[subtopic].push_back(name);
00430 }
00431 
00432 
00433 void
00434 OptionsCont::setApplicationName(const std::string& appName,
00435                                 const std::string& fullName) {
00436     myAppName = appName;
00437     myFullName = fullName;
00438 }
00439 
00440 
00441 void
00442 OptionsCont::setApplicationDescription(const std::string& appDesc) {
00443     myAppDescription = appDesc;
00444 }
00445 
00446 
00447 void
00448 OptionsCont::addCallExample(const std::string& example) {
00449     myCallExamples.push_back(example);
00450 }
00451 
00452 
00453 void
00454 OptionsCont::setAdditionalHelpMessage(const std::string& add) {
00455     myAdditionalMessage = add;
00456 }
00457 
00458 
00459 void
00460 OptionsCont::addCopyrightNotice(const std::string& copyrightLine) {
00461     myCopyrightNotices.push_back(copyrightLine);
00462 }
00463 
00464 
00465 void
00466 OptionsCont::clearCopyrightNotices() {
00467     myCopyrightNotices.clear();
00468 }
00469 
00470 
00471 void
00472 OptionsCont::addOptionSubTopic(const std::string& topic) {
00473     mySubTopics.push_back(topic);
00474     mySubTopicEntries[topic] = std::vector<std::string>();
00475 }
00476 
00477 
00478 void
00479 OptionsCont::splitLines(std::ostream& os, std::string what,
00480                         size_t offset, size_t nextOffset) {
00481     while (what.length()>0) {
00482         if (what.length()>79-offset) {
00483             size_t splitPos = what.rfind(';', 79-offset);
00484             if (splitPos==std::string::npos) {
00485                 splitPos = what.rfind(' ', 79-offset);
00486             } else {
00487                 splitPos++;
00488             }
00489             if (splitPos!=std::string::npos) {
00490                 os << what.substr(0, splitPos) << std::endl;
00491                 what = what.substr(splitPos);
00492                 for (size_t r=0; r<nextOffset+1; ++r) {
00493                     os << ' ';
00494                 }
00495             } else {
00496                 os << what;
00497                 what = "";
00498             }
00499             offset = nextOffset;
00500         } else {
00501             os << what;
00502             what = "";
00503         }
00504     }
00505     os << std::endl;
00506 }
00507 
00508 
00509 bool
00510 OptionsCont::processMetaOptions(bool missingOptions) throw(ProcessError) {
00511     if (missingOptions) {
00512         // no options are given
00513         std::cout << myFullName << std::endl;
00514         for (std::vector<std::string>::const_iterator it =
00515                     myCopyrightNotices.begin(); it != myCopyrightNotices.end(); ++it) {
00516             std::cout << " " << *it << std::endl;
00517         }
00518         std::cout << " License GPLv3+: GNU GPL Version 3 or later <http://gnu.org/licenses/gpl.html>\n";
00519         std::cout << " Use --help to get the list of options." << std::endl;
00520         return true;
00521     }
00522 
00523     // check whether the help shall be printed
00524     if (getBool("help")) {
00525         std::cout << myFullName << std::endl;
00526         for (std::vector<std::string>::const_iterator it =
00527                     myCopyrightNotices.begin(); it != myCopyrightNotices.end(); ++it) {
00528             std::cout << " " << *it << std::endl;
00529         }
00530         printHelp(std::cout);
00531         return true;
00532     }
00533     // check whether the help shall be printed
00534     if (getBool("version")) {
00535         std::cout << myFullName << std::endl;
00536         for (std::vector<std::string>::const_iterator it =
00537                     myCopyrightNotices.begin(); it != myCopyrightNotices.end(); ++it) {
00538             std::cout << " " << *it << std::endl;
00539         }
00540         std::cout << "\nThis program is free software; you can redistribute it and/or modify\n";
00541         std::cout << "it under the terms of the GNU General Public License as published by\n";
00542         std::cout << "the Free Software Foundation; either version 3 of the License, or\n";
00543         std::cout << "(at your option) any later version.\n\n";
00544         std::cout << "This program is distributed in the hope that it will be useful,\n";
00545         std::cout << "but WITHOUT ANY WARRANTY; without even the implied warranty of\n";
00546         std::cout << "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n";
00547         std::cout << "GNU General Public License for more details.\n\n";
00548         std::cout << "You should have received a copy of the GNU General Public License\n";
00549         std::cout << "along with this program. If not, see http://www.gnu.org/licenses/gpl.html" << std::endl;
00550         return true;
00551     }
00552     // check whether the settings shall be printed
00553     if (exists("print-options") && getBool("print-options")) {
00554         std::cout << (*this);
00555     }
00556     // check whether something has to be done with options
00557     // whether the current options shall be saved
00558     if (isSet("save-configuration", false)) { // sumo-gui does not register these
00559         if (getString("save-configuration") == "-" || getString("save-configuration") == "stdout") {
00560             writeConfiguration(std::cout, true, false, getBool("save-commented"));
00561             return true;
00562         }
00563         std::ofstream out(getString("save-configuration").c_str());
00564         if (!out.good()) {
00565             throw ProcessError("Could not save configuration to '" + getString("save-configuration") + "'");
00566         } else {
00567             writeConfiguration(out, true, false, getBool("save-commented"));
00568             if (getBool("verbose")) {
00569                 WRITE_MESSAGE("Written configuration to '" + getString("save-configuration") + "'");
00570             }
00571             return true;
00572         }
00573     }
00574     // whether the template shall be saved
00575     if (isSet("save-template", false)) { // sumo-gui does not register these
00576         if (getString("save-template") == "-" || getString("save-template") == "stdout") {
00577             writeConfiguration(std::cout, false, true, getBool("save-commented"));
00578             return true;
00579         }
00580         std::ofstream out(getString("save-template").c_str());
00581         if (!out.good()) {
00582             throw ProcessError("Could not save template to '" + getString("save-template") + "'");
00583         } else {
00584             writeConfiguration(out, false, true, getBool("save-commented"));
00585             if (getBool("verbose")) {
00586                 WRITE_MESSAGE("Written template to '" + getString("save-template") + "'");
00587             }
00588             return true;
00589         }
00590     }
00591     if (isSet("save-schema", false)) { // sumo-gui does not register these
00592         if (getString("save-schema") == "-" || getString("save-schema") == "stdout") {
00593             writeSchema(std::cout, getBool("save-commented"));
00594             return true;
00595         }
00596         std::ofstream out(getString("save-schema").c_str());
00597         if (!out.good()) {
00598             throw ProcessError("Could not save schema to '" + getString("save-schema") + "'");
00599         } else {
00600             writeSchema(out, getBool("save-commented"));
00601             if (getBool("verbose")) {
00602                 WRITE_MESSAGE("Written schema to '" + getString("save-schema") + "'");
00603             }
00604             return true;
00605         }
00606     }
00607     return false;
00608 }
00609 
00610 void
00611 OptionsCont::printHelp(std::ostream& os) {
00612     std::vector<std::string>::const_iterator i, j;
00613 //#define WIKI_OUTPUT 1
00614 #ifdef WIKI_OUTPUT
00615     for (i=mySubTopics.begin(); i!=mySubTopics.end(); ++i) {
00616         os << "===" << (*i) << "===\n";
00617         os << "{| cellspacing=\"0\" border=\"1\" width=\"90%\" align=\"center\"\n";
00618         os << "|-\n";
00619         os << "! style=\"background:#ddffdd;\" valign=\"top\" | Option\n";
00620         os << "! style=\"background:#ddffdd;\" valign=\"top\" | Default Value\n";
00621         os << "! style=\"background:#ddffdd;\" valign=\"top\" | Description\n";
00622         const std::vector<std::string> &entries = mySubTopicEntries[*i];
00623         for (j=entries.begin(); j!=entries.end(); ++j) {
00624             // start length computation
00625             size_t csize = (*j).length() + 2;
00626             Option* o = getSecure(*j);
00627             os << "|-\n";
00628             os << "| valign=\"top\" | ";
00629             // write abbreviation if given
00630             std::vector<std::string> synonymes = getSynonymes(*j);
00631             std::vector<std::string>::iterator a = find_if(synonymes.begin(), synonymes.end(), abbreviation_finder());
00632             std::string outputType = o->getTypeName();
00633             if (a!=synonymes.end()) {
00634                 os << "{{Option|-" << (*a) << " {{DT_" << outputType << "}}}}<br/>";
00635             }
00636             // write the name
00637             os << "{{Option|--" << *j << " {{DT_" << outputType << "}}}}\n";
00638             std::string defaultValue = o->isSet() ? o->getValueString() : "";
00639             os << "| valign=\"top\" | " << defaultValue << "\n";
00640             os << "| valign=\"top\" | " << o->getDescription() << "\n";
00641         }
00642         os << "|-\n";
00643         os << "|}\n\n";
00644     }
00645     return;
00646 #endif
00647     // print application description
00648     os << ' ' << std::endl;
00649     splitLines(os, myAppDescription, 0, 0);
00650     os << std::endl;
00651     // print usage BNF
00652     os << "Usage: " << myAppName << " [OPTION]*" << std::endl;
00653     os << ' ' << std::endl;
00654     // print usage examples
00655     if (myCallExamples.size()>1) {
00656         os << " Examples:" << std::endl;
00657     } else if (myCallExamples.size()!=0) {
00658         os << " Example:" << std::endl;
00659     }
00660     if (myCallExamples.size()!=0) {
00661         for (i=myCallExamples.begin(); i!=myCallExamples.end(); ++i) {
00662             os << "  " << myAppName << ' ' << (*i) << std::endl;
00663         }
00664     }
00665     os << ' ' << std::endl;
00666     // print additional text if any
00667     if (myAdditionalMessage.length()>0) {
00668         os << myAdditionalMessage << std::endl << ' ' << std::endl;
00669     }
00670     // print the options
00671     // check their sizes first
00672     //  we want to know how large the largest not-too-large-entry will be
00673     size_t tooLarge = 40;
00674     size_t maxSize = 0;
00675     for (i=mySubTopics.begin(); i!=mySubTopics.end(); ++i) {
00676         const std::vector<std::string> &entries = mySubTopicEntries[*i];
00677         for (j=entries.begin(); j!=entries.end(); ++j) {
00678             Option* o = getSecure(*j);
00679             // name, two leading spaces and "--"
00680             size_t csize = (*j).length() + 2 + 4;
00681             // abbreviation length ("-X, "->4chars) if any
00682             std::vector<std::string> synonymes = getSynonymes(*j);
00683             if (find_if(synonymes.begin(), synonymes.end(), abbreviation_finder())!=synonymes.end()) {
00684                 csize += 4;
00685             }
00686             // the type name
00687             if (!o->isBool()) {
00688                 csize += 1 + o->getTypeName().length();
00689             }
00690             // divider
00691             csize += 2;
00692             if (csize<tooLarge&&maxSize<csize) {
00693                 maxSize = csize;
00694             }
00695         }
00696     }
00697 
00698     for (i=mySubTopics.begin(); i!=mySubTopics.end(); ++i) {
00699         os << ' ' << *i << " Options:" << std::endl;
00700         const std::vector<std::string> &entries = mySubTopicEntries[*i];
00701         for (j=entries.begin(); j!=entries.end(); ++j) {
00702             // start length computation
00703             size_t csize = (*j).length() + 2;
00704             Option* o = getSecure(*j);
00705             os << "  ";
00706             // write abbreviation if given
00707             std::vector<std::string> synonymes = getSynonymes(*j);
00708             std::vector<std::string>::iterator a = find_if(synonymes.begin(), synonymes.end(), abbreviation_finder());
00709             if (a!=synonymes.end()) {
00710                 os << '-' << (*a) << ", ";
00711                 csize += 4;
00712             }
00713             // write leading '-'/"--"
00714             os << "--";
00715             csize += 2;
00716             // write the name
00717             os << *j;
00718             // write the type if not a bool option
00719             if (!o->isBool()) {
00720                 os << ' ' << o->getTypeName();
00721                 csize += 1 + o->getTypeName().length();
00722             }
00723             csize += 2;
00724             // write the description formatting it
00725             os << "  ";
00726             size_t r;
00727             for (r=maxSize; r>csize; --r) {
00728                 os << ' ';
00729             }
00730             std::string desc = o->getDescription();
00731             size_t offset = csize > tooLarge ? csize : maxSize;
00732             splitLines(os, desc, offset, maxSize);
00733         }
00734         os << std::endl;
00735     }
00736 }
00737 
00738 
00739 void
00740 OptionsCont::writeConfiguration(std::ostream& os, bool filled,
00741                                 bool complete, bool addComments) {
00742     // to the best of our knowledge files are written in latin-1 on windows and linux
00743     os << "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n\n";
00744     os << "<configuration xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.sf.net/xsd/" << myAppName << "Configuration.xsd\">" << std::endl << std::endl;
00745     for (std::vector<std::string>::const_iterator i=mySubTopics.begin(); i!=mySubTopics.end(); ++i) {
00746         std::string subtopic = *i;
00747         if (subtopic=="Configuration") {
00748             continue;
00749         }
00750         std::replace(subtopic.begin(), subtopic.end(), ' ', '_');
00751         std::transform(subtopic.begin(), subtopic.end(), subtopic.begin(), tolower);
00752         const std::vector<std::string> &entries = mySubTopicEntries[*i];
00753         bool hadOne = false;
00754         for (std::vector<std::string>::const_iterator j=entries.begin(); j!=entries.end(); ++j) {
00755             Option* o = getSecure(*j);
00756             bool write = complete || (filled&&!o->isDefault());
00757             if (!write) {
00758                 continue;
00759             }
00760             if (!hadOne) {
00761                 os << "    <" << subtopic << ">" << std::endl;
00762             }
00763             // add the comment if wished
00764             if (addComments) {
00765                 os << "        <!-- " << o->getDescription() << " -->" << std::endl;
00766             }
00767             // write the option and the value (if given)
00768             os << "        <" << *j << " value=\"";
00769             if (o->isSet()) {
00770                 os << o->getValueString();
00771             }
00772             if (complete) {
00773                 std::vector<std::string> synonymes = getSynonymes(*j);
00774                 if (!synonymes.empty()) {
00775                     os << "\" synonymes=\"";
00776                     for (std::vector<std::string>::const_iterator s=synonymes.begin(); s!=synonymes.end(); ++s) {
00777                         if (s != synonymes.begin()) {
00778                             os << " ";
00779                         }
00780                         os << (*s);
00781                     }
00782                 }
00783                 os << "\" type=\"" << o->getTypeName();
00784                 if (!addComments) {
00785                     os << "\" help=\"" << o->getDescription();
00786                 }
00787             }
00788             os << "\"/>" << std::endl;
00789             // append an endline if a comment was printed
00790             if (addComments) {
00791                 os << std::endl;
00792             }
00793             hadOne = true;
00794         }
00795         if (hadOne) {
00796             os << "    </" << subtopic << ">" << std::endl << std::endl;
00797         }
00798     }
00799     os << "</configuration>" << std::endl;
00800 }
00801 
00802 
00803 void
00804 OptionsCont::writeSchema(std::ostream& os, bool addComments) {
00805     // to the best of our knowledge files are written in latin-1 on windows and linux
00806     os << "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n\n";
00807     os << "<xsd:schema elementFormDefault=\"qualified\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n\n";
00808     os << "    <xsd:element name=\"configuration\" type=\"configurationType\"/>\n\n";
00809     os << "    <xsd:complexType name=\"configurationType\">\n";
00810     os << "        <xsd:sequence>\n";
00811     for (std::vector<std::string>::const_iterator i=mySubTopics.begin(); i!=mySubTopics.end(); ++i) {
00812         std::string subtopic = *i;
00813         if (subtopic=="Configuration") {
00814             continue;
00815         }
00816         std::replace(subtopic.begin(), subtopic.end(), ' ', '_');
00817         std::transform(subtopic.begin(), subtopic.end(), subtopic.begin(), tolower);
00818         os << "            <xsd:element name=\"" << subtopic << "\" type=\"" << subtopic << "Type\" minOccurs=\"0\" maxOccurs=\"1\"/>\n";
00819     }
00820     os << "        </xsd:sequence>\n";
00821     os << "    </xsd:complexType>\n\n";
00822     for (std::vector<std::string>::const_iterator i=mySubTopics.begin(); i!=mySubTopics.end(); ++i) {
00823         std::string subtopic = *i;
00824         if (subtopic=="Configuration") {
00825             continue;
00826         }
00827         std::replace(subtopic.begin(), subtopic.end(), ' ', '_');
00828         std::transform(subtopic.begin(), subtopic.end(), subtopic.begin(), tolower);
00829         os << "    <xsd:complexType name=\"" << subtopic << "Type\">\n";
00830         os << "        <xsd:sequence>\n";
00831         const std::vector<std::string> &entries = mySubTopicEntries[*i];
00832         for (std::vector<std::string>::const_iterator j=entries.begin(); j!=entries.end(); ++j) {
00833             os << "            <xsd:element name=\"" << *j << "\" type=\"" << *j << "Type\" minOccurs=\"0\" maxOccurs=\"1\"/>\n";
00834         }
00835         os << "        </xsd:sequence>\n";
00836         os << "    </xsd:complexType>\n\n";
00837         for (std::vector<std::string>::const_iterator j=entries.begin(); j!=entries.end(); ++j) {
00838             Option* o = getSecure(*j);
00839             std::string type = o->getTypeName();
00840             std::transform(type.begin(), type.end(), type.begin(), tolower);
00841             if (type == "bool") {
00842                 type = "boolean";
00843             } else {
00844                 if (type != "int" && type != "float") {
00845                     type = "string";
00846                 }
00847             }
00848             os << "    <xsd:complexType name=\"" << *j << "Type\">\n";
00849             if (addComments) {
00850                 os << "        <!-- " << o->getDescription() << " -->\n";
00851             }
00852             os << "        <xsd:attribute name=\"value\" type=\"xsd:" << type << "\" use=\"required\"/>\n";
00853             os << "        <xsd:attribute name=\"synonymes\" type=\"xsd:string\" use=\"optional\"/>\n";
00854             os << "        <xsd:attribute name=\"type\" type=\"xsd:string\" use=\"optional\"/>\n";
00855             os << "        <xsd:attribute name=\"help\" type=\"xsd:string\" use=\"optional\"/>\n";
00856             os << "    </xsd:complexType>\n\n";
00857         }
00858     }
00859     os << "</xsd:schema>\n";
00860 }
00861 
00862 
00863 void
00864 OptionsCont::writeXMLHeader(std::ostream& os, const std::string xmlParams) {
00865     time_t rawtime;
00866     char buffer [80];
00867 
00868     os << "<?xml version=\"1.0\"" << xmlParams << "?>\n\n";
00869     time(&rawtime);
00870     strftime(buffer, 80, "<!-- generated on %c by ", localtime(&rawtime));
00871     os << buffer << myFullName << "\n";
00872     writeConfiguration(os, true, false, false);
00873     os << "-->\n\n";
00874 }
00875 
00876 
00877 std::vector<std::string>
00878 OptionsCont::getStringVector(const std::string& name) const {
00879     Option* o = getSecure(name);
00880     std::string def = o->getString();
00881     if (def.find(';')!=std::string::npos&&!myHaveInformedAboutDeprecatedDivider) {
00882         WRITE_WARNING("Please note that using ';' as list separator is deprecated.\n From 1.0 onwards, only ',' will be accepted.");
00883         myHaveInformedAboutDeprecatedDivider = true;
00884     }
00885     StringTokenizer st(def, ";,", true);
00886     std::vector<std::string> ret = st.getVector();
00887     for (std::vector<std::string>::iterator i=ret.begin(); i!=ret.end(); ++i) {
00888         (*i) = StringUtils::prune(*i);
00889     }
00890     return ret;
00891 }
00892 
00893 
00894 bool
00895 OptionsCont::isInStringVector(const std::string& optionName,
00896                               const std::string& itemName) {
00897     if (isSet(optionName)) {
00898         std::vector<std::string> values = getStringVector(optionName);
00899         return find(values.begin(), values.end(), itemName)!=values.end();
00900     }
00901     return false;
00902 }
00903 
00904 
00905 /****************************************************************************/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines