Version 3.0.2
[rtaudio-cdist.git] / tests / Windows / rtaudiotest / StdOpt.h
1 /************************************************************************/\r
2 /*! \class CommandLine\r
3     \brief Command-line opition parser.\r
4 \r
5     Copyright (c) 2005 Robin Davies.\r
6 \r
7     Permission is hereby granted, free of charge, to any person\r
8     obtaining a copy of this software and associated documentation files\r
9     (the "Software"), to deal in the Software without restriction,\r
10     including without limitation the rights to use, copy, modify, merge,\r
11     publish, distribute, sublicense, and/or sell copies of the Software,\r
12     and to permit persons to whom the Software is furnished to do so,\r
13     subject to the following conditions:\r
14 \r
15     The above copyright notice and this permission notice shall be\r
16     included in all copies or substantial portions of the Software.\r
17 \r
18     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
19     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
20     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
21     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
22     ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\r
23     CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
24     WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
25 */\r
26 /************************************************************************/\r
27 \r
28 #ifndef STDOPT_H\r
29 #define STDOPT_H\r
30 \r
31 #include <vector>\r
32 #include <string>\r
33 #include <sstream>\r
34 #include <exception>\r
35 \r
36 namespace stdopt\r
37 {\r
38 \r
39         class CommandLineException: public std::exception {\r
40         public: \r
41                 CommandLineException(const std::string &error)\r
42                 {\r
43                         s = error;\r
44                 }\r
45                 const char*what() { return s.c_str(); }\r
46         private:\r
47                 std::string s;\r
48         };\r
49 \r
50         class CommandLine\r
51         {\r
52         public:\r
53                 CommandLine();\r
54                 virtual ~CommandLine();\r
55 \r
56                 void ProcessCommandLine(int argc, char**argv);\r
57                 void ProcessCommandLine(const std::vector<std::string>& cmdline);\r
58 \r
59                 template <class TVAL> void AddOption(const char*name,TVAL*pResult, TVAL defaultValue)\r
60                 {\r
61                         this->optionHandlers.push_back(new COptionHandler<TVAL>(name,pResult));\r
62             *pResult = defaultValue;\r
63 \r
64                 }\r
65                 template <class TVAL> void AddOption(const char*name,TVAL*pResult)\r
66         {\r
67                         this->optionHandlers.push_back(new COptionHandler<TVAL>(name,pResult));\r
68         }\r
69                 const std::vector<std::string> &GetArguments() { return args; }\r
70     template <class T> void GetArgument(size_t arg, T*pVal)\r
71     {\r
72       if (arg >= args.size()) { \r
73         std::stringstream os;\r
74         os << "Argument " << (arg+1) << " not provided.";\r
75         throw CommandLineException(os.str());\r
76       }\r
77       std::stringstream is(args[arg]);\r
78       T value;\r
79       is >> value;\r
80       if (!is.fail() && is.eof())\r
81       {\r
82         *pVal = value;\r
83       } else {\r
84         std::stringstream os;\r
85         os << "Argument " << (arg+1) << " was not in the correct format.";\r
86         throw CommandLineException(os.str());\r
87       }\r
88     }\r
89     void GetArgument(size_t arg, std::string*pVal)\r
90     {\r
91       if (arg >= args.size()) { \r
92         std::stringstream os;\r
93         os << "Argument " << (arg+1) << " not provided.";\r
94         throw CommandLineException(os.str());\r
95       }\r
96       *pVal = args[arg];\r
97     }\r
98 \r
99 \r
100         private:\r
101 \r
102                 class COptionHandlerBase {\r
103                 public:\r
104                         COptionHandlerBase(const std::string & name) { this->name = name;}\r
105                         virtual ~COptionHandlerBase() { };\r
106                         const std::string &getName() const { return name; }\r
107                         virtual bool HasArgument()const  = 0; \r
108                         virtual void Process(const char* value) const = 0;\r
109                 private:\r
110                         std::string name;\r
111                 };\r
112                 template <class T> class COptionHandler: public COptionHandlerBase {\r
113                 public: \r
114                         COptionHandler(const std::string &name,T *result, T defaultValue = T())\r
115                                 : COptionHandlerBase(name)\r
116                         {\r
117                                 _pResult = result;\r
118                                 *_pResult = defaultValue;\r
119 \r
120                         }\r
121                         virtual bool HasArgument() const;\r
122 \r
123                         virtual void Process(const char *strValue) const {\r
124                                 std::stringstream is(strValue);\r
125                                 T value;\r
126         is >> value;\r
127                                 if (!is.fail() && is.eof())\r
128                                 {\r
129                                         *_pResult = value;\r
130                                 } else {\r
131                                         std::stringstream os;\r
132                                         os << "Invalid value provided for option '" << getName() << "'.";\r
133                                         throw CommandLineException(os.str().c_str());\r
134                                 }\r
135                         }\r
136 \r
137                 private:\r
138                         std::string strName;\r
139                         T*_pResult;\r
140                 };\r
141                 const CommandLine::COptionHandlerBase*GetOptionHandler(const std::string &name) const;\r
142 \r
143                 std::vector<std::string > args;\r
144                 std::vector<COptionHandlerBase*> optionHandlers;\r
145         };\r
146 \r
147         // Argument specializations for bool.\r
148         template <class T> bool CommandLine::COptionHandler<T>::HasArgument()const {\r
149                 return true; \r
150         };\r
151         inline bool CommandLine::COptionHandler<bool>::HasArgument() const {\r
152                 return false;\r
153         }\r
154         inline void CommandLine::COptionHandler<bool>::Process(const char*strValue) const {\r
155     if (strValue == NULL)\r
156     {\r
157       *_pResult = true;\r
158       return;\r
159     }\r
160                 switch (*strValue)\r
161                 {\r
162                 case '\0':\r
163                 case '+':\r
164                         *_pResult = true;\r
165                         break;\r
166                 case '-':\r
167                         *_pResult = false;\r
168                         break;\r
169                 default:\r
170                         throw CommandLineException("Please specify '+' or '-' for boolean options.");\r
171                 }\r
172         }\r
173         // specializations for std::string.\r
174         inline void  CommandLine::COptionHandler<std::string >::Process(const char*strValue)const  {\r
175                 *_pResult  = strValue;\r
176         }\r
177 \r
178         // specializations for std::vector<std::string>\r
179         inline void  CommandLine::COptionHandler<std::vector<std::string> >::Process(const char*strValue)const  {\r
180                 _pResult->push_back(strValue); \r
181         }\r
182 };\r
183 \r
184 \r
185 \r
186 #endif\r