The Sparta Modeling Framework
Loading...
Searching...
No Matches
MultiDetailOptions.hpp
Go to the documentation of this file.
1// <MultiDetailOptions.hpp> -*- C++ -*-
2
3
10#pragma once
11
12#include <boost/program_options.hpp>
13
14#include "sparta/sparta.hpp"
15
16namespace po = boost::program_options;
17
18namespace sparta {
19 namespace app {
20
24template <typename ArgT>
25class named_value_type : public po::typed_value<ArgT>
26{
27 unsigned min_;
28 unsigned max_;
29 std::string my_name_;
30
31public:
32
36 typedef po::typed_value<ArgT> base_t;
37
41 named_value_type(std::string const& name, ArgT* val) :
42 po::typed_value<ArgT>(val),
43 min_(0),
44 max_(1),
45 my_name_(name)
46 { }
47
51 named_value_type(std::string const& name, ArgT* val, unsigned min, unsigned max) :
52 po::typed_value<ArgT>(val),
53 min_(min),
54 max_(max),
55 my_name_(name)
56 { }
57
58 virtual ~named_value_type() {}
59
63 virtual std::string name() const override { return my_name_; }
64
65 named_value_type* min(unsigned min)
66 {
67 min_ = min;
68 return this;
69 }
70
71 named_value_type* max(unsigned max)
72 {
73 max_ = max;
74 return this;
75 }
76
77 named_value_type* multitoken()
78 {
79 base_t::multitoken();
80 return this;
81 }
82
86 virtual unsigned min_tokens() const override { return min_; }
87
91 virtual unsigned max_tokens() const override { return max_; }
92
97 virtual void xparse(boost::any& value_store,
98 const std::vector<std::basic_string<char>>& new_tokens) const override;
99
104 void xparse_base_(boost::any& value_store,
105 const std::vector<std::basic_string<char>>& new_tokens) const {
106 po::typed_value<ArgT>::xparse(value_store, new_tokens);
107 }
108};
109
113template <typename ArgT>
115public:
116
123 static void parse_(const named_value_type<ArgT>& nvt,
124 boost::any& value_store,
125 const std::vector<std::basic_string<char>>& new_tokens) {
126 nvt.xparse_base_(value_store, new_tokens);
127 }
128};
129
130template <class ArgT>
131void named_value_type<ArgT>::xparse(boost::any& value_store,
132 const std::vector<std::basic_string<char>>& new_tokens) const {
133 // Invoked the appropriately typed named_value_parser
134 //std::cout << "parsing " << my_name_ << " : " << new_tokens << std::endl;
135 named_value_parser<ArgT>::parse_(*this, value_store, new_tokens);
136}
137
141template <>
142class named_value_parser<uint64_t> {
143public:
144 static void parse_(const named_value_type<uint64_t>& nvt,
145 boost::any& value_store,
146 const std::vector<std::basic_string<char>>& new_tokens) {
147 (void) nvt;
148 size_t end_pos;
149 uint64_t val = utils::smartLexicalCast<uint64_t>(new_tokens.at(0), end_pos);
150 //std::cout << " got: " << val << std::endl;
151 value_store = val;
152 }
153};
154
158template <>
159class named_value_parser<int64_t> {
160public:
161 static void parse_(const named_value_type<int64_t>& nvt,
162 boost::any& value_store,
163 const std::vector<std::basic_string<char>>& new_tokens) {
164 (void) nvt;
165 size_t end_pos;
166 int64_t val = utils::smartLexicalCast<int64_t>(new_tokens.at(0), end_pos);
167 //std::cout << " got: " << val << std::endl;
168 value_store = val;
169 }
170};
171
175template <>
176class named_value_parser<uint32_t> {
177public:
178 static void parse_(const named_value_type<uint32_t>& nvt,
179 boost::any& value_store,
180 const std::vector<std::basic_string<char>>& new_tokens) {
181 (void) nvt;
182 size_t end_pos;
183 uint32_t val = utils::smartLexicalCast<uint32_t>(new_tokens.at(0), end_pos);
184 //std::cout << " got: " << val << std::endl;
185 value_store = val;
186 }
187};
188
192template <>
193class named_value_parser<int32_t> {
194public:
195 static void parse_(const named_value_type<int32_t>& nvt,
196 boost::any& value_store,
197 const std::vector<std::basic_string<char>>& new_tokens) {
198 (void) nvt;
199 size_t end_pos;
200 int32_t val = utils::smartLexicalCast<int32_t>(new_tokens.at(0), end_pos);
201 //std::cout << " got: " << val << std::endl;
202 value_store = val;
203 }
204};
205
209template <>
210class named_value_parser<uint16_t> {
211public:
212 static void parse_(const named_value_type<uint16_t>& nvt,
213 boost::any& value_store,
214 const std::vector<std::basic_string<char>>& new_tokens) {
215 (void) nvt;
216 size_t end_pos;
217 uint16_t val = utils::smartLexicalCast<uint16_t>(new_tokens.at(0), end_pos);
218 //std::cout << " got: " << val << std::endl;
219 value_store = val;
220 }
221};
222
226template <>
227class named_value_parser<int16_t> {
228public:
229 static void parse_(const named_value_type<int16_t>& nvt,
230 boost::any& value_store,
231 const std::vector<std::basic_string<char>>& new_tokens) {
232 (void) nvt;
233 size_t end_pos;
234 int16_t val = utils::smartLexicalCast<int16_t>(new_tokens.at(0), end_pos);
235 //std::cout << " got: " << val << std::endl;
236 value_store = val;
237 }
238};
239
243template <>
244class named_value_parser<uint8_t> {
245public:
246 static void parse_(const named_value_type<uint8_t>& nvt,
247 boost::any& value_store,
248 const std::vector<std::basic_string<char>>& new_tokens) {
249 (void) nvt;
250 size_t end_pos;
251 uint8_t val = utils::smartLexicalCast<uint8_t>(new_tokens.at(0), end_pos);
252 //std::cout << " got: " << val << std::endl;
253 value_store = val;
254 }
255};
256
260template <>
261class named_value_parser<int8_t> {
262public:
263 static void parse_(const named_value_type<int8_t>& nvt,
264 boost::any& value_store,
265 const std::vector<std::basic_string<char>>& new_tokens) {
266 (void) nvt;
267 size_t end_pos;
268 int8_t val = utils::smartLexicalCast<int8_t>(new_tokens.at(0), end_pos);
269 //std::cout << " got: " << val << std::endl;
270 value_store = val;
271 }
272};
273
274
279template <typename ArgT>
280inline named_value_type<ArgT>* named_value(std::string const& name, ArgT* val=nullptr) {
281 return new named_value_type<ArgT>(name, val);
282}
283
284template <typename ArgT>
285inline named_value_type<ArgT>* named_value(std::string const& name, unsigned min, unsigned max, ArgT* val=nullptr) {
286 return new named_value_type<ArgT>(name, val, min, max);
287}
288
289
294{
295public:
296
297 typedef uint32_t level_t;
298
299 static const level_t VERBOSE = 0;
300 static const level_t BRIEF = 1;
301
305 class OptAdder {
306 MultiDetailOptions& opts_;
307
308 public:
310 opts_(opts)
311 {;}
312
317 template <typename ...Args>
318 OptAdder& operator()(const char* name,
319 const char* verbose_desc,
320 const Args& ...args)
321 {
322 opts_.add_option_with_desc_level_(0, name, verbose_desc, args...);
323
324 return *this;
325 }
326
331 template <typename ...Args>
332 OptAdder operator()(const char* name,
333 const boost::program_options::value_semantic* s,
334 const char* verbose_desc,
335 const Args& ...args)
336 {
337 opts_.add_option_with_desc_level_(0, name, s, verbose_desc, args...);
338
339 return *this;
340 }
341 };
342
346 friend class OptAdded;
347
352
357
362
367 MultiDetailOptions(const std::string& name, uint32_t w=80, uint32_t hw=40) :
368 opt_adder_(*this),
369 name_(name)
370 {
371 descs_.emplace_back(new po::options_description(name_, w, hw));
372 descs_.emplace_back(new po::options_description(name_, w, hw));
373
374 sparta_assert(descs_.size() > VERBOSE);
375 sparta_assert(descs_.size() > BRIEF);
376 }
377
386 const po::options_description& getOptionsLevelUpTo(level_t level) const {
387 if(level < descs_.size()){
388 return *descs_.at(level);
389 }else{
390 sparta_assert(descs_.size() > 0);
391 return *descs_.at(descs_.size() - 1);
392 }
393 }
394
401 const po::options_description& getOptionsLevel(level_t level) const {
402 return *descs_.at(level);
403 }
404
408 const po::options_description& getVerboseOptions() const noexcept {
409 return *descs_.at(VERBOSE);
410 }
411
416 size_t getNumLevels() const {
417 return descs_.size();
418 }
419
424 template <typename ...Args>
425 OptAdder& add_options(const char* name,
426 const char* verbose_desc,
427 const Args& ...args)
428 {
429 add_option_with_desc_level_(0, name, verbose_desc, args...);
430
431 return opt_adder_;
432 }
433
460 template <typename ...Args>
461 OptAdder& add_options(const char* name,
462 const boost::program_options::value_semantic* s,
463 const char* verbose_desc,
464 const Args& ...args)
465 {
466 add_option_with_desc_level_(0, name, s, verbose_desc, args...);
467
468 return opt_adder_;
469 }
470
484 {
485 return opt_adder_;
486 }
487
488private:
489
494 void add_option_with_desc_level_(size_t level,
495 const char* name)
496 {
497 (void) level;
498 (void) name;
499 }
500
505 template <typename ...Args>
506 void add_option_with_desc_level_(size_t level,
507 const char* name,
508 const char* desc,
509 const Args& ...args) {
510 while(descs_.size() <= level){
511 descs_.emplace_back(new po::options_description(name_));
512 }
513
514 descs_.at(level)->add_options()
515 (name, desc);
516
517 // Recursively invoke until terminator overload of this func is reached
518 add_option_with_desc_level_(level+1, name, args...);
519 }
520
521
523 //void add_option_with_desc_level_(size_t level,
524 // const char* name,
525 // const boost::program_options::value_semantic* s)
526 //{
527 // (void) level;
528 // (void) name;
529 // delete s; // Delete unused copy of value_semantic
530 //}
531
539 template <typename ...Args>
540 void add_option_with_desc_level_(size_t level,
541 const char* name,
542 const boost::program_options::value_semantic* s,
543 const char* desc,
544 const Args& ...args) {
545 while(descs_.size() <= level){
546 descs_.emplace_back(new po::options_description(name_));
547 }
548
549 descs_.at(level)->add_options()
550 (name, s, desc);
551
552 // Recursively invoke until terminator overload of this func is reached
553 // Note that this invoked the OTHER signature with NO VALUE SEMANTIC.
554 // Boost frees these on destruction, so assigning the same pointer to
555 // multiple options will create a double-free segfault.
556 // The implication is that parsing must be done at the verbose level and
557 // higher levels will have no semantic information (e.g. arguments)
558 add_option_with_desc_level_(level+1, name, args...);
559 }
560
565 OptAdder opt_adder_;
566
570 const std::string name_;
571
575 std::vector<std::unique_ptr<po::options_description>> descs_;
576
577}; // class MultiDetailOptions
578
579 } // namespace app
580} // namespace sparta
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
Helper class for chained calls to add_options.
OptAdder operator()(const char *name, const boost::program_options::value_semantic *s, const char *verbose_desc, const Args &...args)
Acts like calling MultiDetailOptions::add_options on the object that created this OptAdder.
OptAdder & operator()(const char *name, const char *verbose_desc, const Args &...args)
Acts like calling MultiDetailOptions::add_options on the object that created this OptAdder.
Class for containing multiple levels of boost program options.
friend class OptAdded
Allow access to private adding methods.
const po::options_description & getVerboseOptions() const noexcept
Gets the description object for the VERBOSE level.
const po::options_description & getOptionsLevel(level_t level) const
Gets the description object for a particular level. Only VERBOSE and BRIEF levels are guaranteed to e...
MultiDetailOptions(const MultiDetailOptions &)=delete
Not copy-constructable.
size_t getNumLevels() const
Returns the number of levels that have an options description which can be retrieved through getLevel...
MultiDetailOptions(const std::string &name, uint32_t w=80, uint32_t hw=40)
Construction with group nam.
MultiDetailOptions & operator=(const MultiDetailOptions &)=delete
Not assignable.
OptAdder & add_options(const char *name, const char *verbose_desc, const Args &...args)
Add an option with NO value semantic and any number of descriptions. See the other add_options signat...
OptAdder & add_options()
Empty add_options shell allowing the start of chained calls (exists solely to mimic boost's syntax)
const po::options_description & getOptionsLevelUpTo(level_t level) const
Gets the description object for a particular level if that level exists. If that level does not exist...
OptAdder & add_options(const char *name, const boost::program_options::value_semantic *s, const char *verbose_desc, const Args &...args)
Add an option with a value semantic and any number of descriptions.
MultiDetailOptions()=delete
Not default-constructable.
Parser helper for named_value_type.
static void parse_(const named_value_type< ArgT > &nvt, boost::any &value_store, const std::vector< std::basic_string< char > > &new_tokens)
Default implementation of parse_ - overridden in class template specializations.
Helper class for populating boost program options.
virtual std::string name() const override
boost semantic for getting name of this option
named_value_type(std::string const &name, ArgT *val)
Constructor.
named_value_type(std::string const &name, ArgT *val, unsigned min, unsigned max)
Constructor with min and max extents.
po::typed_value< ArgT > base_t
Type of base class.
virtual void xparse(boost::any &value_store, const std::vector< std::basic_string< char > > &new_tokens) const override
Override parser.
virtual unsigned max_tokens() const override
boost semantic for specifying max tokens
void xparse_base_(boost::any &value_store, const std::vector< std::basic_string< char > > &new_tokens) const
Call xparse on base class. This is available to named_value_parser for invoking the default parser wh...
virtual unsigned min_tokens() const override
boost semantic for specifying min tokens
named_value_type< ArgT > * named_value(std::string const &name, ArgT *val=nullptr)
Helper function for generating new named_value_type structs in the boost style.
Macros for handling exponential backoff.