GCC Code Coverage Report


Directory: ./
File: src/Option.cpp
Date: 2024-07-27 10:53:27
Exec Total Coverage
Lines: 163 191 85.3%
Branches: 117 202 57.9%

Line Branch Exec Source
1 /***************************************
2 Auteur : Pierre Aubert
3 Mail : pierre.aubert@lapp.in2p3.fr
4 Licence : CeCILL-C
5 ****************************************/
6
7 #include "string_utils.h"
8 #include "Option.h"
9
10 ///Default constructor of Option
11 /** @param longName : long name of the option
12 * @param shortName : long name of the option
13 * @param docString : documentation string of the Option
14 */
15 35 Option::Option(const std::string & longName, const std::string & shortName, const std::string & docString)
16
4/4
✓ Branch 2 taken 35 times.
✓ Branch 6 taken 35 times.
✓ Branch 9 taken 35 times.
✓ Branch 14 taken 35 times.
35 :p_longName(longName), p_shortName(shortName), p_value(""), p_isRequired(false), p_docString(docString)
17 {
18
1/1
✓ Branch 1 taken 35 times.
35 initialisationOption();
19 35 }
20
21 ///Constructor of Option
22 /** @param longName : long name of the option
23 * @param shortName : long name of the option
24 * @param value : value of the Option
25 * @param docString : documentation string of the Option
26 */
27 Option::Option(const std::string & longName, const std::string & shortName, const OptionValue & value, const std::string & docString)
28 :p_longName(longName), p_shortName(shortName), p_value(value), p_isRequired(false), p_docString(docString)
29 {
30 initialisationOption();
31 }
32
33 ///Constructor of Option
34 /** @param longName : long name of the option
35 * @param shortName : long name of the option
36 * @param value : value of the Option
37 * @param isRequired : true if the option is required, false if it is optionnal
38 * @param docString : documentation string of the Option
39 */
40 167 Option::Option(const std::string & longName, const std::string & shortName, const OptionValue & value, bool isRequired, const std::string & docString)
41
3/3
✓ Branch 2 taken 167 times.
✓ Branch 5 taken 167 times.
✓ Branch 8 taken 167 times.
167 :p_longName(longName), p_shortName(shortName), p_value(value), p_isRequired(isRequired), p_docString(docString)
42 {
43
1/1
✓ Branch 1 taken 167 times.
167 initialisationOption();
44 167 }
45
46 ///Constructor of Option
47 /** @param longName : long name of the option
48 * @param shortName : long name of the option
49 * @param isRequired : true if the option is required, false if it is optionnal
50 * @param docString : documentation string of the Option
51 */
52 2 Option::Option(const std::string & longName, const std::string & shortName, bool isRequired, const std::string & docString)
53
3/3
✓ Branch 2 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 8 taken 2 times.
2 :p_longName(longName), p_shortName(shortName), p_isRequired(isRequired), p_docString(docString)
54 {
55
1/1
✓ Branch 1 taken 2 times.
2 initialisationOption();
56 2 }
57
58 ///Copy constructor of Option
59 /** @param other : class to copy
60 */
61
1/1
✓ Branch 3 taken 387 times.
387 Option::Option(const Option & other){
62
1/1
✓ Branch 1 taken 387 times.
387 copyOption(other);
63 387 }
64
65 ///Destructeur of Option
66 986 Option::~Option(){
67
68 }
69
70 ///Definition of equal operator of Option
71 /** @param other : class to copy
72 * @return copied class
73 */
74 34 Option & Option::operator = (const Option & other){
75 34 copyOption(other);
76 34 return *this;
77 }
78
79 ///Parse the current option with the given parser
80 /** @param[out] parser : parser of the given arguments to the program
81 * @return true on success, false otherwise
82 */
83 63 bool Option::parseOption(ArgParser & parser){
84
4/4
✓ Branch 2 taken 63 times.
✓ Branch 5 taken 61 times.
✓ Branch 9 taken 20 times.
✓ Branch 10 taken 41 times.
67 if(parsePartOption(parser, "--", p_longName)){return true;}
85
4/4
✓ Branch 2 taken 41 times.
✓ Branch 5 taken 41 times.
✓ Branch 9 taken 19 times.
✓ Branch 10 taken 22 times.
41 else if(parsePartOption(parser, "-", p_shortName)){return true;}
86 22 return false;
87 }
88
89 ///Print a vector of value
90 /** @param vecValue : vector of value to be ploted
91 */
92 9 void printVecString(const VecValue & vecValue){
93
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 if(vecValue.size() == 0lu){return;}
94 9 VecValue::const_iterator it(vecValue.begin());
95
1/1
✓ Branch 2 taken 9 times.
9 std::cout << *it;
96 9 ++it;
97
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
9 while(it != vecValue.end()){
98 std::cout << ", " << *it;
99 ++it;
100 }
101 }
102
103 ///Print an option
104 /** @param indentation : indentation to print the option
105 */
106 38 void Option::print(const std::string & indentation) const{
107 38 OptionType::OptionType type(p_value.getType());
108 38 std::cout << indentation;
109
1/2
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
38 if(p_longName != ""){
110 38 std::cout << "--" << p_longName;
111
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 1 times.
38 if(type != OptionType::NONE){
112
1/1
✓ Branch 3 taken 37 times.
37 std::cout << "=" << convertOptionTypeToString(type);
113 }
114 }
115
1/2
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
38 if(p_shortName != ""){
116
1/2
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
38 if(p_longName != ""){std::cout << " , ";}
117 38 std::cout << "-" << p_shortName;
118
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 1 times.
38 if(type != OptionType::NONE){
119
1/1
✓ Branch 3 taken 37 times.
37 std::cout << " " << convertOptionTypeToString(type);
120 }
121 }
122
1/2
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
38 if(p_docString != ""){
123 38 std::cout << " : " << p_docString;
124 }
125 38 std::cout << std::endl;
126 38 const VecValue & vecDefaultValue = p_value.getDefaultValue();
127
2/2
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 29 times.
38 if(vecDefaultValue.size()){
128 9 std::cout << indentation << "\tDefault value : '";
129 9 printVecString(vecDefaultValue);
130 9 std::cout << "'" << std::endl;
131 }
132 38 const VecValue & vecPossibleValue = p_value.getPossibleValue();
133
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
38 if(vecPossibleValue.size()){
134 std::cout << indentation << "\tPossible values : ";
135 printVecString(vecPossibleValue);
136 std::cout << std::endl;
137 }
138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if(p_isRequired){std::cout << indentation << "\tThis argument has to be set" << std::endl;}
139 38 else{std::cout << indentation << "\tThis argument is optional" << std::endl;}
140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if(p_isAllowEmpty){std::cout << indentation << "\tThis argument can have an empty value" << std::endl;}
141 38 else{std::cout << indentation << "\tThis argument cannot have an empty value" << std::endl;}
142 38 }
143
144 ///Set the long name of the option
145 /** @param longName : long name of the option
146 */
147 1 void Option::setLongName(const std::string & longName){p_longName = longName;}
148
149 ///Set the short name of the option
150 /** @param shortName : short name of the option
151 */
152 1 void Option::setShortName(const std::string & shortName){p_shortName = shortName;}
153
154 ///Set the value of the option
155 /** @param value : value name of the option
156 */
157 1 void Option::setValue(const OptionValue & value){p_value = value;}
158
159 ///Set if the option is required
160 /** @param isRequired : true if the Option is required, false if it is optionnal
161 */
162 1 void Option::setIsRequired(bool isRequired){p_isRequired = isRequired;}
163
164 ///Set the documentation string of the Option
165 /** @param docString : documentation string of the Option
166 */
167 1 void Option::setDocString(const std::string & docString){p_docString = docString;}
168
169 ///Say if the Option has been parsed or not
170 /** @param isParsed : true if the Option has been parsed, false if not
171 */
172 1 void Option::setIsParsed(bool isParsed){p_isParsed = isParsed;}
173
174 ///Say if the option can be empty or not
175 /** @param isAllowEmpty : true if the option can be empty, false otherwise
176 */
177 124 void Option::setIsAllowEmpty(bool isAllowEmpty){p_isAllowEmpty = isAllowEmpty;}
178
179 ///Get the long name of the Option
180 /** @return long name of the Option
181 */
182 159 const std::string & Option::getLongName() const{return p_longName;}
183
184 ///Get the long name of the Option
185 /** @return long name of the Option
186 */
187 1 std::string & Option::getLongName(){return p_longName;}
188
189 ///Get the short name of the Option
190 /** @return short name of the Option
191 */
192 81 const std::string & Option::getShortName() const{return p_shortName;}
193
194 ///Get the short name of the Option
195 /** @return short name of the Option
196 */
197 1 std::string & Option::getShortName(){return p_shortName;}
198
199 ///Get the value of the Option
200 /** @return value of the Option
201 */
202 3 const OptionValue & Option::getValue() const{return p_value;}
203
204 ///Get the value of the Option
205 /** @return value of the Option
206 */
207 35 OptionValue & Option::getValue(){return p_value;}
208
209 ///Get if the option is required
210 /** @return true if the Option is required, false if it is optionnal
211 */
212 3 bool Option::isRequired() const{return p_isRequired;}
213
214 ///Get if the option is required
215 /** @return true if the Option is required, false if it is optionnal
216 */
217 9 bool & Option::isRequired(){return p_isRequired;}
218
219 ///Get if the option value can be empty
220 /** @return true if the option value can be empty, false otherwise
221 */
222 3 bool Option::isAllowEmpty() const{return p_isAllowEmpty;}
223
224 ///Get if the option value can be empty
225 /** @return true if the option value can be empty, false otherwise
226 */
227 1 bool & Option::isAllowEmpty(){return p_isAllowEmpty;}
228
229 ///Get the documentation string of the Option
230 /** @return documentation string of the Option
231 */
232 3 const std::string & Option::getDocString() const{return p_docString;}
233
234 ///Get the documentation string of the Option
235 /** @return documentation string of the Option
236 */
237 1 std::string & Option::getDocString(){return p_docString;}
238
239 ///Say if the Option has been parsed or not
240 /** @return true if the Option has been parsed, false if not
241 */
242 5 bool Option::isParsed() const{return p_isParsed;}
243
244 ///Say if the Option has been parsed or not
245 /** @return true if the Option has been parsed, false if not
246 */
247 68 bool & Option::isParsed(){return p_isParsed;}
248
249 ///Check the argument of the parser
250 /** @return true if the arguments is required and is set, false otherwise
251 */
252 50 bool Option::checkArgument() const{
253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if(p_isRequired){
254 if(!p_isParsed){
255 OptionType::OptionType type(p_value.getType());
256 std::cerr << termRed() << "Missing arguement ";
257 if(p_longName != ""){
258 std::cerr << "--" << p_longName;
259 if(type != OptionType::NONE){
260 std::cout << "=" << convertOptionTypeToString(type);
261 }
262 }
263 if(p_shortName != ""){
264 if(p_longName != ""){std::cerr << " , ";}
265 std::cerr << "-" << p_shortName;
266 if(type != OptionType::NONE){
267 std::cout << " " << convertOptionTypeToString(type);
268 }
269 }
270 std::cerr << termDefault() << std::endl;
271 }
272 return p_isParsed;
273 50 }else{return true;}
274 }
275
276 ///Get the possible options for the bash completion
277 /** @param[out] possibleOption : possible options for the bash completion
278 * @param cursorOption : option of the cursor which is currently completed
279 */
280 27 void Option::getPossibleOption(std::string & possibleOption, const std::string & cursorOption) const{
281
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 23 times.
27 if(p_isParsed){return;}
282
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
23 if(p_longName != ""){
283
1/1
✓ Branch 1 taken 23 times.
23 std::string longOption("--" + p_longName);
284
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 18 times.
23 if(cursorOption == ""){
285
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
5 possibleOption += longOption + " ";
286 }else{
287
3/3
✓ Branch 1 taken 18 times.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 2 times.
18 if(isSameBegining(longOption, cursorOption)){
288
2/2
✓ Branch 1 taken 16 times.
✓ Branch 4 taken 16 times.
16 possibleOption += longOption + " ";
289 }
290 }
291 23 }
292
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
23 if(p_shortName != ""){
293
1/1
✓ Branch 1 taken 23 times.
23 std::string shortOption("-" + p_shortName);
294
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 18 times.
23 if(cursorOption == ""){
295
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
5 possibleOption += shortOption + " ";
296 }else{
297
3/3
✓ Branch 1 taken 18 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 14 times.
18 if(isSameBegining(shortOption, cursorOption)){
298
2/2
✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
4 possibleOption += shortOption + " ";
299 }
300 }
301 23 }
302 }
303
304 ///Complete the possible values of the Option
305 /** @param[out] possibleValue : possible value of the option
306 * @param cursorOption : option of the cursor which is currently completed
307 */
308 8 void Option::getPossibleValue(std::string & possibleValue, const std::string & cursorOption) const{
309 8 p_value.bashCompletionValue(possibleValue, cursorOption);
310 8 }
311
312 ///Copy function of Option
313 /** @param other : class to copy
314 */
315 421 void Option::copyOption(const Option & other){
316 421 p_longName = other.p_longName;
317 421 p_shortName = other.p_shortName;
318 421 p_value = other.p_value;
319 421 p_isRequired = other.p_isRequired;
320 421 p_docString = other.p_docString;
321 421 p_isParsed = other.p_isParsed;
322 421 p_firstPartParsedOption = other.p_firstPartParsedOption;
323 421 p_isAllowEmpty = other.p_isAllowEmpty;
324 421 }
325
326 ///Initialisation function of the class Option
327 204 void Option::initialisationOption(){
328 204 p_isParsed = false;
329 204 p_isRequired = false;
330 204 p_firstPartParsedOption = "";
331 204 p_isAllowEmpty = false;
332 204 }
333
334 ///Parse the given option with the parser
335 /** @param[out] parser : parser to be used
336 * @param prefix : option prefix (- or -- or nothing)
337 * @param optionName : name of hte option to be parsed
338 * @return true on success, false otherwise
339 */
340 104 bool Option::parsePartOption(ArgParser & parser, const std::string & prefix, const std::string & optionName){
341
2/3
✓ Branch 1 taken 104 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 104 times.
104 if(parser.isEndOfOption()){return true;}
342
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 104 times.
104 if(optionName == ""){return false;}
343
1/1
✓ Branch 1 taken 104 times.
104 std::string & currentOption = parser.getCurrentOption();
344
1/1
✓ Branch 1 taken 104 times.
104 std::string longOption(prefix + optionName);
345 104 size_t sizeLongOption(longOption.size());
346
1/1
✓ Branch 1 taken 104 times.
104 OptionType::OptionType optionType = p_value.getType();
347
2/2
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 76 times.
104 if(currentOption == longOption){
348
1/1
✓ Branch 1 taken 28 times.
28 checkAlreadyParsed(longOption);
349 28 p_isParsed = true;
350
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 26 times.
28 if(optionType == OptionType::NONE){ //No value expected
351
1/1
✓ Branch 1 taken 2 times.
2 parser.getNextOption();
352 2 return true; //Option found
353 }
354 26 bool valueOk(true), isInitialised(false);
355
1/1
✓ Branch 1 taken 26 times.
26 parser.getNextOption();
356
7/7
✓ Branch 1 taken 56 times.
✓ Branch 3 taken 34 times.
✓ Branch 4 taken 22 times.
✓ Branch 5 taken 30 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 30 times.
✓ Branch 8 taken 26 times.
56 while(!parser.isEndOfOption() && valueOk){
357
1/1
✓ Branch 1 taken 30 times.
30 std::string & currentOption = parser.getCurrentOption();
358
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 29 times.
30 if(currentOption == ""){
359
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(optionType == OptionType::STRING){
360
2/2
✓ Branch 2 taken 1 times.
✓ Branch 5 taken 1 times.
1 p_value.addValue("");
361
1/1
✓ Branch 1 taken 1 times.
1 parser.getNextOption();
362 1 valueOk = true;
363 1 isInitialised = true;
364 }else{
365 throw std::runtime_error("Option::parsePartOption : pass empty value to option '" + longOption + "' which does not expect STRING");
366 }
367 }else{
368
3/3
✓ Branch 1 taken 29 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 25 times.
29 if(currentOption[0] == '-'){
369 4 valueOk = false;
370 }else{
371
1/1
✓ Branch 1 taken 25 times.
25 p_value.addValue(currentOption);
372
1/1
✓ Branch 1 taken 25 times.
25 parser.getNextOption();
373 25 valueOk = true;
374 25 isInitialised = true;
375 }
376 }
377 }
378
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
26 if(!isInitialised && !p_isAllowEmpty){
379
3/3
✓ Branch 2 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 8 taken 2 times.
2 throw std::runtime_error("Option::parsePartOption : expect value after option '" + longOption + "'");
380 }
381
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
24 return isInitialised || p_isAllowEmpty;
382
3/3
✓ Branch 1 taken 76 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 63 times.
76 }else if(isSameBegining(currentOption, longOption)){
383
2/3
✓ Branch 1 taken 13 times.
✓ Branch 3 taken 13 times.
✗ Branch 4 not taken.
13 if(currentOption[sizeLongOption] == '='){
384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if(optionType == OptionType::NONE){ //No value expected
385 throw std::runtime_error("Option::parsePartOption : the option '"+currentOption+"' does not have value");
386 }
387
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 if(currentOption.size() == sizeLongOption + 1lu){
388 p_firstPartParsedOption = longOption + "=";
389 throw std::runtime_error("Option::parsePartOption : problem with the option '"+currentOption+"' because it ends with a '=' and not a value");
390 //Ici il faut un mode qui renvoie quand même les valeurs possibles quand on a --option=...
391 }
392
1/1
✓ Branch 1 taken 13 times.
13 checkAlreadyParsed(longOption);
393
1/1
✓ Branch 1 taken 13 times.
13 std::string value(currentOption.substr(sizeLongOption + 1lu));
394
1/1
✓ Branch 1 taken 13 times.
13 p_value.addValue(value);
395 13 p_isParsed = true;
396
1/1
✓ Branch 1 taken 13 times.
13 parser.getNextOption();
397 13 return true;
398 13 }else{
399 return false; //It is an option with a longer name
400 }
401 }
402 63 return false;
403 104 }
404
405 ///Check if the Option has been already parsed
406 /** @param longOption : used option
407 */
408 41 void Option::checkAlreadyParsed(const std::string & longOption){
409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if(p_isParsed){ //The option has already been parsed, there is a mistake
410 throw std::runtime_error("Option::checkAlreadyParsed : option '" + longOption + "' already exists");
411 }
412 41 }
413
414
415
416
417