Add Grouped behaviour.
[command.git] / include / multiValue.h
1 #ifndef __COMMAND_MULTIVALUE_H
2 #define __COMMAND_MULTIVALUE_H
3
4 #include <iostream>
5 #include <vector>
6
7 #include "parameter.h"
8
9 namespace command {
10     /**
11      * Multiple Value Parameter decorator. Allows Parameters to understand
12      * many values.
13      *
14      * Example:
15      *  - separator: ","
16      *  - multiValue: "0,1,2,3,4,5,6,7,8,9"
17      *
18      * Example usage:
19      *  - ./myprog ARGUMENT,ARGUMENT,ARGUMENT,ARGUMENT
20      *  - ./myprog OPTION_NAME=VALUE,VALUE,VALUE,VALUE
21      */
22     class MultiValue : public Parameter {
23     protected:
24         /**
25          * Parameter which will be treated as containing multiple values
26          */
27         Parameter * parameter;
28
29         std::vector<std::string> values;
30
31         std::string separator;
32
33     public:
34         /**
35          * Default constructor.
36          *
37          * @param parameter Parameter which will be treated as containing multiple values
38          */
39         MultiValue(std::string separator, Parameter * parameter)
40             : Parameter(parameter->describe()), parameter(parameter),
41                 separator(separator) {
42         }
43
44         /**
45          * Default destructor. Releases allocated memory
46          */
47         virtual ~MultiValue() {
48             delete parameter;
49         }
50
51         /**
52          * Wrapper method around passed Parameter::handle().
53          *
54          * \inheritdoc
55          */
56         virtual void handle() {
57             for (std::string value : values) {
58                 parameter->understand(value);
59                 parameter->handle();
60             }
61         }
62
63         /**
64          * Wrapper method around passed Parameter::understand()
65          *
66          * @param argv command line value against which test will be made
67          *
68          * \inheritdoc
69          */
70         virtual bool understand(const std::string & value) {
71             size_t start = 0;
72             size_t pos = 0;
73             bool _understand = true;
74             std::string prefix = "";
75
76             start = parameter->valuePosition(value);
77
78             if (start > value.size()) {
79                 return false;
80             }
81
82             if (start > 0) {
83                 prefix = value.substr(0, ++start);// always count: "="
84             }
85
86             do {
87                 pos = value.find(separator, start);
88                 values.push_back(prefix + value.substr(start, pos-start));
89                 _understand &= parameter->understand(values.back());
90                 start = pos + 1;
91
92                 if (!_understand) {
93                     values.clear();
94                     break;
95                 }
96             } while ((pos != std::string::npos) && (start < value.size()));
97             return _understand;
98         }
99
100         /**
101          * Wrapper method around passed Parameter::isRequired().
102          * Indicates if current Parameter is required.
103          *
104          * @return true if Parameter is required, false otherwise
105          */
106         virtual bool isRequired() {
107             return parameter->isRequired();
108         };
109
110         /**
111          * Wrapper method around passed Parameter::isUsed().
112          *
113          * \inheritdoc
114          */
115         virtual bool isUsed() {
116             return parameter->isUsed();
117         };
118
119         /**
120          * Wrapper method around passed Parameter::valuePosition().
121          *
122          * \inheritdoc
123          */
124         virtual unsigned int valuePosition(const std::string & value) {
125             return parameter->valuePosition(value);
126         }
127     };
128 }
129
130 #endif /* __COMMAND_MULTIVALUE_H */