| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* -*- c++ -*- */ | ||
| 2 | /* | ||
| 3 | * Copyright 2018-2020 Free Software Foundation, Inc. | ||
| 4 | * | ||
| 5 | * This file is part of VOLK | ||
| 6 | * | ||
| 7 | * SPDX-License-Identifier: LGPL-3.0-or-later | ||
| 8 | */ | ||
| 9 | |||
| 10 | |||
| 11 | #include "volk_option_helpers.h" | ||
| 12 | |||
| 13 | #include <limits.h> // IWYU pragma: keep | ||
| 14 | #include <cstdlib> // IWYU pragma: keep | ||
| 15 | #include <cstring> // IWYU pragma: keep | ||
| 16 | #include <exception> // for exception | ||
| 17 | #include <iostream> // for operator<<, endl, basic_ostream, cout, ostream | ||
| 18 | #include <utility> // for pair | ||
| 19 | |||
| 20 | /* | ||
| 21 | * Option type | ||
| 22 | */ | ||
| 23 | ✗ | option_t::option_t(std::string t_longform, | |
| 24 | std::string t_shortform, | ||
| 25 | std::string t_msg, | ||
| 26 | ✗ | void (*t_callback)()) | |
| 27 | ✗ | : longform("--" + t_longform), | |
| 28 | ✗ | shortform("-" + t_shortform), | |
| 29 | ✗ | msg(t_msg), | |
| 30 | ✗ | callback(t_callback) | |
| 31 | { | ||
| 32 | ✗ | option_type = VOID_CALLBACK; | |
| 33 | ✗ | } | |
| 34 | |||
| 35 | ✗ | option_t::option_t(std::string t_longform, | |
| 36 | std::string t_shortform, | ||
| 37 | std::string t_msg, | ||
| 38 | ✗ | void (*t_callback)(int)) | |
| 39 | ✗ | : longform("--" + t_longform), | |
| 40 | ✗ | shortform("-" + t_shortform), | |
| 41 | ✗ | msg(t_msg), | |
| 42 | ✗ | callback((void (*)())t_callback) | |
| 43 | { | ||
| 44 | ✗ | option_type = INT_CALLBACK; | |
| 45 | ✗ | } | |
| 46 | |||
| 47 | ✗ | option_t::option_t(std::string t_longform, | |
| 48 | std::string t_shortform, | ||
| 49 | std::string t_msg, | ||
| 50 | ✗ | void (*t_callback)(float)) | |
| 51 | ✗ | : longform("--" + t_longform), | |
| 52 | ✗ | shortform("-" + t_shortform), | |
| 53 | ✗ | msg(t_msg), | |
| 54 | ✗ | callback((void (*)())t_callback) | |
| 55 | { | ||
| 56 | ✗ | option_type = FLOAT_CALLBACK; | |
| 57 | ✗ | } | |
| 58 | |||
| 59 | ✗ | option_t::option_t(std::string t_longform, | |
| 60 | std::string t_shortform, | ||
| 61 | std::string t_msg, | ||
| 62 | ✗ | void (*t_callback)(bool)) | |
| 63 | ✗ | : longform("--" + t_longform), | |
| 64 | ✗ | shortform("-" + t_shortform), | |
| 65 | ✗ | msg(t_msg), | |
| 66 | ✗ | callback((void (*)())t_callback) | |
| 67 | { | ||
| 68 | ✗ | option_type = BOOL_CALLBACK; | |
| 69 | ✗ | } | |
| 70 | |||
| 71 | ✗ | option_t::option_t(std::string t_longform, | |
| 72 | std::string t_shortform, | ||
| 73 | std::string t_msg, | ||
| 74 | ✗ | void (*t_callback)(std::string)) | |
| 75 | ✗ | : longform("--" + t_longform), | |
| 76 | ✗ | shortform("-" + t_shortform), | |
| 77 | ✗ | msg(t_msg), | |
| 78 | ✗ | callback((void (*)())t_callback) | |
| 79 | { | ||
| 80 | ✗ | option_type = STRING_CALLBACK; | |
| 81 | ✗ | } | |
| 82 | |||
| 83 | ✗ | option_t::option_t(std::string t_longform, | |
| 84 | std::string t_shortform, | ||
| 85 | std::string t_msg, | ||
| 86 | ✗ | std::string t_printval) | |
| 87 | ✗ | : longform("--" + t_longform), | |
| 88 | ✗ | shortform("-" + t_shortform), | |
| 89 | ✗ | msg(t_msg), | |
| 90 | ✗ | printval(t_printval) | |
| 91 | { | ||
| 92 | ✗ | option_type = STRING; | |
| 93 | ✗ | } | |
| 94 | |||
| 95 | |||
| 96 | /* | ||
| 97 | * Option List | ||
| 98 | */ | ||
| 99 | |||
| 100 | ✗ | option_list::option_list(std::string program_name) : d_program_name(program_name) | |
| 101 | { | ||
| 102 | ✗ | d_internal_list = std::vector<option_t>(); | |
| 103 | ✗ | } | |
| 104 | |||
| 105 | |||
| 106 | ✗ | void option_list::add(option_t opt) { d_internal_list.push_back(opt); } | |
| 107 | |||
| 108 | ✗ | void option_list::parse(int argc, char** argv) | |
| 109 | { | ||
| 110 | ✗ | for (int arg_number = 0; arg_number < argc; ++arg_number) { | |
| 111 | ✗ | for (std::vector<option_t>::iterator this_option = d_internal_list.begin(); | |
| 112 | ✗ | this_option != d_internal_list.end(); | |
| 113 | ✗ | this_option++) { | |
| 114 | ✗ | int int_val = INT_MIN; | |
| 115 | ✗ | if (this_option->longform == std::string(argv[arg_number]) || | |
| 116 | ✗ | this_option->shortform == std::string(argv[arg_number])) { | |
| 117 | |||
| 118 | ✗ | if (d_present_options.count(this_option->longform) == 0) { | |
| 119 | ✗ | d_present_options.insert( | |
| 120 | ✗ | std::pair<std::string, int>(this_option->longform, 1)); | |
| 121 | } else { | ||
| 122 | ✗ | d_present_options[this_option->longform] += 1; | |
| 123 | } | ||
| 124 | ✗ | switch (this_option->option_type) { | |
| 125 | ✗ | case VOID_CALLBACK: | |
| 126 | ✗ | this_option->callback(); | |
| 127 | ✗ | break; | |
| 128 | ✗ | case INT_CALLBACK: | |
| 129 | try { | ||
| 130 | ✗ | int_val = atoi(argv[++arg_number]); | |
| 131 | ✗ | ((void (*)(int))this_option->callback)(int_val); | |
| 132 | ✗ | } catch (std::exception& exc) { | |
| 133 | ✗ | std::cout << "An int option can only receive a number" | |
| 134 | ✗ | << std::endl; | |
| 135 | ✗ | throw std::exception(); | |
| 136 | ✗ | }; | |
| 137 | ✗ | break; | |
| 138 | ✗ | case FLOAT_CALLBACK: | |
| 139 | try { | ||
| 140 | ✗ | double double_val = atof(argv[++arg_number]); | |
| 141 | ✗ | ((void (*)(float))this_option->callback)(double_val); | |
| 142 | ✗ | } catch (std::exception& exc) { | |
| 143 | ✗ | std::cout << "A float option can only receive a number" | |
| 144 | ✗ | << std::endl; | |
| 145 | ✗ | throw std::exception(); | |
| 146 | ✗ | }; | |
| 147 | ✗ | break; | |
| 148 | ✗ | case BOOL_CALLBACK: | |
| 149 | try { | ||
| 150 | ✗ | if (arg_number == (argc - 1)) { // this is the last arg | |
| 151 | ✗ | int_val = 1; | |
| 152 | } else { // sneak a look at the next arg since it's present | ||
| 153 | ✗ | char* next_arg = argv[arg_number + 1]; | |
| 154 | ✗ | if ((strncmp(next_arg, "-", 1) == 0) || | |
| 155 | ✗ | (strncmp(next_arg, "--", 2) == 0)) { | |
| 156 | // the next arg is actually an arg, the bool is just | ||
| 157 | // present, set to true | ||
| 158 | ✗ | int_val = 1; | |
| 159 | ✗ | } else if (strncmp(next_arg, "true", 4) == 0) { | |
| 160 | ✗ | int_val = 1; | |
| 161 | ✗ | } else if (strncmp(next_arg, "false", 5) == 0) { | |
| 162 | ✗ | int_val = 0; | |
| 163 | } else { | ||
| 164 | // we got a number or a string. | ||
| 165 | // convert it to a number and depend on the catch to | ||
| 166 | // report an error condition | ||
| 167 | ✗ | int_val = (bool)atoi(argv[++arg_number]); | |
| 168 | } | ||
| 169 | } | ||
| 170 | } catch (std::exception& e) { | ||
| 171 | int_val = INT_MIN; | ||
| 172 | }; | ||
| 173 | ✗ | if (int_val == INT_MIN) { | |
| 174 | std::cout | ||
| 175 | ✗ | << "option: '" << argv[arg_number - 1] | |
| 176 | << "' -> received an unknown value. Boolean " | ||
| 177 | ✗ | "options should receive one of '0', '1', 'true', 'false'." | |
| 178 | ✗ | << std::endl; | |
| 179 | ✗ | throw std::exception(); | |
| 180 | ✗ | } else if (int_val) { | |
| 181 | ✗ | ((void (*)(bool))this_option->callback)(int_val); | |
| 182 | } | ||
| 183 | ✗ | break; | |
| 184 | ✗ | case STRING_CALLBACK: | |
| 185 | try { | ||
| 186 | ✗ | ((void (*)(std::string))this_option->callback)( | |
| 187 | ✗ | argv[++arg_number]); | |
| 188 | ✗ | } catch (std::exception& exc) { | |
| 189 | ✗ | throw std::exception(); | |
| 190 | ✗ | }; | |
| 191 | ✗ | case STRING: | |
| 192 | ✗ | std::cout << this_option->printval << std::endl; | |
| 193 | ✗ | break; | |
| 194 | } | ||
| 195 | } | ||
| 196 | } | ||
| 197 | ✗ | if (std::string("--help") == std::string(argv[arg_number]) || | |
| 198 | ✗ | std::string("-h") == std::string(argv[arg_number])) { | |
| 199 | ✗ | d_present_options.insert(std::pair<std::string, int>("--help", 1)); | |
| 200 | ✗ | help(); | |
| 201 | } | ||
| 202 | } | ||
| 203 | ✗ | } | |
| 204 | |||
| 205 | ✗ | bool option_list::present(std::string option_name) | |
| 206 | { | ||
| 207 | ✗ | if (d_present_options.count("--" + option_name)) { | |
| 208 | ✗ | return true; | |
| 209 | } else { | ||
| 210 | ✗ | return false; | |
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 214 | ✗ | void option_list::help() | |
| 215 | { | ||
| 216 | ✗ | std::cout << d_program_name << std::endl; | |
| 217 | ✗ | std::cout << " -h [ --help ] \t\tdisplay this help message" << std::endl; | |
| 218 | ✗ | for (std::vector<option_t>::iterator this_option = d_internal_list.begin(); | |
| 219 | ✗ | this_option != d_internal_list.end(); | |
| 220 | ✗ | this_option++) { | |
| 221 | ✗ | std::string help_line(" "); | |
| 222 | ✗ | if (this_option->shortform == "-") { | |
| 223 | ✗ | help_line += this_option->longform + " "; | |
| 224 | } else { | ||
| 225 | ✗ | help_line += this_option->shortform + " [ " + this_option->longform + " ]"; | |
| 226 | } | ||
| 227 | |||
| 228 | ✗ | switch (help_line.size() / 8) { | |
| 229 | ✗ | case 0: | |
| 230 | ✗ | help_line += "\t"; | |
| 231 | ✗ | case 1: | |
| 232 | ✗ | help_line += "\t"; | |
| 233 | ✗ | case 2: | |
| 234 | ✗ | help_line += "\t"; | |
| 235 | ✗ | case 3: | |
| 236 | ✗ | help_line += "\t"; | |
| 237 | } | ||
| 238 | ✗ | help_line += this_option->msg; | |
| 239 | ✗ | std::cout << help_line << std::endl; | |
| 240 | ✗ | } | |
| 241 | ✗ | } | |
| 242 |