All Classes Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
value.hpp
1 // The MIT License (MIT)
2 
3 // Copyright (c) 2012-2014 Danny Y., Rapptz
4 
5 // Permission is hereby granted, free of charge, to any person obtaining a copy of
6 // this software and associated documentation files (the "Software"), to deal in
7 // the Software without restriction, including without limitation the rights to
8 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 // the Software, and to permit persons to whom the Software is furnished to do so,
10 // subject to the following conditions:
11 
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22 #ifndef GEARS_OPTPARSE_VALUE_HPP
23 #define GEARS_OPTPARSE_VALUE_HPP
24 
25 #include "actions.hpp"
26 #include "../utility/helpers.hpp"
27 
28 namespace gears {
29 namespace optparse {
30 struct value_base {
31  std::string metavar;
32  size_t nargs = 1;
33 
34  virtual ~value_base() = default;
35  virtual void parse(const std::string&, const std::string&) = 0;
36  virtual bool is_active() const noexcept = 0;
37  virtual std::unique_ptr<value_base> clone() const = 0;
38 };
39 
50 template<typename T>
51 struct typed_value : public value_base {
52 private:
53  T* reference = nullptr;
54  std::unique_ptr<T> value;
55  std::function<T(const std::string&, const std::string&)> action_;
56  bool active = false;
57 
58  void parse(const std::string& key, const std::string& val) override {
59  auto&& result = action_(key, val);
60  active = true;
61  if(reference != nullptr) {
62  *reference = std::move(result);
63  }
64  else {
65  value.reset(new T(std::move(result)));
66  }
67  }
68 
69  std::unique_ptr<value_base> clone() const override {
70  auto&& ptr = utility::make_unique<typed_value<T>>(action_);
71  ptr->reference = reference;
72  ptr->active = active;
73  ptr->nargs = nargs;
74  ptr->metavar = metavar;
75  return std::unique_ptr<value_base>{std::move(ptr)};
76  }
77 public:
81  template<typename Action>
82  typed_value(Action action): action_(std::move(action)) {}
83 
92  typed_value(T& object): reference(&object) {}
93 
94 
101  bool is_active() const noexcept override {
102  return active;
103  }
104 
118  template<typename Action>
119  typed_value& action(Action&& action) {
120  action_ = std::forward<Action>(action);
121  return *this;
122  }
123 
133  const T& get() const {
134  if(!active) {
135  throw std::runtime_error("value has not been parsed");
136  }
137 
138  if(reference != nullptr) {
139  return *reference;
140  }
141  return *value;
142  }
143 
152  const T& get_or(const T& def) const noexcept {
153  if(is_active()) {
154  if(reference != nullptr) {
155  return *reference;
156  }
157  return *value;
158  }
159  return def;
160  }
161 };
162 
176 template<typename Container, typename Action = store<typename Container::value_type>>
177 inline std::unique_ptr<value_base> compose(std::string metavar = "", Action action = Action{}) {
178  auto&& ptr = utility::make_unique<typed_value<Container>>(append<Container>{action});
179  ptr->metavar = std::move(metavar);
180  return std::unique_ptr<value_base>{std::move(ptr)};
181 }
182 
203 template<typename T, typename Action = store<T>>
204 inline std::unique_ptr<value_base> bind_to(T& t, std::string metavar = "", Action action = Action{}) {
205  auto&& ptr = utility::make_unique<typed_value<T>>(t);
206  ptr->action(std::move(action));
207  ptr->metavar = std::move(metavar);
208  return std::unique_ptr<value_base>{std::move(ptr)};
209 }
210 
223 template<typename T>
224 inline std::unique_ptr<value_base> constant(const T& t) {
225  auto&& ptr = utility::make_unique<typed_value<T>>(store_const<T>{t});
226  ptr->nargs = 0;
227  return std::unique_ptr<value_base>{std::move(ptr)};
228 }
229 
243 template<typename T, typename Action = store<T>>
244 inline std::unique_ptr<value_base> value(std::string metavar = "", Action action = Action{}) {
245  auto&& ptr = utility::make_unique<typed_value<T>>(action);
246  ptr->metavar = std::move(metavar);
247  return std::unique_ptr<value_base>{std::move(ptr)};
248 }
249 
264 template<typename T, typename Action>
265 inline std::unique_ptr<value_base> custom(Action action, std::string metavar = "") {
266  auto&& ptr = utility::make_unique<typed_value<T>>(action);
267  ptr->metavar = std::move(metavar);
268  return std::unique_ptr<value_base>{std::move(ptr)};
269 }
270 
282 template<typename Container, typename Action = store<typename Container::value_type>>
283 inline std::unique_ptr<value_base> list(size_t arguments, std::string metavar = "", Action action = Action{}) {
284  static_assert(std::is_convertible<decltype(action("", "")), typename Container::value_type>::value,
285  "The action must return a type convertible to the container's value type");
286  auto&& ptr = utility::make_unique<typed_value<Container>>(store_list<Container, Action>{action});
287  ptr->nargs = arguments;
288  ptr->metavar = std::move(metavar);
289  return std::unique_ptr<value_base>{std::move(ptr)};
290 }
291 } // optparse
292 } // gears
293 
294 #endif // GEARS_OPTPARSE_VALUE_HPP