creativity  v1.3.0
Agent-based model of creativity and piracy
Validation.hpp
1 #pragma once
2 #include "creativity/cmdargs/strings.hpp"
3 #include <boost/program_options/errors.hpp>
4 #include <boost/program_options/options_description.hpp>
5 #include <boost/program_options/positional_options.hpp>
6 #include <boost/program_options/value_semantic.hpp>
7 #include <string>
8 #include <regex>
9 
10 namespace creativity { namespace cmdargs {
11 
15 class ValidationTag {};
16 
28 template <typename T>
29 class Validation : public ValidationTag {
30  public:
32  Validation(T v) : val_(v) {}
34  operator const T& () const { return val_; }
36  using value_type = T;
38  static std::string validationString() {
39  if (std::is_unsigned<T>::value) { return type_string<T>() + u8"⩾0"; }
40  return type_string<T>();
41  }
43  virtual ~Validation() = default;
44 
45  protected:
47  T val_;
48 };
49 
60 template <typename T, long min, long denom = 1>
61 class Min : public virtual Validation<T> {
62  public:
64  Min(T v) : Validation<T>(v) {
65  if (*this < min / (double) denom)
66  throw boost::program_options::validation_error(boost::program_options::validation_error::invalid_option_value);
67  }
68 
70  static std::string validationString() { return type_string<T>() + u8"⩾" + (denom == 1 ? output_string(min) : output_string(min / (double) denom)); }
71 };
72 
82 template<typename T, long max, long denom = 1>
83 class Max : public virtual Validation<T> {
84  public:
86  Max(T v) : Validation<T>(v) {
87  if (*this > max / (double) denom)
88  throw boost::program_options::validation_error(boost::program_options::validation_error::invalid_option_value);
89  }
90 
92  static std::string validationString() { return type_string<T>() + u8"⩽" + (denom == 1 ? output_string(max) : output_string(max / (double) denom)); }
93 };
94 
102 template<typename T, long min, long max, long denom = 1>
103 class Range : public Min<T, min>, public Max<T, max> {
104  public:
106  Range(T v) : Validation<T>(v), Min<T, min, denom>(v), Max<T, max, denom>(v) {}
107 
109  static std::string validationString() { return (denom == 1 ? output_string(min) : output_string(min / (double) denom)) + u8"⩽" + type_string<T>() + u8"⩽" + (denom == 1 ? output_string(max) : output_string(max / (double) denom)); }
110 };
111 
119 template <typename T, long lower, long denom = 1>
120 class Above : public virtual Validation<T> {
121  public:
123  Above(T v) : Validation<T>(v) {
124  if (*this <= lower / (double) denom)
125  throw boost::program_options::validation_error(boost::program_options::validation_error::invalid_option_value);
126  }
127 
129  static std::string validationString() { return type_string<T>() + u8">" + (denom == 1 ? output_string(lower) : output_string(lower / (double) denom)); }
130 };
131 
139 template <typename T, long upper, long denom = 1>
140 class Below : public virtual Validation<T> {
141  public:
143  Below(T v) : Validation<T>(v) {
144  if (*this >= upper / (double) denom)
145  throw boost::program_options::validation_error(boost::program_options::validation_error::invalid_option_value);
146  }
147 
149  static std::string validationString() { return type_string<T>() + u8"<" + (denom == 1 ? output_string(upper) : output_string(upper / (double) denom)); }
150 };
151 
156 template <class V, typename = typename std::enable_if<std::is_base_of<ValidationTag, V>::value>::type>
157 void validate(boost::any &v, const std::vector<std::string> &values, V*, int) {
158  using namespace boost::program_options;
159 
160  // Check that this value hasn't already been assigned:
161  validators::check_first_occurrence(v);
162  // Check that only a single value was given, and get it:
163  std::string s(validators::get_single_string(values));
164 
165  if (std::is_unsigned<typename V::value_type>::value and std::regex_search(s, std::regex("^\\s*-")))
166  throw invalid_option_value(s);
167 
168  try {
169  // First convert to the appropriate type (this will throw if that can't be done):
170  auto val = boost::lexical_cast<typename V::value_type>(s);
171 
172  // The constructor here will throw if validation fails:
173  v = boost::any(V(val));
174  }
175  catch (...) {
176  throw invalid_option_value(s);
177  }
178 }
179 
180 
181 }}
static std::string validationString()
Returns a string representation of this validation object.
Definition: Validation.hpp:38
Validation wrapper for options that have a maximum value.
Definition: Validation.hpp:83
Primary namespace for all Creativity library code.
Definition: config.hpp:4
static std::string validationString()
Returns string representation of this validation.
Definition: Validation.hpp:109
T val_
The stored value.
Definition: Validation.hpp:47
Validation wrapper base class.
Definition: Validation.hpp:29
static std::string validationString()
Returns string representation of this validation.
Definition: Validation.hpp:92
T value_type
The type T that this object validates.
Definition: Validation.hpp:36
static std::string validationString()
Returns string representation of this validation.
Definition: Validation.hpp:129
Below(T v)
Constructor. Throws if v >= upper.
Definition: Validation.hpp:143
Range(T v)
Constructor. Throws if v < min or v > max.
Definition: Validation.hpp:106
Validation(T v)
Constructs with an initial value.
Definition: Validation.hpp:32
Min(T v)
Constructor. Throws if v < min.
Definition: Validation.hpp:64
Validation tag; any Validation class must (ultimately) inherit from this class.
Definition: Validation.hpp:15
static std::string validationString()
Returns string representation of this validation.
Definition: Validation.hpp:70
Validation wrapper for options that have both a minimum and maximum value.
Definition: Validation.hpp:103
void validate(boost::any &v, const std::vector< std::string > &values, V *, int)
Overload of validate for boost to convert from string to a validated data type.
Definition: Validation.hpp:157
Definition: CLI.hpp:5
Validation wrapper for options that have a minimum value.
Definition: Validation.hpp:61
Validation wrapper for options that have a strict inequality boundary that the value must be below...
Definition: Validation.hpp:140
Max(T v)
Constructor. Throws if v > max.
Definition: Validation.hpp:86
static std::string validationString()
Returns string representation of this validation.
Definition: Validation.hpp:149
std::string output_string(T v)
Returns a value converted to a string; in most cases this just passes the value to std::to_string for...
Definition: strings.hpp:25
Validation wrapper for options that have a strict inequality boundary that the value must be above...
Definition: Validation.hpp:120
Above(T v)
Constructor. Throws if v <= lower.
Definition: Validation.hpp:123