Changeset 1664
- Timestamp:
- Aug 21, 2008, 9:23:11 PM (16 years ago)
- Location:
- code/branches/gui/src
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/gui/src/core/CommandLine.cc
r1663 r1664 31 31 namespace orxonox 32 32 { 33 /** 34 @brief 35 Destructor destroys all CommandLineArguments with it. 36 */ 33 37 CommandLine::~CommandLine() 34 38 { … … 39 43 } 40 44 } 41 45 46 /** 47 @brief 48 Returns a unique instance (Meyers Singleton). 49 */ 42 50 CommandLine& CommandLine::_getInstance() 43 51 { … … 46 54 } 47 55 48 void CommandLine::_parse(int argc, char** argv) 49 { 56 /** 57 @brief 58 Reads the command line parses the values of each argument. 59 It is then stored in the corresponding CommandLineArgument. 60 @note 61 The reason that you have to provide the string to be parsed as 62 space separted list is because of argc and argv. If you only have 63 a whole string, simply use getAllStrings() of SubString. 64 @param arguments 65 Vector of space separated strings. 66 */ 67 void CommandLine::_parse(const std::vector<std::string>& arguments) 68 { 69 // why this? See bFirstTimeParse_ declaration. 50 70 if (bFirstTimeParse_) 51 71 { … … 64 84 std::string name; 65 85 std::string shortcut; 66 std::string val ;67 for ( int i = 1; i < argc; ++i)68 { 69 if (arg v[i][0] == '-')86 std::string value; 87 for (unsigned int i = 0; i < arguments.size(); ++i) 88 { 89 if (arguments[i].size() != 0) 70 90 { 71 if (argv[i][1] <= 57 && argv[i][1] >= 48) 91 // sure not "" 92 if (arguments[i][0] == '-') 72 93 { 73 // negative number as a value 74 val += std::string(argv[i]) + " "; 94 // start with "-" 95 if (arguments[i].size() == 1) 96 { 97 // argument[i] is "-", probably a minus sign 98 value += "- "; 99 } 100 else if (arguments[i][1] <= 57 && arguments[i][1] >= 48) 101 { 102 // negative number as a value 103 value += arguments[i] + " "; 104 } 105 else 106 { 107 // can be shortcut or full name argument 108 109 // save old data first 110 if (name != "") 111 { 112 checkFullArgument(name, value); 113 name = ""; 114 assert(shortcut == ""); 115 } 116 else if (shortcut != "") 117 { 118 checkShortcut(shortcut, value); 119 shortcut = ""; 120 assert(name == ""); 121 } 122 123 if (arguments[i][1] == '-') 124 { 125 // full name argument with "--name" 126 name = arguments[i].substr(2); 127 } 128 else 129 { 130 // shortcut with "-s" 131 shortcut = arguments[i].substr(1); 132 } 133 134 // reset value string 135 value = ""; 136 } 75 137 } 76 138 else 77 139 { 78 // save old data first 79 if (name != "") 80 { 81 checkFullArgument(name, val); 82 name = ""; 83 assert(shortcut == ""); 84 } 85 else if (shortcut != "") 86 { 87 checkShortcut(shortcut, val); 88 shortcut = ""; 89 assert(name == ""); 90 } 91 92 if (argv[i][1] == '-') 93 { 94 // full name argument 95 name = argv[i] + 2; 96 } 97 else 98 { 99 // short cut 100 shortcut = argv[i] + 1; 101 } 102 val = ""; 140 // value string 141 142 if (name == "" && shortcut == "") 143 { 144 ThrowException(Argument, "Expected \"-\" or \"-\" in command line arguments.\n"); 145 } 146 147 // Concatenate strings as long as there's no new argument by "-" or "--" 148 value += arguments[i] + ' '; 103 149 } 104 150 } 105 else // value 106 { 107 if (name == "" && shortcut == "") 108 { 109 ThrowException(Argument, "Expected \"-\" or \"-\" in command line arguments.\n"); 110 } 111 112 val += argv[i]; 113 } 114 } 115 } 116 151 } 152 153 // parse last argument 154 if (name != "") 155 { 156 checkFullArgument(name, value); 157 assert(shortcut == ""); 158 } 159 else if (shortcut != "") 160 { 161 checkShortcut(shortcut, value); 162 assert(name == ""); 163 } 164 } 165 166 /** 167 @brief 168 Parses an argument based on its full name. 169 @param name 170 Full name of the argument 171 @param value 172 String containing the value 173 */ 117 174 void CommandLine::checkFullArgument(const std::string& name, const std::string& value) 118 175 { … … 124 181 } 125 182 183 /** 184 @brief 185 Parses an argument based on its shortcut. 186 @param shortcut 187 Shotcut to the argument 188 @param value 189 String containing the value 190 */ 126 191 void CommandLine::checkShortcut(const std::string& shortcut, const std::string& value) 127 192 { … … 132 197 it->second->parse(value); 133 198 } 199 200 std::string CommandLine::getUsageInformation() 201 { 202 CommandLine* inst = &_getInstance(); 203 std::string infoStr; 204 for (std::map<std::string, BaseCommandLineArgument*>::const_iterator it = inst->cmdLineArgs_.begin(); 205 it != inst->cmdLineArgs_.end(); ++it) 206 { 207 infoStr += "[--" + it->second->getName() + " " + it->second->getInformation() + "] "; 208 } 209 return infoStr; 210 } 211 134 212 } -
code/branches/gui/src/core/CommandLine.h
r1663 r1664 36 36 #include "Exception.h" 37 37 38 39 38 #define SetCommandLineArgument(name, defaultValue) \ 40 39 BaseCommandLineArgument& CmdArgumentDummyBoolVar##name \ 41 40 = orxonox::CommandLine::addCommandLineArgument(#name, defaultValue) 41 #define SetCommandLineSwitch(name) \ 42 BaseCommandLineArgument& CmdArgumentDummyBoolVar##name \ 43 = orxonox::CommandLine::addCommandLineArgument(#name, false) 44 42 45 43 46 namespace orxonox 44 47 { 48 /** 49 @brief 50 Template struct which creates a distinct type for every integer constant. 51 @note 52 This allows to select a different function depending on a boolean value 53 when creating a new CommandLineArgument. 54 From 'Modern C++ Design' (Alexandrescu 2001). 55 */ 56 template <int v> 57 struct Int2Type 58 { 59 enum { value = v }; 60 }; 61 62 /** 63 @brief 64 Base class for CommandLineArguments. 65 */ 45 66 class _CoreExport BaseCommandLineArgument 46 67 { … … 48 69 49 70 public: 71 //! Tells whether the value has been changed by the command line. 50 72 bool hasDefaultValue() const { return bHasDefaultValue_; } 73 //! Returns the name of the argument. 51 74 const std::string& getName() const { return name_; } 75 76 //! Returns the shortcut (example: "-p 22" for "--port 22") of the argument. 77 //! Evaluates to "" if none there is none. 52 78 const std::string& getShortcut() const { return shortcut_; } 79 //! Sets the shortcut for the argument 53 80 BaseCommandLineArgument& setShortcut(const std::string& shortcut) 54 81 { this->shortcut_ = shortcut; return *this; } 82 83 //! Returns the usage information 84 const std::string& getInformation() const { return this->usageInformation_; } 85 //! Sets the option information when displaying orxonox usage. 86 BaseCommandLineArgument& setInformation(const std::string& usage) 87 { this->usageInformation_ = usage; return *this; } 55 88 56 89 protected: … … 60 93 { } 61 94 95 //! Undefined copy constructor 62 96 BaseCommandLineArgument(const BaseCommandLineArgument& instance); 63 97 virtual ~BaseCommandLineArgument() { } 64 98 99 //! Parses the value string of a command line argument. 65 100 virtual void parse(const std::string& value) = 0; 66 101 102 //! Tells whether the value has been changed by the command line. 67 103 bool bHasDefaultValue_; 68 104 69 105 private: 70 std::string name_; 71 std::string shortcut_; 106 std::string name_; //!< Name of the argument 107 std::string shortcut_; //!< Shortcut of the argument. @see getShortcut(). 108 std::string usageInformation_; //!< Tells about the usage of this parameter 72 109 }; 73 110 74 111 112 /** 113 @brief 114 Container class for a command line argument of type T. 115 116 Whenever you want to have an option specified by a command line switch, 117 you need to first define it with SetCommandLineArgument(name, defaultValue). 118 It is then added to a map and possibly changed when the command line is being parsed. 119 If the option was not given, you can detect this by asking hasDefaultValue(). 120 121 There is a possibility to define a short cut so you can write "-p 20" instead of "--port 20". 122 Note the difference between "-" and "--"! 123 Also, there is no restriction to the number of strings you add after --name. 124 So "--startVector (2, 4, 5)" is perfectly legal. 125 126 Retrieving an argument is possible with the getCommandLineArgument function of the 127 CommandLine class. It is a Singleton, but the public interface is static. 128 */ 75 129 template <class T> 76 130 class CommandLineArgument : public BaseCommandLineArgument 77 131 { 132 // Only let CommandLine change the value. 78 133 friend class CommandLine; 79 134 80 135 public: 136 //! Returns the actual value of the argument. Can be equal to default value. 81 137 T getValue() const { return value_; } 138 //! Returns the given default value as type T. 82 139 T getDefaultValue() const { return defaultValue_; } 83 140 84 141 private: 142 //! Constructor initialises both value_ and defaultValue_ with defaultValue. 85 143 CommandLineArgument(const std::string& name, const T& defaultValue) 86 144 : BaseCommandLineArgument(name) … … 91 149 virtual void parse(const std::string& value); 92 150 93 T value_; 94 T defaultValue_; 151 T value_; //!< The actual value 152 T defaultValue_; //!< Default value. Should not be changed. 95 153 }; 96 154 155 /** 156 @brief 157 Parses a value string for a command line argument. 158 It simply uses convertValue(Output, Input) to do that. 159 */ 97 160 template <class T> 98 161 void CommandLineArgument<T>::parse(const std::string& value) … … 108 171 } 109 172 110 173 /** 174 @brief 175 Parses a value string for a command line argument. 176 It simply uses convertValue(Output, Input) to do that. 177 This is a template specialisation for bool type. That is necessary 178 so that you can have simple command line switches. 179 */ 180 template <> 181 inline void CommandLineArgument<bool>::parse(const std::string& value) 182 { 183 if (convertValue(&this->value_, value)) 184 { 185 this->bHasDefaultValue_ = false; 186 } 187 else if (value == "") 188 { 189 this->bHasDefaultValue_ = false; 190 this->value_ = true; 191 } 192 else 193 { 194 ThrowException(Argument, "Could not read command line argument '" + getName() + "'."); 195 } 196 } 197 198 199 /** 200 @brief 201 Global interface to command line options. 202 Allows to add and retrieve command line arguments. Also does the parsing. 203 @note 204 Internally it is a Singleton, but the public interface is static. 205 @see 206 CommandLineArgument 207 */ 111 208 class _CoreExport CommandLine 112 209 { 113 210 public: 114 211 115 static void parse(int argc, char** argv) { _getInstance()._parse(argc, argv); } 212 //! Parse redirection to internal member method. 213 static void parse(const std::vector<std::string>& arguments) { _getInstance()._parse(arguments); } 214 215 static std::string getUsageInformation(); 116 216 117 217 template <class T> 118 218 static const CommandLineArgument<T>* getCommandLineArgument(const std::string& name); 119 template <class T> 120 static BaseCommandLineArgument& addCommandLineArgument(const std::string& name, 121 const T& defaultValue); 219 //! Writes the argument value in the given parameter. 220 template <class T> 221 static void getCommandLineValue(const std::string& name, T* value) 222 { *value = getCommandLineArgument<T>(name)->getValue(); } 223 template <class T> 224 static BaseCommandLineArgument& addCommandLineArgument(const std::string& name, T defaultValue); 122 225 123 226 private: 227 //! Constructor initialises bFirstTimeParse_ with true. 124 228 CommandLine() : bFirstTimeParse_(true) { } 229 //! Undefined copy constructor 125 230 CommandLine(const CommandLine& instance); 126 231 ~CommandLine(); … … 128 233 static CommandLine& _getInstance(); 129 234 130 void _parse( int argc, char** argv);235 void _parse(const std::vector<std::string>& arguments); 131 236 void checkFullArgument(const std::string& name, const std::string& value); 132 237 void checkShortcut(const std::string& shortcut, const std::string& value); 133 238 239 template <class T> 240 BaseCommandLineArgument* createArg(const std::string& name, T defaultValue, Int2Type<0> isString); 241 template <class T> 242 BaseCommandLineArgument* createArg(const std::string& name, T defaultValue, Int2Type<1> isString); 243 244 /** 245 Tells whether we parse the first expression. The CommmandLineArguments are added before main(). 246 So when we call parse() the first time, we need to create a map with all shortcuts since these 247 get added after addCommandLineArgument(). 248 */ 134 249 bool bFirstTimeParse_; 135 250 251 //! Holds all pointers to the arguments and serves as a search map by name. 136 252 std::map<std::string, BaseCommandLineArgument*> cmdLineArgs_; 253 //! Search map by chortcut for the arguments. 137 254 std::map<std::string, BaseCommandLineArgument*> cmdLineArgsShortcut_; 138 255 }; 139 256 140 257 258 /** 259 @brief 260 Retrieves a CommandLineArgument. 261 The method throws an exception if 'name' was not found or the value could not be converted. 262 @note 263 You shold of course not call this method before the command line has been parsed. 264 */ 141 265 template <class T> 142 266 const CommandLineArgument<T>* CommandLine::getCommandLineArgument(const std::string& name) … … 162 286 } 163 287 164 template <class T> 165 BaseCommandLineArgument& CommandLine::addCommandLineArgument(const std::string& name, 166 const T& defaultValue) 288 /** 289 @brief 290 Adds a new CommandLineArgument to the internal map. 291 Note that only such arguments are actually valid. 292 @param name 293 Name of the argument. Shortcut can be added later. 294 @param defaultValue 295 Default value that is used when argument was not given. 296 @note 297 In order to store char* strings as std::string too, there's 298 little bit of template programming involved: 299 StaticConversions::exists determines whether T converts to std::string. 300 Int2Type<int> is then used to call the right function. One returns 301 a CommandLineArgument<T> and the other CommandLineArgument<std::string>. 302 */ 303 template <class T> 304 BaseCommandLineArgument& CommandLine::addCommandLineArgument(const std::string& name, T defaultValue) 167 305 { 168 306 std::map<std::string, BaseCommandLineArgument*>::const_iterator it = _getInstance().cmdLineArgs_.find(name); … … 170 308 "Cannot add a command line argument with name '" + name + "' twice."); 171 309 172 return *(_getInstance().cmdLineArgs_[name] = new CommandLineArgument<T>(name, defaultValue)); 310 return *(_getInstance().cmdLineArgs_[name] = 311 _getInstance().createArg(name, defaultValue, Int2Type<StaticConversion<T, std::string>::exists>())); 312 } 313 314 /** 315 Returns a new CommandLineArgument<T>. 316 */ 317 template <class T> 318 BaseCommandLineArgument* CommandLine::createArg(const std::string& name, T defaultValue, Int2Type<0> isPrime) 319 { 320 return new CommandLineArgument<T>(name, defaultValue); 321 } 322 323 /** 324 Returns a new CommandLineArgument<std::string>. 325 */ 326 template <class T> 327 BaseCommandLineArgument* CommandLine::createArg(const std::string& name, T defaultValue, Int2Type<1> isPrime) 328 { 329 return new CommandLineArgument<std::string>(name, defaultValue); 173 330 } 174 331 } -
code/branches/gui/src/core/Exception.cc
r1638 r1664 52 52 { } 53 53 54 std::stringException::getFullDescription() const54 const std::string& Exception::getFullDescription() const 55 55 { 56 std::ostringstream fullDesc; 56 if (fullDescription_ == "") 57 { 58 std::ostringstream fullDesc; 57 59 58 fullDesc << this->getTypeName() << "_EXCEPTION";60 fullDesc << this->getTypeName() << "_EXCEPTION"; 59 61 60 if (this->fileName_ != "") 61 { 62 fullDesc << " in " << this->fileName_; 63 if (this->lineNumber_) 64 fullDesc << "(" << this->lineNumber_ << ")"; 62 if (this->fileName_ != "") 63 { 64 fullDesc << " in " << this->fileName_; 65 if (this->lineNumber_) 66 fullDesc << "(" << this->lineNumber_ << ")"; 67 } 68 69 if (this->functionName_ != "") 70 fullDesc << " in function '" << this->functionName_ << "'"; 71 72 fullDesc << ": "; 73 if (this->description_ != "") 74 fullDesc << this->description_; 75 else 76 fullDesc << "No description available."; 77 78 this->fullDescription_ = std::string(fullDesc.str()); 65 79 } 66 80 67 if (this->functionName_ != "") 68 fullDesc << " in function '" << this->functionName_ << "'"; 69 70 fullDesc << ": "; 71 if (this->description_ != "") 72 fullDesc << this->description_; 73 else 74 fullDesc << "No description available."; 75 76 return fullDesc.str(); 81 return fullDescription_; 77 82 } 78 83 -
code/branches/gui/src/core/Exception.h
r1663 r1664 73 73 virtual ~Exception() throw() { } 74 74 75 virtual std::stringgetFullDescription() const;75 virtual const std::string& getFullDescription() const; 76 76 virtual ExceptionType getType() const = 0; 77 77 virtual std::string getTypeName() const = 0; … … 88 88 std::string functionName_; 89 89 std::string fileName_; 90 // mutable because of "what()" is a const method 91 mutable std::string fullDescription_; 90 92 }; 91 93 -
code/branches/gui/src/orxonox/Main.cc
r1663 r1664 41 41 #include "core/SignalHandler.h" 42 42 #include "core/Debug.h" 43 #include "core/CommandLine.h"44 //#include "Orxonox.h"45 43 46 44 #include "gamestates/GSRoot.h" … … 85 83 int main(int argc, char** argv) 86 84 { 87 try88 {89 orxonox::CommandLine::parse(argc, argv);90 }91 catch (orxonox::ArgumentException& ex)92 {93 COUT(1) << ex.what() << std::endl;94 COUT(0) << "Usage:" << std::endl << "orxonox [--mode client|server|dedicated|standalone] "95 << "[--data PATH] [--ip IP] [--port PORT]" << std::endl;96 }97 98 99 85 // create a signal handler (only works for linux) 100 86 SignalHandler::getInstance()->doCatch(argv[0], "orxonox.log"); 101 102 87 103 88 … … 144 129 graphics.addChild(&gui); 145 130 146 root.requestState("gui"); 131 root.feedCommandLine(argc, argv); 132 root.requestState("root"); 147 133 root.tick(0.0f); 148 134 root.requestState(""); 149 150 151 //Orxonox orxonoxInstance;152 153 try154 {155 #if ORXONOX_PLATFORM == ORXONOX_PLATFORM_APPLE156 orxonoxInstance.start(macBundlePath());157 #else158 //orxonoxInstance.start();159 #endif160 }161 catch (std::exception& ex)162 {163 COUT(1) << ex.what() << std::endl;164 COUT(1) << "Abort." << std::endl;165 }166 135 167 136 return 0; -
code/branches/gui/src/orxonox/gamestates/GSLevel.cc
r1663 r1664 46 46 namespace orxonox 47 47 { 48 SetCommandLineArgument(port, 55556).setShortcut("p") ;49 SetCommandLineArgument(ip, std::string("127.0.0.0"));48 SetCommandLineArgument(port, 55556).setShortcut("p").setInformation("PORT"); 49 SetCommandLineArgument(ip, "127.0.0.0").setInformation("#.#.#.#"); 50 50 51 51 GSLevel::GSLevel() -
code/branches/gui/src/orxonox/gamestates/GSRoot.cc
r1663 r1664 30 30 #include "GSRoot.h" 31 31 32 #include "util/SubString.h" 32 33 #include "core/Factory.h" 33 34 #include "core/ConfigFileManager.h" 34 35 #include "core/ConfigValueIncludes.h" 35 36 #include "core/ConsoleCommand.h" 37 #include "core/CommandLine.h" 36 38 #include "core/Debug.h" 37 39 #include "core/Exception.h" … … 44 46 namespace orxonox 45 47 { 46 SetCommandLineArgument(dataPath, std::string("./"));48 SetCommandLineArgument(dataPath, "").setInformation("PATH"); 47 49 48 50 GSRoot::GSRoot() … … 55 57 GSRoot::~GSRoot() 56 58 { 59 } 60 61 //SetCommandLineArgument(asdf1, "haha").setShortcut("a").setUsageInformation("1|2|3"); 62 //SetCommandLineArgument(asdf2, 3).setShortcut("b"); 63 //SetCommandLineArgument(asdf3, Vector2()).setShortcut("c"); 64 //SetCommandLineArgument(adsf4, 1.4f).setShortcut("d"); 65 //SetCommandLineSwitch(showGraphics).setShortcut("g"); 66 67 void GSRoot::feedCommandLine(int argc, char** argv) 68 { 69 std::vector<std::string> args; 70 for (int i = 1; i < argc; ++i) 71 args.push_back(argv[i]); 72 73 //std::string line = "-a --asdf3 (3,3) -d -5 -b - 5.4"; 74 //SubString tokens(line, " ", " ", false, 92, false, 34, true, 40, 41, false, 0); 75 76 try 77 { 78 orxonox::CommandLine::parse(args); 79 //CommandLine::parse(tokens.getAllStrings()); 80 } 81 catch (orxonox::ArgumentException& ex) 82 { 83 COUT(1) << ex.what() << std::endl; 84 COUT(0) << "Usage:" << std::endl << "orxonox " << CommandLine::getUsageInformation() << std::endl; 85 } 57 86 } 58 87 … … 71 100 this->settings_ = new Settings(); 72 101 73 const CommandLineArgument<std::string>* dataPath = CommandLine::getCommandLineArgument<std::string>("dataPath"); 74 if (!dataPath->hasDefaultValue()) 102 std::string dataPath; 103 CommandLine::getCommandLineValue("dataPath", &dataPath); 104 if (dataPath != "") 75 105 { 76 if (*dataPath ->getValue().end() != '/' && *dataPath->getValue().end() != '\\')77 Settings::tsetDataPath(dataPath ->getValue()+ "/");106 if (*dataPath.end() != '/' && *dataPath.end() != '\\') 107 Settings::tsetDataPath(dataPath + "/"); 78 108 else 79 Settings::tsetDataPath(dataPath ->getValue());109 Settings::tsetDataPath(dataPath); 80 110 } 81 111 … … 91 121 functor->setObject(this); 92 122 CommandExecutor::addConsoleCommandShortcut(createConsoleCommand(functor, "loadGame")); 123 124 requestState("gui"); 93 125 } 94 126 -
code/branches/gui/src/orxonox/gamestates/GSRoot.h
r1663 r1664 41 41 ~GSRoot(); 42 42 43 void feedCommandLine(int argc, char** argv); 43 44 bool tick(float dt); 44 45 void loadGame(const std::string& name); -
code/branches/gui/src/util/Convert.h
r1625 r1664 690 690 }; 691 691 692 693 /////////////////////////// 694 // Static type detection // 695 /////////////////////////// 696 697 /** 698 Template class that determines whether type T converts implicitly to type U. 699 @note 700 This allows to detect type conversion at compile time. 701 From 'Modern C++ Design' (Alexandrescu 2001). 702 */ 703 template <class T, class U> 704 class StaticConversion 705 { 706 class Small { char dummy[1]; }; 707 class Big { char dummy[1024]; }; 708 static Small Test(U); 709 static Big Test(...); 710 static T MakeT(); 711 public: 712 enum { exists = sizeof(Test(MakeT())) == sizeof(Small) }; 713 }; 714 692 715 #if ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC 693 716 #pragma warning(pop) -
code/branches/gui/src/util/SubString.h
r1505 r1664 131 131 /** @brief Returns the i'th string from the subset of Strings @param i the i'th String */ 132 132 inline const std::string& getString(unsigned int i) const { return (*this)[i]; }; 133 /** @brief Returns all Strings as std::vector */ 134 inline const std::vector<std::string>& getAllStrings() const { return this->strings; } 133 135 /** @brief Returns true if the token is in safemode. @param i the i'th token */ 134 136 inline bool isInSafemode(unsigned int i) const { return this->bInSafemode[i]; }
Note: See TracChangeset
for help on using the changeset viewer.