Documentation improvements.
[command.git] / include / option.h
1 #ifndef __COMMAND_OPTION_H
2 #define __COMMAND_OPTION_H
3
4 #include <string>
5 #include <sstream>
6 #include <stdexcept>
7
8 #include "parameter.h"
9
10 namespace command {
11     /**
12      * Class responsible for handling commandline options.
13      * Options are named parameters of program.
14      *
15      * Example:
16      *  - ./myprog OptionName=OptionValue
17      *  - ./myprog -f=/some/file
18      *  - ./myprog --level=15
19      */
20     template<typename ParameterType>
21     class Option
22         : public Parameter, public Callable<ParameterType>  {
23     public:
24         typedef std::string OptionName;
25     protected:
26         /**
27          * Current Option name
28          */
29         const OptionName name;
30
31         /**
32          * Current Option value
33          */
34         ParameterType value;
35
36     public:
37         /**
38          * Default constructor.
39          *
40          * @param name Name of the current Option
41          * @param description Description of current Option
42          * @param function Function used to handle current Option.
43          */
44         Option(const std::string & name, const std::string & description, void (*function)(ParameterType))
45             : Parameter(description), Callable<ParameterType>(function), name(name) {
46         }
47
48         /**
49          *
50          */
51         virtual ~Option() { }
52
53         /**
54          * \inheritdoc
55          */
56         virtual void handle() {
57             this->call(value);
58         }
59
60         /**
61          * Method used for checking if Option understands given user value.
62          * If so current Option is flagged as used and no more checks against
63          * it will be done in future.
64          *
65          * Passed value should be in form of:
66          *      OptionName=OptionValue
67          *
68          * If no equal sign is after OptionName part,
69          * std::invalid_argument exception with appropriate message is thrown
70          *
71          * If conversion of OptionValue part to ParameterType failed,
72          * std::invalid_argument exception with appropriate message is thrown
73          *
74          * @param argv command line value against which test will be made.
75          *  User value should be in format: OptionName=OptionValue.
76          *
77          * @return If passed argv succesfully detected OptionName part as a
78          *  current option and its OptionValue part has been succesfully
79          *  converted to ParameterType, returns true and Option is set as used one.
80          *  Otherwise returns false and can be used to check against next value.
81          *
82          * @throw std::invalid_argument when OptionName part has no equal sign
83          *  after itself
84          * @throw std::invalid_argument when OptionValue part failed conversion
85          *  to ParameterType
86          */
87         virtual bool understand(const std::string & argv)
88             throw(std::invalid_argument) {
89
90             if ((!isUsed()) && (argv.find(name) == 0)) {
91                 std::size_t pos = argv.find("=");
92
93                 if (pos != name.size()) {
94                     throw std::invalid_argument("Option: " + name + " requires value but no one has been provided");
95                 }
96
97                 std::stringstream ss;
98                 ss << argv.substr(pos + 1);
99                 ss >> value;// memory leak? when uncommented and exception is
100                             // thrown, valgrind shows e.g.:
101                             //  possibly lost: 380 bytes in 7 blocks
102
103                 if (ss.fail()) {
104                     throw std::invalid_argument("Value for option: " + name + " failed conversion to the required type");
105                 }
106
107                 used = true;
108                 return true;
109             }
110             return false;
111         }
112     };
113
114     /**
115      * Template class responsible for handling commandline options.
116      * Options are non-required, named parameters of program.
117      * This template specialization allows Options to work like switches.
118      * It means that just named parameter is needed to invoke command. No value
119      * is used.
120      *
121      * Example:
122      *  ./myprog OptionName
123      *  ./myprog -h
124      *  ./myprog --help
125      */
126     template<>
127     class Option<void>
128         : public Parameter, public Callable<void>  {
129     public:
130         typedef std::string OptionName;
131     protected:
132         /**
133          * Current Option name
134          */
135         const OptionName name;
136     public:
137         /**
138          * Default constructor.
139          *
140          * @param name Name of the current Option
141          * @param description Description of current Option
142          * @param function Function used to handle current Option.
143          */
144         Option(const std::string & name, const std::string & description, void (*function)(void))
145             : Parameter(description), Callable<void>(function), name(name) {
146         }
147
148         /**
149          *
150          */
151         virtual void handle() {
152             this->call();
153         }
154
155         /**
156          * Method used for checking if Option understands given user value.
157          * If so, current Option is flagged as used and no more checks against
158          * it will be done in future.
159          *
160          * Passed value should be in form of:
161          *      OptionName
162          *
163          * @param argv command line value against which test will be made.
164          *  User value should be in format: OptionName.
165          *
166          * @return If passed argv succesfully detected OptionName returns true
167          *  and Option is set as used one. Otherwise returns false and can be
168          *  used to check against next value.
169          */
170         virtual bool understand(const std::string & argv) {
171             if ((!isUsed()) &&
172                 (argv == name)) {
173                 used = true;
174                 return true;
175             }
176             return false;
177         }
178     };
179 }
180
181 #endif /* __COMMAND_OPTION_H */