Monero
command_line.h
Go to the documentation of this file.
1 // Copyright (c) 2014-2018, The Monero Project
2 //
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification, are
6 // permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice, this list of
9 // conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 // of conditions and the following disclaimer in the documentation and/or other
13 // materials provided with the distribution.
14 //
15 // 3. Neither the name of the copyright holder nor the names of its contributors may be
16 // used to endorse or promote products derived from this software without specific
17 // prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 //
29 // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
30 
31 #pragma once
32 
33 #include <functional>
34 #include <iostream>
35 #include <sstream>
36 #include <array>
37 #include <type_traits>
38 
39 #include <boost/program_options/parsers.hpp>
40 #include <boost/program_options/options_description.hpp>
41 #include <boost/program_options/variables_map.hpp>
42 #include "include_base_utils.h"
43 
44 namespace command_line
45 {
46 
48  bool is_yes(const std::string& str);
50  bool is_no(const std::string& str);
51 
52  template<typename T, bool required = false, bool dependent = false, int NUM_DEPS = 1>
54 
55  template<typename T>
57  {
58  typedef T value_type;
59 
60  const char* name;
61  const char* description;
64  };
65 
66  template<typename T>
67  struct arg_descriptor<std::vector<T>, false>
68  {
69  typedef std::vector<T> value_type;
70 
71  const char* name;
72  const char* description;
73  };
74 
75  template<typename T>
77  {
78  static_assert(!std::is_same<T, bool>::value, "Boolean switch can't be required");
79 
80  typedef T value_type;
81 
82  const char* name;
83  const char* description;
84  };
85 
86  template<typename T>
88  {
89  typedef T value_type;
90 
91  const char* name;
92  const char* description;
93 
95 
97  std::function<T(bool, bool, T)> depf;
98 
100  };
101 
102  template<typename T, int NUM_DEPS>
103  struct arg_descriptor<T, false, true, NUM_DEPS>
104  {
105  typedef T value_type;
106 
107  const char* name;
108  const char* description;
109 
111 
112  std::array<const arg_descriptor<bool, false> *, NUM_DEPS> ref;
113  std::function<T(std::array<bool, NUM_DEPS>, bool, T)> depf;
114 
116  };
117 
118  template<typename T>
119  boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, true>& /*arg*/)
120  {
121  return boost::program_options::value<T>()->required();
122  }
123 
124  template<typename T>
125  boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, false>& arg)
126  {
127  auto semantic = boost::program_options::value<T>();
128  if (!arg.not_use_default)
129  semantic->default_value(arg.default_value);
130  return semantic;
131  }
132 
133  template<typename T>
134  boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, false, true>& arg)
135  {
136  auto semantic = boost::program_options::value<T>();
137  if (!arg.not_use_default) {
138  std::ostringstream format;
139  format << arg.depf(false, true, arg.default_value) << ", "
140  << arg.depf(true, true, arg.default_value) << " if '"
141  << arg.ref.name << "'";
142  semantic->default_value(arg.depf(arg.ref.default_value, true, arg.default_value), format.str());
143  }
144  return semantic;
145  }
146 
147  template<typename T, int NUM_DEPS>
148  boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, false, true, NUM_DEPS>& arg)
149  {
150  auto semantic = boost::program_options::value<T>();
151  if (!arg.not_use_default) {
152  std::array<bool, NUM_DEPS> depval;
153  depval.fill(false);
154  std::ostringstream format;
155  format << arg.depf(depval, true, arg.default_value);
156  for (size_t i = 0; i < depval.size(); ++i)
157  {
158  depval.fill(false);
159  depval[i] = true;
160  format << ", " << arg.depf(depval, true, arg.default_value) << " if '" << arg.ref[i]->name << "'";
161  }
162  for (size_t i = 0; i < depval.size(); ++i)
163  depval[i] = arg.ref[i]->default_value;
164  semantic->default_value(arg.depf(depval, true, arg.default_value), format.str());
165  }
166  return semantic;
167  }
168 
169  template<typename T>
170  boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, false>& arg, const T& def)
171  {
172  auto semantic = boost::program_options::value<T>();
173  if (!arg.not_use_default)
174  semantic->default_value(def);
175  return semantic;
176  }
177 
178  template<typename T>
179  boost::program_options::typed_value<std::vector<T>, char>* make_semantic(const arg_descriptor<std::vector<T>, false>& /*arg*/)
180  {
181  auto semantic = boost::program_options::value< std::vector<T> >();
182  semantic->default_value(std::vector<T>(), "");
183  return semantic;
184  }
185 
186  template<typename T, bool required, bool dependent, int NUM_DEPS>
187  void add_arg(boost::program_options::options_description& description, const arg_descriptor<T, required, dependent, NUM_DEPS>& arg, bool unique = true)
188  {
189  if (0 != description.find_nothrow(arg.name, false))
190  {
191  CHECK_AND_ASSERT_MES(!unique, void(), "Argument already exists: " << arg.name);
192  return;
193  }
194 
195  description.add_options()(arg.name, make_semantic(arg), arg.description);
196  }
197 
198  template<typename T>
199  void add_arg(boost::program_options::options_description& description, const arg_descriptor<T, false>& arg, const T& def, bool unique = true)
200  {
201  if (0 != description.find_nothrow(arg.name, false))
202  {
203  CHECK_AND_ASSERT_MES(!unique, void(), "Argument already exists: " << arg.name);
204  return;
205  }
206 
207  description.add_options()(arg.name, make_semantic(arg, def), arg.description);
208  }
209 
210  template<>
211  inline void add_arg(boost::program_options::options_description& description, const arg_descriptor<bool, false>& arg, bool unique)
212  {
213  if (0 != description.find_nothrow(arg.name, false))
214  {
215  CHECK_AND_ASSERT_MES(!unique, void(), "Argument already exists: " << arg.name);
216  return;
217  }
218 
219  description.add_options()(arg.name, boost::program_options::bool_switch(), arg.description);
220  }
221 
222  template<typename charT>
223  boost::program_options::basic_parsed_options<charT> parse_command_line(int argc, const charT* const argv[],
224  const boost::program_options::options_description& desc, bool allow_unregistered = false)
225  {
226  auto parser = boost::program_options::command_line_parser(argc, argv);
227  parser.options(desc);
228  if (allow_unregistered)
229  {
230  parser.allow_unregistered();
231  }
232  return parser.run();
233  }
234 
235  template<typename F>
236  bool handle_error_helper(const boost::program_options::options_description& desc, F parser)
237  {
238  try
239  {
240  return parser();
241  }
242  catch (const std::exception& e)
243  {
244  std::cerr << "Failed to parse arguments: " << e.what() << std::endl;
245  std::cerr << desc << std::endl;
246  return false;
247  }
248  catch (...)
249  {
250  std::cerr << "Failed to parse arguments: unknown exception" << std::endl;
251  std::cerr << desc << std::endl;
252  return false;
253  }
254  }
255 
256  template<typename T, bool required, bool dependent, int NUM_DEPS>
257  typename std::enable_if<!std::is_same<T, bool>::value, bool>::type has_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, required, dependent, NUM_DEPS>& arg)
258  {
259  auto value = vm[arg.name];
260  return !value.empty();
261  }
262 
263  template<typename T, bool required, bool dependent, int NUM_DEPS>
264  bool is_arg_defaulted(const boost::program_options::variables_map& vm, const arg_descriptor<T, required, dependent, NUM_DEPS>& arg)
265  {
266  return vm[arg.name].defaulted();
267  }
268 
269  template<typename T>
270  T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, false, true>& arg)
271  {
272  return arg.depf(get_arg(vm, arg.ref), is_arg_defaulted(vm, arg), vm[arg.name].template as<T>());
273  }
274 
275  template<typename T, int NUM_DEPS>
276  T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, false, true, NUM_DEPS>& arg)
277  {
278  std::array<bool, NUM_DEPS> depval;
279  for (size_t i = 0; i < depval.size(); ++i)
280  depval[i] = get_arg(vm, *arg.ref[i]);
281  return arg.depf(depval, is_arg_defaulted(vm, arg), vm[arg.name].template as<T>());
282  }
283 
284  template<typename T, bool required>
285  T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, required>& arg)
286  {
287  return vm[arg.name].template as<T>();
288  }
289 
290  template<bool dependent, int NUM_DEPS>
291  inline bool has_arg(const boost::program_options::variables_map& vm, const arg_descriptor<bool, false, dependent, NUM_DEPS>& arg)
292  {
293  return get_arg(vm, arg);
294  }
295 
296 
297  extern const arg_descriptor<bool> arg_help;
298  extern const arg_descriptor<bool> arg_version;
299 }
std::array< const arg_descriptor< bool, false > *, NUM_DEPS > ref
Definition: command_line.h:112
bool is_no(const std::string &str)
Definition: command_line.cpp:63
T value_type
Definition: command_line.h:58
const uint32_t T[512]
Definition: groestl_tables.h:33
const arg_descriptor< bool, false > & ref
Definition: command_line.h:96
#define F(w, k)
Definition: sha512-blocks.c:61
const char * description
Definition: command_line.h:61
bool not_use_default
Definition: command_line.h:63
bool is_yes(const std::string &str)
Definition: command_line.cpp:49
const char * description
Definition: command_line.h:83
const char * description
Definition: command_line.h:72
Definition: blockchain_ancestry.cpp:70
const arg_descriptor< bool > arg_help
Definition: command_line.cpp:77
const char * description
Definition: command_line.h:92
bool not_use_default
Definition: command_line.h:99
const char * name
Definition: command_line.h:60
std::function< T(std::array< bool, NUM_DEPS >, bool, T)> depf
Definition: command_line.h:113
const char * name
Definition: command_line.h:71
std::function< T(bool, bool, T)> depf
Definition: command_line.h:97
const char * description
Definition: command_line.h:108
bool not_use_default
Definition: command_line.h:115
const char * name
Definition: command_line.h:82
bool handle_error_helper(const boost::program_options::options_description &desc, F parser)
Definition: command_line.h:236
std::enable_if<!std::is_same< T, bool >::value, bool >::type has_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg)
Definition: command_line.h:257
boost::program_options::typed_value< T, char > * make_semantic(const arg_descriptor< T, true > &)
Definition: command_line.h:119
T default_value
Definition: command_line.h:94
#define false
Definition: stdbool.h:37
Definition: command_line.cpp:39
void add_arg(boost::program_options::options_description &description, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg, bool unique=true)
Definition: command_line.h:187
T value_type
Definition: command_line.h:89
const char * name
Definition: command_line.h:107
T get_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, false, true > &arg)
Definition: command_line.h:270
boost::program_options::basic_parsed_options< charT > parse_command_line(int argc, const charT *const argv[], const boost::program_options::options_description &desc, bool allow_unregistered=false)
Definition: command_line.h:223
int bool
Definition: stdbool.h:35
T value_type
Definition: command_line.h:78
Definition: command_line.h:76
const char * name
Definition: command_line.h:91
Definition: command_line.h:53
const arg_descriptor< bool > arg_version
Definition: command_line.cpp:78
std::vector< T > value_type
Definition: command_line.h:69
#define true
Definition: stdbool.h:36
bool is_arg_defaulted(const boost::program_options::variables_map &vm, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg)
Definition: command_line.h:264
T default_value
Definition: command_line.h:62
Definition: command_line.h:56